porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c
Go to the documentation of this file.
1 /*
2 Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
3 miniaudio - v0.10.41 - 2021-08-15
4 
5 David Reid - mackron@gmail.com
6 
7 Website: https://miniaud.io
8 Documentation: https://miniaud.io/docs
9 GitHub: https://github.com/mackron/miniaudio
10 */
11 #include "miniaudio.h"
12 
13 #ifndef miniaudio_c
14 #define miniaudio_c
15 
16 #include <assert.h>
17 #include <limits.h> /* For INT_MAX */
18 #include <math.h> /* sin(), etc. */
19 
20 #include <stdarg.h>
21 #include <stdio.h>
22 #if !defined(_MSC_VER) && !defined(__DMC__)
23  #include <strings.h> /* For strcasecmp(). */
24  #include <wchar.h> /* For wcslen(), wcsrtombs() */
25 #endif
26 
27 #ifdef MA_WIN32
28 #include <windows.h>
29 #else
30 #include <stdlib.h> /* For malloc(), free(), wcstombs(). */
31 #include <string.h> /* For memset() */
32 #include <sched.h>
33 #include <sys/time.h> /* select() (used for ma_sleep()). */
34 #endif
35 
36 #include <sys/stat.h> /* For fstat(), etc. */
37 
38 #ifdef MA_EMSCRIPTEN
39 #include <emscripten/emscripten.h>
40 #endif
41 
42 #if !defined(MA_64BIT) && !defined(MA_32BIT)
43 #ifdef _WIN32
44 #ifdef _WIN64
45 #define MA_64BIT
46 #else
47 #define MA_32BIT
48 #endif
49 #endif
50 #endif
51 
52 #if !defined(MA_64BIT) && !defined(MA_32BIT)
53 #ifdef __GNUC__
54 #ifdef __LP64__
55 #define MA_64BIT
56 #else
57 #define MA_32BIT
58 #endif
59 #endif
60 #endif
61 
62 #if !defined(MA_64BIT) && !defined(MA_32BIT)
63 #include <stdint.h>
64 #if INTPTR_MAX == INT64_MAX
65 #define MA_64BIT
66 #else
67 #define MA_32BIT
68 #endif
69 #endif
70 
71 /* Architecture Detection */
72 #if defined(__x86_64__) || defined(_M_X64)
73 #define MA_X64
74 #elif defined(__i386) || defined(_M_IX86)
75 #define MA_X86
76 #elif defined(__arm__) || defined(_M_ARM)
77 #define MA_ARM
78 #endif
79 
80 /* Cannot currently support AVX-512 if AVX is disabled. */
81 #if !defined(MA_NO_AVX512) && defined(MA_NO_AVX2)
82 #define MA_NO_AVX512
83 #endif
84 
85 /* Intrinsics Support */
86 #if defined(MA_X64) || defined(MA_X86)
87  #if defined(_MSC_VER) && !defined(__clang__)
88  /* MSVC. */
89  #if _MSC_VER >= 1400 && !defined(MA_NO_SSE2) /* 2005 */
90  #define MA_SUPPORT_SSE2
91  #endif
92  /*#if _MSC_VER >= 1600 && !defined(MA_NO_AVX)*/ /* 2010 */
93  /* #define MA_SUPPORT_AVX*/
94  /*#endif*/
95  #if _MSC_VER >= 1700 && !defined(MA_NO_AVX2) /* 2012 */
96  #define MA_SUPPORT_AVX2
97  #endif
98  #if _MSC_VER >= 1910 && !defined(MA_NO_AVX512) /* 2017 */
99  #define MA_SUPPORT_AVX512
100  #endif
101  #else
102  /* Assume GNUC-style. */
103  #if defined(__SSE2__) && !defined(MA_NO_SSE2)
104  #define MA_SUPPORT_SSE2
105  #endif
106  /*#if defined(__AVX__) && !defined(MA_NO_AVX)*/
107  /* #define MA_SUPPORT_AVX*/
108  /*#endif*/
109  #if defined(__AVX2__) && !defined(MA_NO_AVX2)
110  #define MA_SUPPORT_AVX2
111  #endif
112  #if defined(__AVX512F__) && !defined(MA_NO_AVX512)
113  #define MA_SUPPORT_AVX512
114  #endif
115  #endif
116 
117  /* If at this point we still haven't determined compiler support for the intrinsics just fall back to __has_include. */
118  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
119  #if !defined(MA_SUPPORT_SSE2) && !defined(MA_NO_SSE2) && __has_include(<emmintrin.h>)
120  #define MA_SUPPORT_SSE2
121  #endif
122  /*#if !defined(MA_SUPPORT_AVX) && !defined(MA_NO_AVX) && __has_include(<immintrin.h>)*/
123  /* #define MA_SUPPORT_AVX*/
124  /*#endif*/
125  #if !defined(MA_SUPPORT_AVX2) && !defined(MA_NO_AVX2) && __has_include(<immintrin.h>)
126  #define MA_SUPPORT_AVX2
127  #endif
128  #if !defined(MA_SUPPORT_AVX512) && !defined(MA_NO_AVX512) && __has_include(<zmmintrin.h>)
129  #define MA_SUPPORT_AVX512
130  #endif
131  #endif
132 
133  #if defined(MA_SUPPORT_AVX512)
134  #include <immintrin.h> /* Not a mistake. Intentionally including <immintrin.h> instead of <zmmintrin.h> because otherwise the compiler will complain. */
135  #elif defined(MA_SUPPORT_AVX2) || defined(MA_SUPPORT_AVX)
136  #include <immintrin.h>
137  #elif defined(MA_SUPPORT_SSE2)
138  #include <emmintrin.h>
139  #endif
140 #endif
141 
142 #if defined(MA_ARM)
143  #if !defined(MA_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
144  #define MA_SUPPORT_NEON
145  #endif
146 
147  /* Fall back to looking for the #include file. */
148  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
149  #if !defined(MA_SUPPORT_NEON) && !defined(MA_NO_NEON) && __has_include(<arm_neon.h>)
150  #define MA_SUPPORT_NEON
151  #endif
152  #endif
153 
154  #if defined(MA_SUPPORT_NEON)
155  #include <arm_neon.h>
156  #endif
157 #endif
158 
159 /* Begin globally disabled warnings. */
160 #if defined(_MSC_VER)
161  #pragma warning(push)
162  #pragma warning(disable:4752) /* found Intel(R) Advanced Vector Extensions; consider using /arch:AVX */
163 #endif
164 
165 #if defined(MA_X64) || defined(MA_X86)
166  #if defined(_MSC_VER) && !defined(__clang__)
167  #if _MSC_VER >= 1400
168  #include <intrin.h>
169  static MA_INLINE void ma_cpuid(int info[4], int fid)
170  {
171  __cpuid(info, fid);
172  }
173  #else
174  #define MA_NO_CPUID
175  #endif
176 
177  #if _MSC_VER >= 1600 && (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219)
178  static MA_INLINE unsigned __int64 ma_xgetbv(int reg)
179  {
180  return _xgetbv(reg);
181  }
182  #else
183  #define MA_NO_XGETBV
184  #endif
185  #elif (defined(__GNUC__) || defined(__clang__)) && !defined(MA_ANDROID)
186  static MA_INLINE void ma_cpuid(int info[4], int fid)
187  {
188  /*
189  It looks like the -fPIC option uses the ebx register which GCC complains about. We can work around this by just using a different register, the
190  specific register of which I'm letting the compiler decide on. The "k" prefix is used to specify a 32-bit register. The {...} syntax is for
191  supporting different assembly dialects.
192 
193  What's basically happening is that we're saving and restoring the ebx register manually.
194  */
195  #if defined(DRFLAC_X86) && defined(__PIC__)
196  __asm__ __volatile__ (
197  "xchg{l} {%%}ebx, %k1;"
198  "cpuid;"
199  "xchg{l} {%%}ebx, %k1;"
200  : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
201  );
202  #else
203  __asm__ __volatile__ (
204  "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
205  );
206  #endif
207  }
208 
209  static MA_INLINE ma_uint64 ma_xgetbv(int reg)
210  {
211  unsigned int hi;
212  unsigned int lo;
213 
214  __asm__ __volatile__ (
215  "xgetbv" : "=a"(lo), "=d"(hi) : "c"(reg)
216  );
217 
218  return ((ma_uint64)hi << 32) | (ma_uint64)lo;
219  }
220  #else
221  #define MA_NO_CPUID
222  #define MA_NO_XGETBV
223  #endif
224 #else
225  #define MA_NO_CPUID
226  #define MA_NO_XGETBV
227 #endif
228 
230 {
231 #if defined(MA_SUPPORT_SSE2)
232  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_SSE2)
233  #if defined(MA_X64)
234  return MA_TRUE; /* 64-bit targets always support SSE2. */
235  #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
236  return MA_TRUE; /* If the compiler is allowed to freely generate SSE2 code we can assume support. */
237  #else
238  #if defined(MA_NO_CPUID)
239  return MA_FALSE;
240  #else
241  int info[4];
242  ma_cpuid(info, 1);
243  return (info[3] & (1 << 26)) != 0;
244  #endif
245  #endif
246  #else
247  return MA_FALSE; /* SSE2 is only supported on x86 and x64 architectures. */
248  #endif
249 #else
250  return MA_FALSE; /* No compiler support. */
251 #endif
252 }
253 
254 #if 0
255 static MA_INLINE ma_bool32 ma_has_avx()
256 {
257 #if defined(MA_SUPPORT_AVX)
258  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX)
259  #if defined(_AVX_) || defined(__AVX__)
260  return MA_TRUE; /* If the compiler is allowed to freely generate AVX code we can assume support. */
261  #else
262  /* AVX requires both CPU and OS support. */
263  #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
264  return MA_FALSE;
265  #else
266  int info[4];
267  ma_cpuid(info, 1);
268  if (((info[2] & (1 << 27)) != 0) && ((info[2] & (1 << 28)) != 0)) {
269  ma_uint64 xrc = ma_xgetbv(0);
270  if ((xrc & 0x06) == 0x06) {
271  return MA_TRUE;
272  } else {
273  return MA_FALSE;
274  }
275  } else {
276  return MA_FALSE;
277  }
278  #endif
279  #endif
280  #else
281  return MA_FALSE; /* AVX is only supported on x86 and x64 architectures. */
282  #endif
283 #else
284  return MA_FALSE; /* No compiler support. */
285 #endif
286 }
287 #endif
288 
290 {
291 #if defined(MA_SUPPORT_AVX2)
292  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX2)
293  #if defined(_AVX2_) || defined(__AVX2__)
294  return MA_TRUE; /* If the compiler is allowed to freely generate AVX2 code we can assume support. */
295  #else
296  /* AVX2 requires both CPU and OS support. */
297  #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
298  return MA_FALSE;
299  #else
300  int info1[4];
301  int info7[4];
302  ma_cpuid(info1, 1);
303  ma_cpuid(info7, 7);
304  if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 5)) != 0)) {
305  ma_uint64 xrc = ma_xgetbv(0);
306  if ((xrc & 0x06) == 0x06) {
307  return MA_TRUE;
308  } else {
309  return MA_FALSE;
310  }
311  } else {
312  return MA_FALSE;
313  }
314  #endif
315  #endif
316  #else
317  return MA_FALSE; /* AVX2 is only supported on x86 and x64 architectures. */
318  #endif
319 #else
320  return MA_FALSE; /* No compiler support. */
321 #endif
322 }
323 
325 {
326 #if defined(MA_SUPPORT_AVX512)
327  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX512)
328  #if defined(__AVX512F__)
329  return MA_TRUE; /* If the compiler is allowed to freely generate AVX-512F code we can assume support. */
330  #else
331  /* AVX-512 requires both CPU and OS support. */
332  #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
333  return MA_FALSE;
334  #else
335  int info1[4];
336  int info7[4];
337  ma_cpuid(info1, 1);
338  ma_cpuid(info7, 7);
339  if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 16)) != 0)) {
340  ma_uint64 xrc = ma_xgetbv(0);
341  if ((xrc & 0xE6) == 0xE6) {
342  return MA_TRUE;
343  } else {
344  return MA_FALSE;
345  }
346  } else {
347  return MA_FALSE;
348  }
349  #endif
350  #endif
351  #else
352  return MA_FALSE; /* AVX-512F is only supported on x86 and x64 architectures. */
353  #endif
354 #else
355  return MA_FALSE; /* No compiler support. */
356 #endif
357 }
358 
360 {
361 #if defined(MA_SUPPORT_NEON)
362  #if defined(MA_ARM) && !defined(MA_NO_NEON)
363  #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
364  return MA_TRUE; /* If the compiler is allowed to freely generate NEON code we can assume support. */
365  #else
366  /* TODO: Runtime check. */
367  return MA_FALSE;
368  #endif
369  #else
370  return MA_FALSE; /* NEON is only supported on ARM architectures. */
371  #endif
372 #else
373  return MA_FALSE; /* No compiler support. */
374 #endif
375 }
376 
377 #define MA_SIMD_NONE 0
378 #define MA_SIMD_SSE2 1
379 #define MA_SIMD_AVX2 2
380 #define MA_SIMD_NEON 3
381 
382 #ifndef MA_PREFERRED_SIMD
383  # if defined(MA_SUPPORT_SSE2) && defined(MA_PREFER_SSE2)
384  #define MA_PREFERRED_SIMD MA_SIMD_SSE2
385  #elif defined(MA_SUPPORT_AVX2) && defined(MA_PREFER_AVX2)
386  #define MA_PREFERRED_SIMD MA_SIMD_AVX2
387  #elif defined(MA_SUPPORT_NEON) && defined(MA_PREFER_NEON)
388  #define MA_PREFERRED_SIMD MA_SIMD_NEON
389  #else
390  #define MA_PREFERRED_SIMD MA_SIMD_NONE
391  #endif
392 #endif
393 
394 #if defined(__has_builtin)
395  #define MA_COMPILER_HAS_BUILTIN(x) __has_builtin(x)
396 #else
397  #define MA_COMPILER_HAS_BUILTIN(x) 0
398 #endif
399 
400 #ifndef MA_ASSUME
401  #if MA_COMPILER_HAS_BUILTIN(__builtin_assume)
402  #define MA_ASSUME(x) __builtin_assume(x)
403  #elif MA_COMPILER_HAS_BUILTIN(__builtin_unreachable)
404  #define MA_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0)
405  #elif defined(_MSC_VER)
406  #define MA_ASSUME(x) __assume(x)
407  #else
408  #define MA_ASSUME(x) while(0)
409  #endif
410 #endif
411 
412 #ifndef MA_RESTRICT
413  #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
414  #define MA_RESTRICT __restrict
415  #else
416  #define MA_RESTRICT
417  #endif
418 #endif
419 
420 #if defined(_MSC_VER) && _MSC_VER >= 1400
421  #define MA_HAS_BYTESWAP16_INTRINSIC
422  #define MA_HAS_BYTESWAP32_INTRINSIC
423  #define MA_HAS_BYTESWAP64_INTRINSIC
424 #elif defined(__clang__)
425  #if MA_COMPILER_HAS_BUILTIN(__builtin_bswap16)
426  #define MA_HAS_BYTESWAP16_INTRINSIC
427  #endif
428  #if MA_COMPILER_HAS_BUILTIN(__builtin_bswap32)
429  #define MA_HAS_BYTESWAP32_INTRINSIC
430  #endif
431  #if MA_COMPILER_HAS_BUILTIN(__builtin_bswap64)
432  #define MA_HAS_BYTESWAP64_INTRINSIC
433  #endif
434 #elif defined(__GNUC__)
435  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
436  #define MA_HAS_BYTESWAP32_INTRINSIC
437  #define MA_HAS_BYTESWAP64_INTRINSIC
438  #endif
439  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
440  #define MA_HAS_BYTESWAP16_INTRINSIC
441  #endif
442 #endif
443 
444 
446 {
447 #if defined(MA_X86) || defined(MA_X64)
448  return MA_TRUE;
449 #else
450  int n = 1;
451  return (*(char*)&n) == 1;
452 #endif
453 }
454 
456 {
457  return !ma_is_little_endian();
458 }
459 
460 
462 {
463 #ifdef MA_HAS_BYTESWAP32_INTRINSIC
464  #if defined(_MSC_VER)
465  return _byteswap_ulong(n);
466  #elif defined(__GNUC__) || defined(__clang__)
467  #if defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(MA_64BIT) /* <-- 64-bit inline assembly has not been tested, so disabling for now. */
468  /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
469  ma_uint32 r;
470  __asm__ __volatile__ (
471  #if defined(MA_64BIT)
472  "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n) /* <-- This is untested. If someone in the community could test this, that would be appreciated! */
473  #else
474  "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
475  #endif
476  );
477  return r;
478  #else
479  return __builtin_bswap32(n);
480  #endif
481  #else
482  #error "This compiler does not support the byte swap intrinsic."
483  #endif
484 #else
485  return ((n & 0xFF000000) >> 24) |
486  ((n & 0x00FF0000) >> 8) |
487  ((n & 0x0000FF00) << 8) |
488  ((n & 0x000000FF) << 24);
489 #endif
490 }
491 
492 
493 #if !defined(MA_EMSCRIPTEN)
494 #ifdef MA_WIN32
495 static void ma_sleep__win32(ma_uint32 milliseconds)
496 {
497  Sleep((DWORD)milliseconds);
498 }
499 #endif
500 #ifdef MA_POSIX
501 static void ma_sleep__posix(ma_uint32 milliseconds)
502 {
503 #ifdef MA_EMSCRIPTEN
504  (void)milliseconds;
505  MA_ASSERT(MA_FALSE); /* The Emscripten build should never sleep. */
506 #else
507  #if _POSIX_C_SOURCE >= 199309L
508  struct timespec ts;
509  ts.tv_sec = milliseconds / 1000;
510  ts.tv_nsec = milliseconds % 1000 * 1000000;
511  nanosleep(&ts, NULL);
512  #else
513  struct timeval tv;
514  tv.tv_sec = milliseconds / 1000;
515  tv.tv_usec = milliseconds % 1000 * 1000;
516  select(0, NULL, NULL, NULL, &tv);
517  #endif
518 #endif
519 }
520 #endif
521 
522 static void ma_sleep(ma_uint32 milliseconds)
523 {
524 #ifdef MA_WIN32
525  ma_sleep__win32(milliseconds);
526 #endif
527 #ifdef MA_POSIX
528  ma_sleep__posix(milliseconds);
529 #endif
530 }
531 #endif
532 
533 static MA_INLINE void ma_yield()
534 {
535 #if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
536  /* x86/x64 */
537  #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)) && !defined(__clang__)
538  #if _MSC_VER >= 1400
539  _mm_pause();
540  #else
541  #if defined(__DMC__)
542  /* Digital Mars does not recognize the PAUSE opcode. Fall back to NOP. */
543  __asm nop;
544  #else
545  __asm pause;
546  #endif
547  #endif
548  #else
549  __asm__ __volatile__ ("pause");
550  #endif
551 #elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || (defined(_M_ARM) && _M_ARM >= 7) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
552  /* ARM */
553  #if defined(_MSC_VER)
554  /* Apparently there is a __yield() intrinsic that's compatible with ARM, but I cannot find documentation for it nor can I find where it's declared. */
555  __yield();
556  #else
557  __asm__ __volatile__ ("yield"); /* ARMv6K/ARMv6T2 and above. */
558  #endif
559 #else
560  /* Unknown or unsupported architecture. No-op. */
561 #endif
562 }
563 
564 
565 
566 #ifndef MA_COINIT_VALUE
567 #define MA_COINIT_VALUE 0 /* 0 = COINIT_MULTITHREADED */
568 #endif
569 
570 
571 #ifndef MA_FLT_MAX
572  #ifdef FLT_MAX
573  #define MA_FLT_MAX FLT_MAX
574  #else
575  #define MA_FLT_MAX 3.402823466e+38F
576  #endif
577 #endif
578 
579 
580 #ifndef MA_PI
581 #define MA_PI 3.14159265358979323846264f
582 #endif
583 #ifndef MA_PI_D
584 #define MA_PI_D 3.14159265358979323846264
585 #endif
586 #ifndef MA_TAU
587 #define MA_TAU 6.28318530717958647693f
588 #endif
589 #ifndef MA_TAU_D
590 #define MA_TAU_D 6.28318530717958647693
591 #endif
592 
593 
594 /* The default format when ma_format_unknown (0) is requested when initializing a device. */
595 #ifndef MA_DEFAULT_FORMAT
596 #define MA_DEFAULT_FORMAT ma_format_f32
597 #endif
598 
599 /* The default channel count to use when 0 is used when initializing a device. */
600 #ifndef MA_DEFAULT_CHANNELS
601 #define MA_DEFAULT_CHANNELS 2
602 #endif
603 
604 /* The default sample rate to use when 0 is used when initializing a device. */
605 #ifndef MA_DEFAULT_SAMPLE_RATE
606 #define MA_DEFAULT_SAMPLE_RATE 48000
607 #endif
608 
609 /* Default periods when none is specified in ma_device_init(). More periods means more work on the CPU. */
610 #ifndef MA_DEFAULT_PERIODS
611 #define MA_DEFAULT_PERIODS 3
612 #endif
613 
614 /* The default period size in milliseconds for low latency mode. */
615 #ifndef MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY
616 #define MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY 10
617 #endif
618 
619 /* The default buffer size in milliseconds for conservative mode. */
620 #ifndef MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE
621 #define MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE 100
622 #endif
623 
624 /* The default LPF filter order for linear resampling. Note that this is clamped to MA_MAX_FILTER_ORDER. */
625 #ifndef MA_DEFAULT_RESAMPLER_LPF_ORDER
626  #if MA_MAX_FILTER_ORDER >= 4
627  #define MA_DEFAULT_RESAMPLER_LPF_ORDER 4
628  #else
629  #define MA_DEFAULT_RESAMPLER_LPF_ORDER MA_MAX_FILTER_ORDER
630  #endif
631 #endif
632 
633 
634 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
635  #pragma GCC diagnostic push
636  #pragma GCC diagnostic ignored "-Wunused-variable"
637 #endif
638 
639 /* Standard sample rates, in order of priority. */
643 
647 
652 
656 
659 };
660 
662 {
663  ma_uint32 iSampleRate;
664 
665  for (iSampleRate = 0; iSampleRate < sizeof(g_maStandardSampleRatePriorities) / sizeof(g_maStandardSampleRatePriorities[0]); iSampleRate += 1) {
666  if (g_maStandardSampleRatePriorities[iSampleRate] == sampleRate) {
667  return MA_TRUE;
668  }
669  }
670 
671  /* Getting here means the sample rate is not supported. */
672  return MA_FALSE;
673 }
674 
675 
677  ma_format_s16, /* Most common */
679 
680  /*ma_format_s24_32,*/ /* Clean alignment */
682 
683  ma_format_s24, /* Unclean alignment */
684 
685  ma_format_u8 /* Low quality */
686 };
687 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
688  #pragma GCC diagnostic pop
689 #endif
690 
691 
692 MA_API void ma_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* pRevision)
693 {
694  if (pMajor) {
695  *pMajor = MA_VERSION_MAJOR;
696  }
697 
698  if (pMinor) {
699  *pMinor = MA_VERSION_MINOR;
700  }
701 
702  if (pRevision) {
703  *pRevision = MA_VERSION_REVISION;
704  }
705 }
706 
707 MA_API const char* ma_version_string(void)
708 {
709  return MA_VERSION_STRING;
710 }
711 
712 
713 /******************************************************************************
714 
715 Standard Library Stuff
716 
717 ******************************************************************************/
718 #ifndef MA_MALLOC
719 #ifdef MA_WIN32
720 #define MA_MALLOC(sz) HeapAlloc(GetProcessHeap(), 0, (sz))
721 #else
722 #define MA_MALLOC(sz) malloc((sz))
723 #endif
724 #endif
725 
726 #ifndef MA_REALLOC
727 #ifdef MA_WIN32
728 #define MA_REALLOC(p, sz) (((sz) > 0) ? ((p) ? HeapReAlloc(GetProcessHeap(), 0, (p), (sz)) : HeapAlloc(GetProcessHeap(), 0, (sz))) : ((VOID*)(size_t)(HeapFree(GetProcessHeap(), 0, (p)) & 0)))
729 #else
730 #define MA_REALLOC(p, sz) realloc((p), (sz))
731 #endif
732 #endif
733 
734 #ifndef MA_FREE
735 #ifdef MA_WIN32
736 #define MA_FREE(p) HeapFree(GetProcessHeap(), 0, (p))
737 #else
738 #define MA_FREE(p) free((p))
739 #endif
740 #endif
741 
742 #ifndef MA_ZERO_MEMORY
743 #ifdef MA_WIN32
744 #define MA_ZERO_MEMORY(p, sz) ZeroMemory((p), (sz))
745 #else
746 #define MA_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
747 #endif
748 #endif
749 
750 #ifndef MA_COPY_MEMORY
751 #ifdef MA_WIN32
752 #define MA_COPY_MEMORY(dst, src, sz) CopyMemory((dst), (src), (sz))
753 #else
754 #define MA_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
755 #endif
756 #endif
757 
758 #ifndef MA_MOVE_MEMORY
759 #ifdef MA_WIN32
760 #define MA_MOVE_MEMORY(dst, src, sz) MoveMemory((dst), (src), (sz))
761 #else
762 #define MA_MOVE_MEMORY(dst, src, sz) memmove((dst), (src), (sz))
763 #endif
764 #endif
765 
766 #ifndef MA_ASSERT
767 #ifdef MA_WIN32
768 #define MA_ASSERT(condition) assert(condition)
769 #else
770 #define MA_ASSERT(condition) assert(condition)
771 #endif
772 #endif
773 
774 #define MA_ZERO_OBJECT(p) MA_ZERO_MEMORY((p), sizeof(*(p)))
775 
776 #define ma_countof(x) (sizeof(x) / sizeof(x[0]))
777 #define ma_max(x, y) (((x) > (y)) ? (x) : (y))
778 #define ma_min(x, y) (((x) < (y)) ? (x) : (y))
779 #define ma_abs(x) (((x) > 0) ? (x) : -(x))
780 #define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
781 #define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
782 #define ma_align(x, a) ((x + (a-1)) & ~(a-1))
783 #define ma_align_64(x) ma_align(x, 8)
784 
785 #define ma_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / ma_get_bytes_per_sample(format) / (channels))
786 
787 static MA_INLINE double ma_sind(double x)
788 {
789  /* TODO: Implement custom sin(x). */
790  return sin(x);
791 }
792 
793 static MA_INLINE double ma_expd(double x)
794 {
795  /* TODO: Implement custom exp(x). */
796  return exp(x);
797 }
798 
799 static MA_INLINE double ma_logd(double x)
800 {
801  /* TODO: Implement custom log(x). */
802  return log(x);
803 }
804 
805 static MA_INLINE double ma_powd(double x, double y)
806 {
807  /* TODO: Implement custom pow(x, y). */
808  return pow(x, y);
809 }
810 
811 static MA_INLINE double ma_sqrtd(double x)
812 {
813  /* TODO: Implement custom sqrt(x). */
814  return sqrt(x);
815 }
816 
817 
818 static MA_INLINE double ma_cosd(double x)
819 {
820  return ma_sind((MA_PI_D*0.5) - x);
821 }
822 
823 static MA_INLINE double ma_log10d(double x)
824 {
825  return ma_logd(x) * 0.43429448190325182765;
826 }
827 
828 static MA_INLINE float ma_powf(float x, float y)
829 {
830  return (float)ma_powd((double)x, (double)y);
831 }
832 
833 static MA_INLINE float ma_log10f(float x)
834 {
835  return (float)ma_log10d((double)x);
836 }
837 
838 
839 static MA_INLINE double ma_degrees_to_radians(double degrees)
840 {
841  return degrees * 0.01745329252;
842 }
843 
844 static MA_INLINE double ma_radians_to_degrees(double radians)
845 {
846  return radians * 57.295779512896;
847 }
848 
849 static MA_INLINE float ma_degrees_to_radians_f(float degrees)
850 {
851  return degrees * 0.01745329252f;
852 }
853 
854 static MA_INLINE float ma_radians_to_degrees_f(float radians)
855 {
856  return radians * 57.295779512896f;
857 }
858 
859 
860 /*
861 Return Values:
862  0: Success
863  22: EINVAL
864  34: ERANGE
865 
866 Not using symbolic constants for errors because I want to avoid #including errno.h
867 */
868 MA_API int ma_strcpy_s(char* dst, size_t dstSizeInBytes, const char* src)
869 {
870  size_t i;
871 
872  if (dst == 0) {
873  return 22;
874  }
875  if (dstSizeInBytes == 0) {
876  return 34;
877  }
878  if (src == 0) {
879  dst[0] = '\0';
880  return 22;
881  }
882 
883  for (i = 0; i < dstSizeInBytes && src[i] != '\0'; ++i) {
884  dst[i] = src[i];
885  }
886 
887  if (i < dstSizeInBytes) {
888  dst[i] = '\0';
889  return 0;
890  }
891 
892  dst[0] = '\0';
893  return 34;
894 }
895 
896 MA_API int ma_wcscpy_s(wchar_t* dst, size_t dstCap, const wchar_t* src)
897 {
898  size_t i;
899 
900  if (dst == 0) {
901  return 22;
902  }
903  if (dstCap == 0) {
904  return 34;
905  }
906  if (src == 0) {
907  dst[0] = '\0';
908  return 22;
909  }
910 
911  for (i = 0; i < dstCap && src[i] != '\0'; ++i) {
912  dst[i] = src[i];
913  }
914 
915  if (i < dstCap) {
916  dst[i] = '\0';
917  return 0;
918  }
919 
920  dst[0] = '\0';
921  return 34;
922 }
923 
924 
925 MA_API int ma_strncpy_s(char* dst, size_t dstSizeInBytes, const char* src, size_t count)
926 {
927  size_t maxcount;
928  size_t i;
929 
930  if (dst == 0) {
931  return 22;
932  }
933  if (dstSizeInBytes == 0) {
934  return 34;
935  }
936  if (src == 0) {
937  dst[0] = '\0';
938  return 22;
939  }
940 
941  maxcount = count;
942  if (count == ((size_t)-1) || count >= dstSizeInBytes) { /* -1 = _TRUNCATE */
943  maxcount = dstSizeInBytes - 1;
944  }
945 
946  for (i = 0; i < maxcount && src[i] != '\0'; ++i) {
947  dst[i] = src[i];
948  }
949 
950  if (src[i] == '\0' || i == count || count == ((size_t)-1)) {
951  dst[i] = '\0';
952  return 0;
953  }
954 
955  dst[0] = '\0';
956  return 34;
957 }
958 
959 MA_API int ma_strcat_s(char* dst, size_t dstSizeInBytes, const char* src)
960 {
961  char* dstorig;
962 
963  if (dst == 0) {
964  return 22;
965  }
966  if (dstSizeInBytes == 0) {
967  return 34;
968  }
969  if (src == 0) {
970  dst[0] = '\0';
971  return 22;
972  }
973 
974  dstorig = dst;
975 
976  while (dstSizeInBytes > 0 && dst[0] != '\0') {
977  dst += 1;
978  dstSizeInBytes -= 1;
979  }
980 
981  if (dstSizeInBytes == 0) {
982  return 22; /* Unterminated. */
983  }
984 
985 
986  while (dstSizeInBytes > 0 && src[0] != '\0') {
987  *dst++ = *src++;
988  dstSizeInBytes -= 1;
989  }
990 
991  if (dstSizeInBytes > 0) {
992  dst[0] = '\0';
993  } else {
994  dstorig[0] = '\0';
995  return 34;
996  }
997 
998  return 0;
999 }
1000 
1001 MA_API int ma_strncat_s(char* dst, size_t dstSizeInBytes, const char* src, size_t count)
1002 {
1003  char* dstorig;
1004 
1005  if (dst == 0) {
1006  return 22;
1007  }
1008  if (dstSizeInBytes == 0) {
1009  return 34;
1010  }
1011  if (src == 0) {
1012  return 22;
1013  }
1014 
1015  dstorig = dst;
1016 
1017  while (dstSizeInBytes > 0 && dst[0] != '\0') {
1018  dst += 1;
1019  dstSizeInBytes -= 1;
1020  }
1021 
1022  if (dstSizeInBytes == 0) {
1023  return 22; /* Unterminated. */
1024  }
1025 
1026 
1027  if (count == ((size_t)-1)) { /* _TRUNCATE */
1028  count = dstSizeInBytes - 1;
1029  }
1030 
1031  while (dstSizeInBytes > 0 && src[0] != '\0' && count > 0) {
1032  *dst++ = *src++;
1033  dstSizeInBytes -= 1;
1034  count -= 1;
1035  }
1036 
1037  if (dstSizeInBytes > 0) {
1038  dst[0] = '\0';
1039  } else {
1040  dstorig[0] = '\0';
1041  return 34;
1042  }
1043 
1044  return 0;
1045 }
1046 
1047 MA_API int ma_itoa_s(int value, char* dst, size_t dstSizeInBytes, int radix)
1048 {
1049  int sign;
1050  unsigned int valueU;
1051  char* dstEnd;
1052 
1053  if (dst == NULL || dstSizeInBytes == 0) {
1054  return 22;
1055  }
1056  if (radix < 2 || radix > 36) {
1057  dst[0] = '\0';
1058  return 22;
1059  }
1060 
1061  sign = (value < 0 && radix == 10) ? -1 : 1; /* The negative sign is only used when the base is 10. */
1062 
1063  if (value < 0) {
1064  valueU = -value;
1065  } else {
1066  valueU = value;
1067  }
1068 
1069  dstEnd = dst;
1070  do
1071  {
1072  int remainder = valueU % radix;
1073  if (remainder > 9) {
1074  *dstEnd = (char)((remainder - 10) + 'a');
1075  } else {
1076  *dstEnd = (char)(remainder + '0');
1077  }
1078 
1079  dstEnd += 1;
1080  dstSizeInBytes -= 1;
1081  valueU /= radix;
1082  } while (dstSizeInBytes > 0 && valueU > 0);
1083 
1084  if (dstSizeInBytes == 0) {
1085  dst[0] = '\0';
1086  return 22; /* Ran out of room in the output buffer. */
1087  }
1088 
1089  if (sign < 0) {
1090  *dstEnd++ = '-';
1091  dstSizeInBytes -= 1;
1092  }
1093 
1094  if (dstSizeInBytes == 0) {
1095  dst[0] = '\0';
1096  return 22; /* Ran out of room in the output buffer. */
1097  }
1098 
1099  *dstEnd = '\0';
1100 
1101 
1102  /* At this point the string will be reversed. */
1103  dstEnd -= 1;
1104  while (dst < dstEnd) {
1105  char temp = *dst;
1106  *dst = *dstEnd;
1107  *dstEnd = temp;
1108 
1109  dst += 1;
1110  dstEnd -= 1;
1111  }
1112 
1113  return 0;
1114 }
1115 
1116 MA_API int ma_strcmp(const char* str1, const char* str2)
1117 {
1118  if (str1 == str2) return 0;
1119 
1120  /* These checks differ from the standard implementation. It's not important, but I prefer it just for sanity. */
1121  if (str1 == NULL) return -1;
1122  if (str2 == NULL) return 1;
1123 
1124  for (;;) {
1125  if (str1[0] == '\0') {
1126  break;
1127  }
1128  if (str1[0] != str2[0]) {
1129  break;
1130  }
1131 
1132  str1 += 1;
1133  str2 += 1;
1134  }
1135 
1136  return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
1137 }
1138 
1139 MA_API int ma_strappend(char* dst, size_t dstSize, const char* srcA, const char* srcB)
1140 {
1141  int result;
1142 
1143  result = ma_strncpy_s(dst, dstSize, srcA, (size_t)-1);
1144  if (result != 0) {
1145  return result;
1146  }
1147 
1148  result = ma_strncat_s(dst, dstSize, srcB, (size_t)-1);
1149  if (result != 0) {
1150  return result;
1151  }
1152 
1153  return result;
1154 }
1155 
1156 MA_API char* ma_copy_string(const char* src, const ma_allocation_callbacks* pAllocationCallbacks)
1157 {
1158  size_t sz = strlen(src)+1;
1159  char* dst = (char*)ma_malloc(sz, pAllocationCallbacks);
1160  if (dst == NULL) {
1161  return NULL;
1162  }
1163 
1164  ma_strcpy_s(dst, sz, src);
1165 
1166  return dst;
1167 }
1168 
1169 MA_API wchar_t* ma_copy_string_w(const wchar_t* src, const ma_allocation_callbacks* pAllocationCallbacks)
1170 {
1171  size_t sz = wcslen(src)+1;
1172  wchar_t* dst = (wchar_t*)ma_malloc(sz * sizeof(*dst), pAllocationCallbacks);
1173  if (dst == NULL) {
1174  return NULL;
1175  }
1176 
1177  ma_wcscpy_s(dst, sz, src);
1178 
1179  return dst;
1180 }
1181 
1182 
1183 #include <errno.h>
1185 {
1186  switch (e)
1187  {
1188  case 0: return MA_SUCCESS;
1189  #ifdef EPERM
1190  case EPERM: return MA_INVALID_OPERATION;
1191  #endif
1192  #ifdef ENOENT
1193  case ENOENT: return MA_DOES_NOT_EXIST;
1194  #endif
1195  #ifdef ESRCH
1196  case ESRCH: return MA_DOES_NOT_EXIST;
1197  #endif
1198  #ifdef EINTR
1199  case EINTR: return MA_INTERRUPT;
1200  #endif
1201  #ifdef EIO
1202  case EIO: return MA_IO_ERROR;
1203  #endif
1204  #ifdef ENXIO
1205  case ENXIO: return MA_DOES_NOT_EXIST;
1206  #endif
1207  #ifdef E2BIG
1208  case E2BIG: return MA_INVALID_ARGS;
1209  #endif
1210  #ifdef ENOEXEC
1211  case ENOEXEC: return MA_INVALID_FILE;
1212  #endif
1213  #ifdef EBADF
1214  case EBADF: return MA_INVALID_FILE;
1215  #endif
1216  #ifdef ECHILD
1217  case ECHILD: return MA_ERROR;
1218  #endif
1219  #ifdef EAGAIN
1220  case EAGAIN: return MA_UNAVAILABLE;
1221  #endif
1222  #ifdef ENOMEM
1223  case ENOMEM: return MA_OUT_OF_MEMORY;
1224  #endif
1225  #ifdef EACCES
1226  case EACCES: return MA_ACCESS_DENIED;
1227  #endif
1228  #ifdef EFAULT
1229  case EFAULT: return MA_BAD_ADDRESS;
1230  #endif
1231  #ifdef ENOTBLK
1232  case ENOTBLK: return MA_ERROR;
1233  #endif
1234  #ifdef EBUSY
1235  case EBUSY: return MA_BUSY;
1236  #endif
1237  #ifdef EEXIST
1238  case EEXIST: return MA_ALREADY_EXISTS;
1239  #endif
1240  #ifdef EXDEV
1241  case EXDEV: return MA_ERROR;
1242  #endif
1243  #ifdef ENODEV
1244  case ENODEV: return MA_DOES_NOT_EXIST;
1245  #endif
1246  #ifdef ENOTDIR
1247  case ENOTDIR: return MA_NOT_DIRECTORY;
1248  #endif
1249  #ifdef EISDIR
1250  case EISDIR: return MA_IS_DIRECTORY;
1251  #endif
1252  #ifdef EINVAL
1253  case EINVAL: return MA_INVALID_ARGS;
1254  #endif
1255  #ifdef ENFILE
1256  case ENFILE: return MA_TOO_MANY_OPEN_FILES;
1257  #endif
1258  #ifdef EMFILE
1259  case EMFILE: return MA_TOO_MANY_OPEN_FILES;
1260  #endif
1261  #ifdef ENOTTY
1262  case ENOTTY: return MA_INVALID_OPERATION;
1263  #endif
1264  #ifdef ETXTBSY
1265  case ETXTBSY: return MA_BUSY;
1266  #endif
1267  #ifdef EFBIG
1268  case EFBIG: return MA_TOO_BIG;
1269  #endif
1270  #ifdef ENOSPC
1271  case ENOSPC: return MA_NO_SPACE;
1272  #endif
1273  #ifdef ESPIPE
1274  case ESPIPE: return MA_BAD_SEEK;
1275  #endif
1276  #ifdef EROFS
1277  case EROFS: return MA_ACCESS_DENIED;
1278  #endif
1279  #ifdef EMLINK
1280  case EMLINK: return MA_TOO_MANY_LINKS;
1281  #endif
1282  #ifdef EPIPE
1283  case EPIPE: return MA_BAD_PIPE;
1284  #endif
1285  #ifdef EDOM
1286  case EDOM: return MA_OUT_OF_RANGE;
1287  #endif
1288  #ifdef ERANGE
1289  case ERANGE: return MA_OUT_OF_RANGE;
1290  #endif
1291  #ifdef EDEADLK
1292  case EDEADLK: return MA_DEADLOCK;
1293  #endif
1294  #ifdef ENAMETOOLONG
1295  case ENAMETOOLONG: return MA_PATH_TOO_LONG;
1296  #endif
1297  #ifdef ENOLCK
1298  case ENOLCK: return MA_ERROR;
1299  #endif
1300  #ifdef ENOSYS
1301  case ENOSYS: return MA_NOT_IMPLEMENTED;
1302  #endif
1303  #ifdef ENOTEMPTY
1304  case ENOTEMPTY: return MA_DIRECTORY_NOT_EMPTY;
1305  #endif
1306  #ifdef ELOOP
1307  case ELOOP: return MA_TOO_MANY_LINKS;
1308  #endif
1309  #ifdef ENOMSG
1310  case ENOMSG: return MA_NO_MESSAGE;
1311  #endif
1312  #ifdef EIDRM
1313  case EIDRM: return MA_ERROR;
1314  #endif
1315  #ifdef ECHRNG
1316  case ECHRNG: return MA_ERROR;
1317  #endif
1318  #ifdef EL2NSYNC
1319  case EL2NSYNC: return MA_ERROR;
1320  #endif
1321  #ifdef EL3HLT
1322  case EL3HLT: return MA_ERROR;
1323  #endif
1324  #ifdef EL3RST
1325  case EL3RST: return MA_ERROR;
1326  #endif
1327  #ifdef ELNRNG
1328  case ELNRNG: return MA_OUT_OF_RANGE;
1329  #endif
1330  #ifdef EUNATCH
1331  case EUNATCH: return MA_ERROR;
1332  #endif
1333  #ifdef ENOCSI
1334  case ENOCSI: return MA_ERROR;
1335  #endif
1336  #ifdef EL2HLT
1337  case EL2HLT: return MA_ERROR;
1338  #endif
1339  #ifdef EBADE
1340  case EBADE: return MA_ERROR;
1341  #endif
1342  #ifdef EBADR
1343  case EBADR: return MA_ERROR;
1344  #endif
1345  #ifdef EXFULL
1346  case EXFULL: return MA_ERROR;
1347  #endif
1348  #ifdef ENOANO
1349  case ENOANO: return MA_ERROR;
1350  #endif
1351  #ifdef EBADRQC
1352  case EBADRQC: return MA_ERROR;
1353  #endif
1354  #ifdef EBADSLT
1355  case EBADSLT: return MA_ERROR;
1356  #endif
1357  #ifdef EBFONT
1358  case EBFONT: return MA_INVALID_FILE;
1359  #endif
1360  #ifdef ENOSTR
1361  case ENOSTR: return MA_ERROR;
1362  #endif
1363  #ifdef ENODATA
1364  case ENODATA: return MA_NO_DATA_AVAILABLE;
1365  #endif
1366  #ifdef ETIME
1367  case ETIME: return MA_TIMEOUT;
1368  #endif
1369  #ifdef ENOSR
1370  case ENOSR: return MA_NO_DATA_AVAILABLE;
1371  #endif
1372  #ifdef ENONET
1373  case ENONET: return MA_NO_NETWORK;
1374  #endif
1375  #ifdef ENOPKG
1376  case ENOPKG: return MA_ERROR;
1377  #endif
1378  #ifdef EREMOTE
1379  case EREMOTE: return MA_ERROR;
1380  #endif
1381  #ifdef ENOLINK
1382  case ENOLINK: return MA_ERROR;
1383  #endif
1384  #ifdef EADV
1385  case EADV: return MA_ERROR;
1386  #endif
1387  #ifdef ESRMNT
1388  case ESRMNT: return MA_ERROR;
1389  #endif
1390  #ifdef ECOMM
1391  case ECOMM: return MA_ERROR;
1392  #endif
1393  #ifdef EPROTO
1394  case EPROTO: return MA_ERROR;
1395  #endif
1396  #ifdef EMULTIHOP
1397  case EMULTIHOP: return MA_ERROR;
1398  #endif
1399  #ifdef EDOTDOT
1400  case EDOTDOT: return MA_ERROR;
1401  #endif
1402  #ifdef EBADMSG
1403  case EBADMSG: return MA_BAD_MESSAGE;
1404  #endif
1405  #ifdef EOVERFLOW
1406  case EOVERFLOW: return MA_TOO_BIG;
1407  #endif
1408  #ifdef ENOTUNIQ
1409  case ENOTUNIQ: return MA_NOT_UNIQUE;
1410  #endif
1411  #ifdef EBADFD
1412  case EBADFD: return MA_ERROR;
1413  #endif
1414  #ifdef EREMCHG
1415  case EREMCHG: return MA_ERROR;
1416  #endif
1417  #ifdef ELIBACC
1418  case ELIBACC: return MA_ACCESS_DENIED;
1419  #endif
1420  #ifdef ELIBBAD
1421  case ELIBBAD: return MA_INVALID_FILE;
1422  #endif
1423  #ifdef ELIBSCN
1424  case ELIBSCN: return MA_INVALID_FILE;
1425  #endif
1426  #ifdef ELIBMAX
1427  case ELIBMAX: return MA_ERROR;
1428  #endif
1429  #ifdef ELIBEXEC
1430  case ELIBEXEC: return MA_ERROR;
1431  #endif
1432  #ifdef EILSEQ
1433  case EILSEQ: return MA_INVALID_DATA;
1434  #endif
1435  #ifdef ERESTART
1436  case ERESTART: return MA_ERROR;
1437  #endif
1438  #ifdef ESTRPIPE
1439  case ESTRPIPE: return MA_ERROR;
1440  #endif
1441  #ifdef EUSERS
1442  case EUSERS: return MA_ERROR;
1443  #endif
1444  #ifdef ENOTSOCK
1445  case ENOTSOCK: return MA_NOT_SOCKET;
1446  #endif
1447  #ifdef EDESTADDRREQ
1448  case EDESTADDRREQ: return MA_NO_ADDRESS;
1449  #endif
1450  #ifdef EMSGSIZE
1451  case EMSGSIZE: return MA_TOO_BIG;
1452  #endif
1453  #ifdef EPROTOTYPE
1454  case EPROTOTYPE: return MA_BAD_PROTOCOL;
1455  #endif
1456  #ifdef ENOPROTOOPT
1457  case ENOPROTOOPT: return MA_PROTOCOL_UNAVAILABLE;
1458  #endif
1459  #ifdef EPROTONOSUPPORT
1460  case EPROTONOSUPPORT: return MA_PROTOCOL_NOT_SUPPORTED;
1461  #endif
1462  #ifdef ESOCKTNOSUPPORT
1463  case ESOCKTNOSUPPORT: return MA_SOCKET_NOT_SUPPORTED;
1464  #endif
1465  #ifdef EOPNOTSUPP
1466  case EOPNOTSUPP: return MA_INVALID_OPERATION;
1467  #endif
1468  #ifdef EPFNOSUPPORT
1469  case EPFNOSUPPORT: return MA_PROTOCOL_FAMILY_NOT_SUPPORTED;
1470  #endif
1471  #ifdef EAFNOSUPPORT
1472  case EAFNOSUPPORT: return MA_ADDRESS_FAMILY_NOT_SUPPORTED;
1473  #endif
1474  #ifdef EADDRINUSE
1475  case EADDRINUSE: return MA_ALREADY_IN_USE;
1476  #endif
1477  #ifdef EADDRNOTAVAIL
1478  case EADDRNOTAVAIL: return MA_ERROR;
1479  #endif
1480  #ifdef ENETDOWN
1481  case ENETDOWN: return MA_NO_NETWORK;
1482  #endif
1483  #ifdef ENETUNREACH
1484  case ENETUNREACH: return MA_NO_NETWORK;
1485  #endif
1486  #ifdef ENETRESET
1487  case ENETRESET: return MA_NO_NETWORK;
1488  #endif
1489  #ifdef ECONNABORTED
1490  case ECONNABORTED: return MA_NO_NETWORK;
1491  #endif
1492  #ifdef ECONNRESET
1493  case ECONNRESET: return MA_CONNECTION_RESET;
1494  #endif
1495  #ifdef ENOBUFS
1496  case ENOBUFS: return MA_NO_SPACE;
1497  #endif
1498  #ifdef EISCONN
1499  case EISCONN: return MA_ALREADY_CONNECTED;
1500  #endif
1501  #ifdef ENOTCONN
1502  case ENOTCONN: return MA_NOT_CONNECTED;
1503  #endif
1504  #ifdef ESHUTDOWN
1505  case ESHUTDOWN: return MA_ERROR;
1506  #endif
1507  #ifdef ETOOMANYREFS
1508  case ETOOMANYREFS: return MA_ERROR;
1509  #endif
1510  #ifdef ETIMEDOUT
1511  case ETIMEDOUT: return MA_TIMEOUT;
1512  #endif
1513  #ifdef ECONNREFUSED
1514  case ECONNREFUSED: return MA_CONNECTION_REFUSED;
1515  #endif
1516  #ifdef EHOSTDOWN
1517  case EHOSTDOWN: return MA_NO_HOST;
1518  #endif
1519  #ifdef EHOSTUNREACH
1520  case EHOSTUNREACH: return MA_NO_HOST;
1521  #endif
1522  #ifdef EALREADY
1523  case EALREADY: return MA_IN_PROGRESS;
1524  #endif
1525  #ifdef EINPROGRESS
1526  case EINPROGRESS: return MA_IN_PROGRESS;
1527  #endif
1528  #ifdef ESTALE
1529  case ESTALE: return MA_INVALID_FILE;
1530  #endif
1531  #ifdef EUCLEAN
1532  case EUCLEAN: return MA_ERROR;
1533  #endif
1534  #ifdef ENOTNAM
1535  case ENOTNAM: return MA_ERROR;
1536  #endif
1537  #ifdef ENAVAIL
1538  case ENAVAIL: return MA_ERROR;
1539  #endif
1540  #ifdef EISNAM
1541  case EISNAM: return MA_ERROR;
1542  #endif
1543  #ifdef EREMOTEIO
1544  case EREMOTEIO: return MA_IO_ERROR;
1545  #endif
1546  #ifdef EDQUOT
1547  case EDQUOT: return MA_NO_SPACE;
1548  #endif
1549  #ifdef ENOMEDIUM
1550  case ENOMEDIUM: return MA_DOES_NOT_EXIST;
1551  #endif
1552  #ifdef EMEDIUMTYPE
1553  case EMEDIUMTYPE: return MA_ERROR;
1554  #endif
1555  #ifdef ECANCELED
1556  case ECANCELED: return MA_CANCELLED;
1557  #endif
1558  #ifdef ENOKEY
1559  case ENOKEY: return MA_ERROR;
1560  #endif
1561  #ifdef EKEYEXPIRED
1562  case EKEYEXPIRED: return MA_ERROR;
1563  #endif
1564  #ifdef EKEYREVOKED
1565  case EKEYREVOKED: return MA_ERROR;
1566  #endif
1567  #ifdef EKEYREJECTED
1568  case EKEYREJECTED: return MA_ERROR;
1569  #endif
1570  #ifdef EOWNERDEAD
1571  case EOWNERDEAD: return MA_ERROR;
1572  #endif
1573  #ifdef ENOTRECOVERABLE
1574  case ENOTRECOVERABLE: return MA_ERROR;
1575  #endif
1576  #ifdef ERFKILL
1577  case ERFKILL: return MA_ERROR;
1578  #endif
1579  #ifdef EHWPOISON
1580  case EHWPOISON: return MA_ERROR;
1581  #endif
1582  default: return MA_ERROR;
1583  }
1584 }
1585 
1586 MA_API ma_result ma_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
1587 {
1588 #if defined(_MSC_VER) && _MSC_VER >= 1400
1589  errno_t err;
1590 #endif
1591 
1592  if (ppFile != NULL) {
1593  *ppFile = NULL; /* Safety. */
1594  }
1595 
1596  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
1597  return MA_INVALID_ARGS;
1598  }
1599 
1600 #if defined(_MSC_VER) && _MSC_VER >= 1400
1601  err = fopen_s(ppFile, pFilePath, pOpenMode);
1602  if (err != 0) {
1603  return ma_result_from_errno(err);
1604  }
1605 #else
1606 #if defined(_WIN32) || defined(__APPLE__)
1607  *ppFile = fopen(pFilePath, pOpenMode);
1608 #else
1609  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
1610  *ppFile = fopen64(pFilePath, pOpenMode);
1611  #else
1612  *ppFile = fopen(pFilePath, pOpenMode);
1613  #endif
1614 #endif
1615  if (*ppFile == NULL) {
1617  if (result == MA_SUCCESS) {
1618  result = MA_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
1619  }
1620 
1621  return result;
1622  }
1623 #endif
1624 
1625  return MA_SUCCESS;
1626 }
1627 
1628 
1629 
1630 /*
1631 _wfopen() isn't always available in all compilation environments.
1632 
1633  * Windows only.
1634  * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
1635  * MinGW-64 (both 32- and 64-bit) seems to support it.
1636  * MinGW wraps it in !defined(__STRICT_ANSI__).
1637  * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
1638 
1639 This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
1640 fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
1641 */
1642 #if defined(_WIN32)
1643  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
1644  #define MA_HAS_WFOPEN
1645  #endif
1646 #endif
1647 
1648 MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const ma_allocation_callbacks* pAllocationCallbacks)
1649 {
1650  if (ppFile != NULL) {
1651  *ppFile = NULL; /* Safety. */
1652  }
1653 
1654  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
1655  return MA_INVALID_ARGS;
1656  }
1657 
1658 #if defined(MA_HAS_WFOPEN)
1659  {
1660  /* Use _wfopen() on Windows. */
1661  #if defined(_MSC_VER) && _MSC_VER >= 1400
1662  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
1663  if (err != 0) {
1664  return ma_result_from_errno(err);
1665  }
1666  #else
1667  *ppFile = _wfopen(pFilePath, pOpenMode);
1668  if (*ppFile == NULL) {
1669  return ma_result_from_errno(errno);
1670  }
1671  #endif
1672  (void)pAllocationCallbacks;
1673  }
1674 #else
1675  /*
1676  Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
1677  think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
1678  maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
1679  */
1680  {
1681  mbstate_t mbs;
1682  size_t lenMB;
1683  const wchar_t* pFilePathTemp = pFilePath;
1684  char* pFilePathMB = NULL;
1685  char pOpenModeMB[32] = {0};
1686 
1687  /* Get the length first. */
1688  MA_ZERO_OBJECT(&mbs);
1689  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
1690  if (lenMB == (size_t)-1) {
1691  return ma_result_from_errno(errno);
1692  }
1693 
1694  pFilePathMB = (char*)ma_malloc(lenMB + 1, pAllocationCallbacks);
1695  if (pFilePathMB == NULL) {
1696  return MA_OUT_OF_MEMORY;
1697  }
1698 
1699  pFilePathTemp = pFilePath;
1700  MA_ZERO_OBJECT(&mbs);
1701  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
1702 
1703  /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
1704  {
1705  size_t i = 0;
1706  for (;;) {
1707  if (pOpenMode[i] == 0) {
1708  pOpenModeMB[i] = '\0';
1709  break;
1710  }
1711 
1712  pOpenModeMB[i] = (char)pOpenMode[i];
1713  i += 1;
1714  }
1715  }
1716 
1717  *ppFile = fopen(pFilePathMB, pOpenModeMB);
1718 
1719  ma_free(pFilePathMB, pAllocationCallbacks);
1720  }
1721 
1722  if (*ppFile == NULL) {
1723  return MA_ERROR;
1724  }
1725 #endif
1726 
1727  return MA_SUCCESS;
1728 }
1729 
1730 
1731 
1732 static MA_INLINE void ma_copy_memory_64(void* dst, const void* src, ma_uint64 sizeInBytes)
1733 {
1734 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
1735  MA_COPY_MEMORY(dst, src, (size_t)sizeInBytes);
1736 #else
1737  while (sizeInBytes > 0) {
1738  ma_uint64 bytesToCopyNow = sizeInBytes;
1739  if (bytesToCopyNow > MA_SIZE_MAX) {
1740  bytesToCopyNow = MA_SIZE_MAX;
1741  }
1742 
1743  MA_COPY_MEMORY(dst, src, (size_t)bytesToCopyNow); /* Safe cast to size_t. */
1744 
1745  sizeInBytes -= bytesToCopyNow;
1746  dst = ( void*)(( ma_uint8*)dst + bytesToCopyNow);
1747  src = (const void*)((const ma_uint8*)src + bytesToCopyNow);
1748  }
1749 #endif
1750 }
1751 
1752 static MA_INLINE void ma_zero_memory_64(void* dst, ma_uint64 sizeInBytes)
1753 {
1754 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
1755  MA_ZERO_MEMORY(dst, (size_t)sizeInBytes);
1756 #else
1757  while (sizeInBytes > 0) {
1758  ma_uint64 bytesToZeroNow = sizeInBytes;
1759  if (bytesToZeroNow > MA_SIZE_MAX) {
1760  bytesToZeroNow = MA_SIZE_MAX;
1761  }
1762 
1763  MA_ZERO_MEMORY(dst, (size_t)bytesToZeroNow); /* Safe cast to size_t. */
1764 
1765  sizeInBytes -= bytesToZeroNow;
1766  dst = (void*)((ma_uint8*)dst + bytesToZeroNow);
1767  }
1768 #endif
1769 }
1770 
1771 
1772 /* Thanks to good old Bit Twiddling Hacks for this one: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
1773 static MA_INLINE unsigned int ma_next_power_of_2(unsigned int x)
1774 {
1775  x--;
1776  x |= x >> 1;
1777  x |= x >> 2;
1778  x |= x >> 4;
1779  x |= x >> 8;
1780  x |= x >> 16;
1781  x++;
1782 
1783  return x;
1784 }
1785 
1786 static MA_INLINE unsigned int ma_prev_power_of_2(unsigned int x)
1787 {
1788  return ma_next_power_of_2(x) >> 1;
1789 }
1790 
1791 static MA_INLINE unsigned int ma_round_to_power_of_2(unsigned int x)
1792 {
1793  unsigned int prev = ma_prev_power_of_2(x);
1794  unsigned int next = ma_next_power_of_2(x);
1795  if ((next - x) > (x - prev)) {
1796  return prev;
1797  } else {
1798  return next;
1799  }
1800 }
1801 
1802 static MA_INLINE unsigned int ma_count_set_bits(unsigned int x)
1803 {
1804  unsigned int count = 0;
1805  while (x != 0) {
1806  if (x & 1) {
1807  count += 1;
1808  }
1809 
1810  x = x >> 1;
1811  }
1812 
1813  return count;
1814 }
1815 
1816 
1817 
1818 /**************************************************************************************************************************************************************
1819 
1820 Allocation Callbacks
1821 
1822 **************************************************************************************************************************************************************/
1823 static void* ma__malloc_default(size_t sz, void* pUserData)
1824 {
1825  (void)pUserData;
1826  return MA_MALLOC(sz);
1827 }
1828 
1829 static void* ma__realloc_default(void* p, size_t sz, void* pUserData)
1830 {
1831  (void)pUserData;
1832  return MA_REALLOC(p, sz);
1833 }
1834 
1835 static void ma__free_default(void* p, void* pUserData)
1836 {
1837  (void)pUserData;
1838  MA_FREE(p);
1839 }
1840 
1841 
1842 static void* ma__malloc_from_callbacks(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
1843 {
1844  if (pAllocationCallbacks == NULL) {
1845  return NULL;
1846  }
1847 
1848  if (pAllocationCallbacks->onMalloc != NULL) {
1849  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
1850  }
1851 
1852  /* Try using realloc(). */
1853  if (pAllocationCallbacks->onRealloc != NULL) {
1854  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
1855  }
1856 
1857  return NULL;
1858 }
1859 
1860 static void* ma__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const ma_allocation_callbacks* pAllocationCallbacks)
1861 {
1862  if (pAllocationCallbacks == NULL) {
1863  return NULL;
1864  }
1865 
1866  if (pAllocationCallbacks->onRealloc != NULL) {
1867  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
1868  }
1869 
1870  /* Try emulating realloc() in terms of malloc()/free(). */
1871  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
1872  void* p2;
1873 
1874  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
1875  if (p2 == NULL) {
1876  return NULL;
1877  }
1878 
1879  if (p != NULL) {
1880  MA_COPY_MEMORY(p2, p, szOld);
1881  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1882  }
1883 
1884  return p2;
1885  }
1886 
1887  return NULL;
1888 }
1889 
1890 static MA_INLINE void* ma__calloc_from_callbacks(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
1891 {
1892  void* p = ma__malloc_from_callbacks(sz, pAllocationCallbacks);
1893  if (p != NULL) {
1894  MA_ZERO_MEMORY(p, sz);
1895  }
1896 
1897  return p;
1898 }
1899 
1900 static void ma__free_from_callbacks(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
1901 {
1902  if (p == NULL || pAllocationCallbacks == NULL) {
1903  return;
1904  }
1905 
1906  if (pAllocationCallbacks->onFree != NULL) {
1907  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1908  }
1909 }
1910 
1912 {
1913  ma_allocation_callbacks callbacks;
1914  callbacks.pUserData = NULL;
1915  callbacks.onMalloc = ma__malloc_default;
1916  callbacks.onRealloc = ma__realloc_default;
1917  callbacks.onFree = ma__free_default;
1918 
1919  return callbacks;
1920 }
1921 
1923 {
1924  if (pDst == NULL) {
1925  return MA_INVALID_ARGS;
1926  }
1927 
1928  if (pSrc == NULL) {
1930  } else {
1931  if (pSrc->pUserData == NULL && pSrc->onFree == NULL && pSrc->onMalloc == NULL && pSrc->onRealloc == NULL) {
1933  } else {
1934  if (pSrc->onFree == NULL || (pSrc->onMalloc == NULL && pSrc->onRealloc == NULL)) {
1935  return MA_INVALID_ARGS; /* Invalid allocation callbacks. */
1936  } else {
1937  *pDst = *pSrc;
1938  }
1939  }
1940  }
1941 
1942  return MA_SUCCESS;
1943 }
1944 
1945 
1946 
1947 
1948 /**************************************************************************************************************************************************************
1949 
1950 Logging
1951 
1952 **************************************************************************************************************************************************************/
1954 {
1955  switch (logLevel)
1956  {
1957  case MA_LOG_LEVEL_DEBUG: return "DEBUG";
1958  case MA_LOG_LEVEL_INFO: return "INFO";
1959  case MA_LOG_LEVEL_WARNING: return "WARNING";
1960  case MA_LOG_LEVEL_ERROR: return "ERROR";
1961  default: return "ERROR";
1962  }
1963 }
1964 
1965 #if defined(MA_DEBUG_OUTPUT)
1966 
1967 /* Customize this to use a specific tag in __android_log_print() for debug output messages. */
1968 #ifndef MA_ANDROID_LOG_TAG
1969 #define MA_ANDROID_LOG_TAG "miniaudio"
1970 #endif
1971 
1972 void ma_log_callback_debug(void* pUserData, ma_uint32 level, const char* pMessage)
1973 {
1974  (void)pUserData;
1975 
1976  /* Special handling for some platforms. */
1977  #if defined(MA_ANDROID)
1978  {
1979  /* Android. */
1980  __android_log_print(ANDROID_LOG_DEBUG, MA_ANDROID_LOG_TAG, "%s: %s", ma_log_level_to_string(level), pMessage);
1981  }
1982  #else
1983  {
1984  /* Everything else. */
1985  printf("%s: %s", ma_log_level_to_string(level), pMessage);
1986  }
1987  #endif
1988 }
1989 #endif
1990 
1992 {
1993  ma_log_callback callback;
1994 
1995  MA_ZERO_OBJECT(&callback);
1996  callback.onLog = onLog;
1997  callback.pUserData = pUserData;
1998 
1999  return callback;
2000 }
2001 
2002 
2003 MA_API ma_result ma_log_init(const ma_allocation_callbacks* pAllocationCallbacks, ma_log* pLog)
2004 {
2005  if (pLog == NULL) {
2006  return MA_INVALID_ARGS;
2007  }
2008 
2009  MA_ZERO_OBJECT(pLog);
2010  ma_allocation_callbacks_init_copy(&pLog->allocationCallbacks, pAllocationCallbacks);
2011 
2012  /* We need a mutex for thread safety. */
2013  #ifndef MA_NO_THREADING
2014  {
2015  ma_result result = ma_mutex_init(&pLog->lock);
2016  if (result != MA_SUCCESS) {
2017  return result;
2018  }
2019  }
2020  #endif
2021 
2022  /* If we're using debug output, enable it. */
2023  #if defined(MA_DEBUG_OUTPUT)
2024  {
2025  ma_log_register_callback(pLog, ma_log_callback_init(ma_log_callback_debug, NULL)); /* Doesn't really matter if this fails. */
2026  }
2027  #endif
2028 
2029  return MA_SUCCESS;
2030 }
2031 
2033 {
2034  if (pLog == NULL) {
2035  return;
2036  }
2037 
2038 #ifndef MA_NO_THREADING
2039  ma_mutex_uninit(&pLog->lock);
2040 #endif
2041 }
2042 
2043 static void ma_log_lock(ma_log* pLog)
2044 {
2045 #ifndef MA_NO_THREADING
2046  ma_mutex_lock(&pLog->lock);
2047 #else
2048  (void)pLog;
2049 #endif
2050 }
2051 
2052 static void ma_log_unlock(ma_log* pLog)
2053 {
2054 #ifndef MA_NO_THREADING
2055  ma_mutex_unlock(&pLog->lock);
2056 #else
2057  (void)pLog;
2058 #endif
2059 }
2060 
2062 {
2063  ma_result result = MA_SUCCESS;
2064 
2065  if (pLog == NULL || callback.onLog == NULL) {
2066  return MA_INVALID_ARGS;
2067  }
2068 
2069  ma_log_lock(pLog);
2070  {
2071  if (pLog->callbackCount == ma_countof(pLog->callbacks)) {
2072  result = MA_OUT_OF_MEMORY; /* Reached the maximum allowed log callbacks. */
2073  } else {
2074  pLog->callbacks[pLog->callbackCount] = callback;
2075  pLog->callbackCount += 1;
2076  }
2077  }
2078  ma_log_unlock(pLog);
2079 
2080  return result;
2081 }
2082 
2084 {
2085  if (pLog == NULL) {
2086  return MA_INVALID_ARGS;
2087  }
2088 
2089  ma_log_lock(pLog);
2090  {
2091  ma_uint32 iLog;
2092  for (iLog = 0; iLog < pLog->callbackCount; ) {
2093  if (pLog->callbacks[iLog].onLog == callback.onLog) {
2094  /* Found. Move everything down a slot. */
2095  ma_uint32 jLog;
2096  for (jLog = iLog; jLog < pLog->callbackCount-1; jLog += 1) {
2097  pLog->callbacks[jLog] = pLog->callbacks[jLog + 1];
2098  }
2099 
2100  pLog->callbackCount -= 1;
2101  } else {
2102  /* Not found. */
2103  iLog += 1;
2104  }
2105  }
2106  }
2107  ma_log_unlock(pLog);
2108 
2109  return MA_SUCCESS;
2110 }
2111 
2112 MA_API ma_result ma_log_post(ma_log* pLog, ma_uint32 level, const char* pMessage)
2113 {
2114  if (pLog == NULL || pMessage == NULL) {
2115  return MA_INVALID_ARGS;
2116  }
2117 
2118  /* If it's a debug log, ignore it unless MA_DEBUG_OUTPUT is enabled. */
2119  #if !defined(MA_DEBUG_OUTPUT)
2120  {
2121  if (level == MA_LOG_LEVEL_DEBUG) {
2122  return MA_INVALID_ARGS; /* Don't post debug messages if debug output is disabled. */
2123  }
2124  }
2125  #endif
2126 
2127  ma_log_lock(pLog);
2128  {
2129  ma_uint32 iLog;
2130  for (iLog = 0; iLog < pLog->callbackCount; iLog += 1) {
2131  if (pLog->callbacks[iLog].onLog) {
2132  pLog->callbacks[iLog].onLog(pLog->callbacks[iLog].pUserData, level, pMessage);
2133  }
2134  }
2135  }
2136  ma_log_unlock(pLog);
2137 
2138  return MA_SUCCESS;
2139 }
2140 
2141 
2142 /*
2143 We need to emulate _vscprintf() for the VC6 build. This can be more efficient, but since it's only VC6, and it's just a
2144 logging function, I'm happy to keep this simple. In the VC6 build we can implement this in terms of _vsnprintf().
2145 */
2146 #if defined(_MSC_VER) && _MSC_VER < 1900
2147 static int ma_vscprintf(const ma_allocation_callbacks* pAllocationCallbacks, const char* format, va_list args)
2148 {
2149 #if _MSC_VER > 1200
2150  return _vscprintf(format, args);
2151 #else
2152  int result;
2153  char* pTempBuffer = NULL;
2154  size_t tempBufferCap = 1024;
2155 
2156  if (format == NULL) {
2157  errno = EINVAL;
2158  return -1;
2159  }
2160 
2161  for (;;) {
2162  char* pNewTempBuffer = (char*)ma_realloc(pTempBuffer, tempBufferCap, pAllocationCallbacks);
2163  if (pNewTempBuffer == NULL) {
2164  ma_free(pTempBuffer, pAllocationCallbacks);
2165  errno = ENOMEM;
2166  return -1; /* Out of memory. */
2167  }
2168 
2169  pTempBuffer = pNewTempBuffer;
2170 
2171  result = _vsnprintf(pTempBuffer, tempBufferCap, format, args);
2172  ma_free(pTempBuffer, NULL);
2173 
2174  if (result != -1) {
2175  break; /* Got it. */
2176  }
2177 
2178  /* Buffer wasn't big enough. Ideally it'd be nice to use an error code to know the reason for sure, but this is reliable enough. */
2179  tempBufferCap *= 2;
2180  }
2181 
2182  return result;
2183 #endif
2184 }
2185 #endif
2186 
2187 MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat, va_list args)
2188 {
2189  if (pLog == NULL || pFormat == NULL) {
2190  return MA_INVALID_ARGS;
2191  }
2192 
2193  /*
2194  If it's a debug log, ignore it unless MA_DEBUG_OUTPUT is enabled. Do this before generating the
2195  formatted message string so that we don't waste time only to have ma_log_post() reject it.
2196  */
2197  #if !defined(MA_DEBUG_OUTPUT)
2198  {
2199  if (level == MA_LOG_LEVEL_DEBUG) {
2200  return MA_INVALID_ARGS; /* Don't post debug messages if debug output is disabled. */
2201  }
2202  }
2203  #endif
2204 
2205  #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || ((!defined(_MSC_VER) || _MSC_VER >= 1900) && !defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
2206  {
2207  ma_result result;
2208  int length;
2209  char pFormattedMessageStack[1024];
2210  char* pFormattedMessageHeap = NULL;
2211 
2212  /* First try formatting into our fixed sized stack allocated buffer. If this is too small we'll fallback to a heap allocation. */
2213  length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args);
2214  if (length < 0) {
2215  return MA_INVALID_OPERATION; /* An error occured when trying to convert the buffer. */
2216  }
2217 
2218  if ((size_t)length < sizeof(pFormattedMessageStack)) {
2219  /* The string was written to the stack. */
2220  result = ma_log_post(pLog, level, pFormattedMessageStack);
2221  } else {
2222  /* The stack buffer was too small, try the heap. */
2223  pFormattedMessageHeap = (char*)ma_malloc(length + 1, &pLog->allocationCallbacks);
2224  if (pFormattedMessageHeap == NULL) {
2225  return MA_OUT_OF_MEMORY;
2226  }
2227 
2228  length = vsnprintf(pFormattedMessageHeap, length + 1, pFormat, args);
2229  if (length < 0) {
2230  ma_free(pFormattedMessageHeap, &pLog->allocationCallbacks);
2231  return MA_INVALID_OPERATION;
2232  }
2233 
2234  result = ma_log_post(pLog, level, pFormattedMessageHeap);
2235  ma_free(pFormattedMessageHeap, &pLog->allocationCallbacks);
2236  }
2237 
2238  return result;
2239  }
2240  #else
2241  {
2242  /*
2243  Without snprintf() we need to first measure the string and then heap allocate it. I'm only aware of Visual Studio having support for this without snprintf(), so we'll
2244  need to restrict this branch to Visual Studio. For other compilers we need to just not support formatted logging because I don't want the security risk of overflowing
2245  a fixed sized stack allocated buffer.
2246  */
2247  #if defined(_MSC_VER) && _MSC_VER >= 1200 /* 1200 = VC6 */
2248  {
2249  ma_result result;
2250  int formattedLen;
2251  char* pFormattedMessage = NULL;
2252  va_list args2;
2253 
2254  #if _MSC_VER >= 1800
2255  {
2256  va_copy(args2, args);
2257  }
2258  #else
2259  {
2260  args2 = args;
2261  }
2262  #endif
2263 
2264  formattedLen = ma_vscprintf(&pLog->allocationCallbacks, pFormat, args2);
2265  va_end(args2);
2266 
2267  if (formattedLen <= 0) {
2268  return MA_INVALID_OPERATION;
2269  }
2270 
2271  pFormattedMessage = (char*)ma_malloc(formattedLen + 1, &pLog->allocationCallbacks);
2272  if (pFormattedMessage == NULL) {
2273  return MA_OUT_OF_MEMORY;
2274  }
2275 
2276  /* We'll get errors on newer versions of Visual Studio if we try to use vsprintf(). */
2277  #if _MSC_VER >= 1400 /* 1400 = Visual Studio 2005 */
2278  {
2279  vsprintf_s(pFormattedMessage, formattedLen + 1, pFormat, args);
2280  }
2281  #else
2282  {
2283  vsprintf(pFormattedMessage, pFormat, args);
2284  }
2285  #endif
2286 
2287  result = ma_log_post(pLog, level, pFormattedMessage);
2288  ma_free(pFormattedMessage, &pLog->allocationCallbacks);
2289 
2290  return result;
2291  }
2292  #else
2293  {
2294  /* Can't do anything because we don't have a safe way of to emulate vsnprintf() without a manual solution. */
2295  (void)level;
2296  (void)args;
2297 
2298  return MA_INVALID_OPERATION;
2299  }
2300  #endif
2301  }
2302  #endif
2303 }
2304 
2305 MA_API ma_result ma_log_postf(ma_log* pLog, ma_uint32 level, const char* pFormat, ...)
2306 {
2307  ma_result result;
2308  va_list args;
2309 
2310  if (pLog == NULL || pFormat == NULL) {
2311  return MA_INVALID_ARGS;
2312  }
2313 
2314  /*
2315  If it's a debug log, ignore it unless MA_DEBUG_OUTPUT is enabled. Do this before generating the
2316  formatted message string so that we don't waste time only to have ma_log_post() reject it.
2317  */
2318  #if !defined(MA_DEBUG_OUTPUT)
2319  {
2320  if (level == MA_LOG_LEVEL_DEBUG) {
2321  return MA_INVALID_ARGS; /* Don't post debug messages if debug output is disabled. */
2322  }
2323  }
2324  #endif
2325 
2326  va_start(args, pFormat);
2327  {
2328  result = ma_log_postv(pLog, level, pFormat, args);
2329  }
2330  va_end(args);
2331 
2332  return result;
2333 }
2334 
2335 
2336 
2337 
2338 /* Clamps an f32 sample to -1..1 */
2339 static MA_INLINE float ma_clip_f32(float x)
2340 {
2341  if (x < -1) return -1;
2342  if (x > +1) return +1;
2343  return x;
2344 }
2345 
2346 static MA_INLINE float ma_mix_f32(float x, float y, float a)
2347 {
2348  return x*(1-a) + y*a;
2349 }
2350 static MA_INLINE float ma_mix_f32_fast(float x, float y, float a)
2351 {
2352  float r0 = (y - x);
2353  float r1 = r0*a;
2354  return x + r1;
2355  /*return x + (y - x)*a;*/
2356 }
2357 
2358 #if defined(MA_SUPPORT_SSE2)
2359 static MA_INLINE __m128 ma_mix_f32_fast__sse2(__m128 x, __m128 y, __m128 a)
2360 {
2361  return _mm_add_ps(x, _mm_mul_ps(_mm_sub_ps(y, x), a));
2362 }
2363 #endif
2364 #if defined(MA_SUPPORT_AVX2)
2365 static MA_INLINE __m256 ma_mix_f32_fast__avx2(__m256 x, __m256 y, __m256 a)
2366 {
2367  return _mm256_add_ps(x, _mm256_mul_ps(_mm256_sub_ps(y, x), a));
2368 }
2369 #endif
2370 #if defined(MA_SUPPORT_AVX512)
2371 static MA_INLINE __m512 ma_mix_f32_fast__avx512(__m512 x, __m512 y, __m512 a)
2372 {
2373  return _mm512_add_ps(x, _mm512_mul_ps(_mm512_sub_ps(y, x), a));
2374 }
2375 #endif
2376 #if defined(MA_SUPPORT_NEON)
2377 static MA_INLINE float32x4_t ma_mix_f32_fast__neon(float32x4_t x, float32x4_t y, float32x4_t a)
2378 {
2379  return vaddq_f32(x, vmulq_f32(vsubq_f32(y, x), a));
2380 }
2381 #endif
2382 
2383 
2384 static MA_INLINE double ma_mix_f64(double x, double y, double a)
2385 {
2386  return x*(1-a) + y*a;
2387 }
2388 static MA_INLINE double ma_mix_f64_fast(double x, double y, double a)
2389 {
2390  return x + (y - x)*a;
2391 }
2392 
2393 static MA_INLINE float ma_scale_to_range_f32(float x, float lo, float hi)
2394 {
2395  return lo + x*(hi-lo);
2396 }
2397 
2398 
2399 /*
2400 Greatest common factor using Euclid's algorithm iteratively.
2401 */
2403 {
2404  for (;;) {
2405  if (b == 0) {
2406  break;
2407  } else {
2408  ma_uint32 t = a;
2409  a = b;
2410  b = t % a;
2411  }
2412  }
2413 
2414  return a;
2415 }
2416 
2417 
2418 /*
2419 Random Number Generation
2420 
2421 miniaudio uses the LCG random number generation algorithm. This is good enough for audio.
2422 
2423 Note that miniaudio's global LCG implementation uses global state which is _not_ thread-local. When this is called across
2424 multiple threads, results will be unpredictable. However, it won't crash and results will still be random enough for
2425 miniaudio's purposes.
2426 */
2427 #ifndef MA_DEFAULT_LCG_SEED
2428 #define MA_DEFAULT_LCG_SEED 4321
2429 #endif
2430 
2431 #define MA_LCG_M 2147483647
2432 #define MA_LCG_A 48271
2433 #define MA_LCG_C 0
2434 
2435 static ma_lcg g_maLCG = {MA_DEFAULT_LCG_SEED}; /* Non-zero initial seed. Use ma_seed() to use an explicit seed. */
2436 
2437 static MA_INLINE void ma_lcg_seed(ma_lcg* pLCG, ma_int32 seed)
2438 {
2439  MA_ASSERT(pLCG != NULL);
2440  pLCG->state = seed;
2441 }
2442 
2444 {
2445  pLCG->state = (MA_LCG_A * pLCG->state + MA_LCG_C) % MA_LCG_M;
2446  return pLCG->state;
2447 }
2448 
2450 {
2451  return (ma_uint32)ma_lcg_rand_s32(pLCG);
2452 }
2453 
2455 {
2456  return (ma_int16)(ma_lcg_rand_s32(pLCG) & 0xFFFF);
2457 }
2458 
2459 static MA_INLINE double ma_lcg_rand_f64(ma_lcg* pLCG)
2460 {
2461  return ma_lcg_rand_s32(pLCG) / (double)0x7FFFFFFF;
2462 }
2463 
2464 static MA_INLINE float ma_lcg_rand_f32(ma_lcg* pLCG)
2465 {
2466  return (float)ma_lcg_rand_f64(pLCG);
2467 }
2468 
2469 static MA_INLINE float ma_lcg_rand_range_f32(ma_lcg* pLCG, float lo, float hi)
2470 {
2471  return ma_scale_to_range_f32(ma_lcg_rand_f32(pLCG), lo, hi);
2472 }
2473 
2475 {
2476  if (lo == hi) {
2477  return lo;
2478  }
2479 
2480  return lo + ma_lcg_rand_u32(pLCG) / (0xFFFFFFFF / (hi - lo + 1) + 1);
2481 }
2482 
2483 
2484 
2485 static MA_INLINE void ma_seed(ma_int32 seed)
2486 {
2487  ma_lcg_seed(&g_maLCG, seed);
2488 }
2489 
2491 {
2492  return ma_lcg_rand_s32(&g_maLCG);
2493 }
2494 
2496 {
2497  return ma_lcg_rand_u32(&g_maLCG);
2498 }
2499 
2500 static MA_INLINE double ma_rand_f64(void)
2501 {
2502  return ma_lcg_rand_f64(&g_maLCG);
2503 }
2504 
2505 static MA_INLINE float ma_rand_f32(void)
2506 {
2507  return ma_lcg_rand_f32(&g_maLCG);
2508 }
2509 
2510 static MA_INLINE float ma_rand_range_f32(float lo, float hi)
2511 {
2512  return ma_lcg_rand_range_f32(&g_maLCG, lo, hi);
2513 }
2514 
2516 {
2517  return ma_lcg_rand_range_s32(&g_maLCG, lo, hi);
2518 }
2519 
2520 
2521 static MA_INLINE float ma_dither_f32_rectangle(float ditherMin, float ditherMax)
2522 {
2523  return ma_rand_range_f32(ditherMin, ditherMax);
2524 }
2525 
2526 static MA_INLINE float ma_dither_f32_triangle(float ditherMin, float ditherMax)
2527 {
2528  float a = ma_rand_range_f32(ditherMin, 0);
2529  float b = ma_rand_range_f32(0, ditherMax);
2530  return a + b;
2531 }
2532 
2533 static MA_INLINE float ma_dither_f32(ma_dither_mode ditherMode, float ditherMin, float ditherMax)
2534 {
2535  if (ditherMode == ma_dither_mode_rectangle) {
2536  return ma_dither_f32_rectangle(ditherMin, ditherMax);
2537  }
2538  if (ditherMode == ma_dither_mode_triangle) {
2539  return ma_dither_f32_triangle(ditherMin, ditherMax);
2540  }
2541 
2542  return 0;
2543 }
2544 
2545 static MA_INLINE ma_int32 ma_dither_s32(ma_dither_mode ditherMode, ma_int32 ditherMin, ma_int32 ditherMax)
2546 {
2547  if (ditherMode == ma_dither_mode_rectangle) {
2548  ma_int32 a = ma_rand_range_s32(ditherMin, ditherMax);
2549  return a;
2550  }
2551  if (ditherMode == ma_dither_mode_triangle) {
2552  ma_int32 a = ma_rand_range_s32(ditherMin, 0);
2553  ma_int32 b = ma_rand_range_s32(0, ditherMax);
2554  return a + b;
2555  }
2556 
2557  return 0;
2558 }
2559 
2560 
2561 /**************************************************************************************************************************************************************
2562 
2563 Atomics
2564 
2565 **************************************************************************************************************************************************************/
2566 /* c89atomic.h begin */
2567 #ifndef c89atomic_h
2568 #define c89atomic_h
2569 #if defined(__cplusplus)
2570 extern "C" {
2571 #endif
2572 typedef signed char c89atomic_int8;
2573 typedef unsigned char c89atomic_uint8;
2574 typedef signed short c89atomic_int16;
2575 typedef unsigned short c89atomic_uint16;
2576 typedef signed int c89atomic_int32;
2577 typedef unsigned int c89atomic_uint32;
2578 #if defined(_MSC_VER)
2579  typedef signed __int64 c89atomic_int64;
2580  typedef unsigned __int64 c89atomic_uint64;
2581 #else
2582  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
2583  #pragma GCC diagnostic push
2584  #pragma GCC diagnostic ignored "-Wlong-long"
2585  #if defined(__clang__)
2586  #pragma GCC diagnostic ignored "-Wc++11-long-long"
2587  #endif
2588  #endif
2589  typedef signed long long c89atomic_int64;
2590  typedef unsigned long long c89atomic_uint64;
2591  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
2592  #pragma GCC diagnostic pop
2593  #endif
2594 #endif
2596 typedef unsigned char c89atomic_bool;
2597 #if !defined(C89ATOMIC_64BIT) && !defined(C89ATOMIC_32BIT)
2598 #ifdef _WIN32
2599 #ifdef _WIN64
2600 #define C89ATOMIC_64BIT
2601 #else
2602 #define C89ATOMIC_32BIT
2603 #endif
2604 #endif
2605 #endif
2606 #if !defined(C89ATOMIC_64BIT) && !defined(C89ATOMIC_32BIT)
2607 #ifdef __GNUC__
2608 #ifdef __LP64__
2609 #define C89ATOMIC_64BIT
2610 #else
2611 #define C89ATOMIC_32BIT
2612 #endif
2613 #endif
2614 #endif
2615 #if !defined(C89ATOMIC_64BIT) && !defined(C89ATOMIC_32BIT)
2616 #include <stdint.h>
2617 #if INTPTR_MAX == INT64_MAX
2618 #define C89ATOMIC_64BIT
2619 #else
2620 #define C89ATOMIC_32BIT
2621 #endif
2622 #endif
2623 #if defined(__x86_64__) || defined(_M_X64)
2624 #define C89ATOMIC_X64
2625 #elif defined(__i386) || defined(_M_IX86)
2626 #define C89ATOMIC_X86
2627 #elif defined(__arm__) || defined(_M_ARM)
2628 #define C89ATOMIC_ARM
2629 #endif
2630 #if defined(_MSC_VER)
2631  #define C89ATOMIC_INLINE __forceinline
2632 #elif defined(__GNUC__)
2633  #if defined(__STRICT_ANSI__)
2634  #define C89ATOMIC_INLINE __inline__ __attribute__((always_inline))
2635  #else
2636  #define C89ATOMIC_INLINE inline __attribute__((always_inline))
2637  #endif
2638 #elif defined(__WATCOMC__) || defined(__DMC__)
2639  #define C89ATOMIC_INLINE __inline
2640 #else
2641  #define C89ATOMIC_INLINE
2642 #endif
2643 #define C89ATOMIC_HAS_8
2644 #define C89ATOMIC_HAS_16
2645 #define C89ATOMIC_HAS_32
2646 #define C89ATOMIC_HAS_64
2647 #if (defined(_MSC_VER) ) || defined(__WATCOMC__) || defined(__DMC__)
2648  #define c89atomic_memory_order_relaxed 0
2649  #define c89atomic_memory_order_consume 1
2650  #define c89atomic_memory_order_acquire 2
2651  #define c89atomic_memory_order_release 3
2652  #define c89atomic_memory_order_acq_rel 4
2653  #define c89atomic_memory_order_seq_cst 5
2654  #if _MSC_VER < 1600 && defined(C89ATOMIC_32BIT)
2655  #define C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY
2656  #endif
2657  #if _MSC_VER < 1600
2658  #undef C89ATOMIC_HAS_8
2659  #undef C89ATOMIC_HAS_16
2660  #endif
2661  #if !defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
2662  #include <intrin.h>
2663  #endif
2664  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
2665  #if defined(C89ATOMIC_HAS_8)
2667  {
2668  c89atomic_uint8 result = 0;
2669  __asm {
2670  mov ecx, dst
2671  mov al, expected
2672  mov dl, desired
2673  lock cmpxchg [ecx], dl
2674  mov result, al
2675  }
2676  return result;
2677  }
2678  #endif
2679  #if defined(C89ATOMIC_HAS_16)
2681  {
2682  c89atomic_uint16 result = 0;
2683  __asm {
2684  mov ecx, dst
2685  mov ax, expected
2686  mov dx, desired
2687  lock cmpxchg [ecx], dx
2688  mov result, ax
2689  }
2690  return result;
2691  }
2692  #endif
2693  #if defined(C89ATOMIC_HAS_32)
2695  {
2696  c89atomic_uint32 result = 0;
2697  __asm {
2698  mov ecx, dst
2699  mov eax, expected
2700  mov edx, desired
2701  lock cmpxchg [ecx], edx
2702  mov result, eax
2703  }
2704  return result;
2705  }
2706  #endif
2707  #if defined(C89ATOMIC_HAS_64)
2709  {
2710  c89atomic_uint32 resultEAX = 0;
2711  c89atomic_uint32 resultEDX = 0;
2712  __asm {
2713  mov esi, dst
2714  mov eax, dword ptr expected
2715  mov edx, dword ptr expected + 4
2716  mov ebx, dword ptr desired
2717  mov ecx, dword ptr desired + 4
2718  lock cmpxchg8b qword ptr [esi]
2719  mov resultEAX, eax
2720  mov resultEDX, edx
2721  }
2722  return ((c89atomic_uint64)resultEDX << 32) | resultEAX;
2723  }
2724  #endif
2725  #else
2726  #if defined(C89ATOMIC_HAS_8)
2727  #define c89atomic_compare_and_swap_8( dst, expected, desired) (c89atomic_uint8 )_InterlockedCompareExchange8((volatile char*)dst, (char)desired, (char)expected)
2728  #endif
2729  #if defined(C89ATOMIC_HAS_16)
2730  #define c89atomic_compare_and_swap_16(dst, expected, desired) (c89atomic_uint16)_InterlockedCompareExchange16((volatile short*)dst, (short)desired, (short)expected)
2731  #endif
2732  #if defined(C89ATOMIC_HAS_32)
2733  #define c89atomic_compare_and_swap_32(dst, expected, desired) (c89atomic_uint32)_InterlockedCompareExchange((volatile long*)dst, (long)desired, (long)expected)
2734  #endif
2735  #if defined(C89ATOMIC_HAS_64)
2736  #define c89atomic_compare_and_swap_64(dst, expected, desired) (c89atomic_uint64)_InterlockedCompareExchange64((volatile long long*)dst, (long long)desired, (long long)expected)
2737  #endif
2738  #endif
2739  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
2740  #if defined(C89ATOMIC_HAS_8)
2742  {
2743  c89atomic_uint8 result = 0;
2744  (void)order;
2745  __asm {
2746  mov ecx, dst
2747  mov al, src
2748  lock xchg [ecx], al
2749  mov result, al
2750  }
2751  return result;
2752  }
2753  #endif
2754  #if defined(C89ATOMIC_HAS_16)
2756  {
2757  c89atomic_uint16 result = 0;
2758  (void)order;
2759  __asm {
2760  mov ecx, dst
2761  mov ax, src
2762  lock xchg [ecx], ax
2763  mov result, ax
2764  }
2765  return result;
2766  }
2767  #endif
2768  #if defined(C89ATOMIC_HAS_32)
2770  {
2771  c89atomic_uint32 result = 0;
2772  (void)order;
2773  __asm {
2774  mov ecx, dst
2775  mov eax, src
2776  lock xchg [ecx], eax
2777  mov result, eax
2778  }
2779  return result;
2780  }
2781  #endif
2782  #else
2783  #if defined(C89ATOMIC_HAS_8)
2785  {
2786  (void)order;
2787  return (c89atomic_uint8)_InterlockedExchange8((volatile char*)dst, (char)src);
2788  }
2789  #endif
2790  #if defined(C89ATOMIC_HAS_16)
2792  {
2793  (void)order;
2794  return (c89atomic_uint16)_InterlockedExchange16((volatile short*)dst, (short)src);
2795  }
2796  #endif
2797  #if defined(C89ATOMIC_HAS_32)
2799  {
2800  (void)order;
2801  return (c89atomic_uint32)_InterlockedExchange((volatile long*)dst, (long)src);
2802  }
2803  #endif
2804  #if defined(C89ATOMIC_HAS_64) && defined(C89ATOMIC_64BIT)
2806  {
2807  (void)order;
2808  return (c89atomic_uint64)_InterlockedExchange64((volatile long long*)dst, (long long)src);
2809  }
2810  #else
2811  #endif
2812  #endif
2813  #if defined(C89ATOMIC_HAS_64) && !defined(C89ATOMIC_64BIT)
2815  {
2816  c89atomic_uint64 oldValue;
2817  do {
2818  oldValue = *dst;
2819  } while (c89atomic_compare_and_swap_64(dst, oldValue, src) != oldValue);
2820  (void)order;
2821  return oldValue;
2822  }
2823  #endif
2824  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
2825  #if defined(C89ATOMIC_HAS_8)
2827  {
2828  c89atomic_uint8 result = 0;
2829  (void)order;
2830  __asm {
2831  mov ecx, dst
2832  mov al, src
2833  lock xadd [ecx], al
2834  mov result, al
2835  }
2836  return result;
2837  }
2838  #endif
2839  #if defined(C89ATOMIC_HAS_16)
2841  {
2842  c89atomic_uint16 result = 0;
2843  (void)order;
2844  __asm {
2845  mov ecx, dst
2846  mov ax, src
2847  lock xadd [ecx], ax
2848  mov result, ax
2849  }
2850  return result;
2851  }
2852  #endif
2853  #if defined(C89ATOMIC_HAS_32)
2855  {
2856  c89atomic_uint32 result = 0;
2857  (void)order;
2858  __asm {
2859  mov ecx, dst
2860  mov eax, src
2861  lock xadd [ecx], eax
2862  mov result, eax
2863  }
2864  return result;
2865  }
2866  #endif
2867  #else
2868  #if defined(C89ATOMIC_HAS_8)
2870  {
2871  (void)order;
2872  return (c89atomic_uint8)_InterlockedExchangeAdd8((volatile char*)dst, (char)src);
2873  }
2874  #endif
2875  #if defined(C89ATOMIC_HAS_16)
2877  {
2878  (void)order;
2879  return (c89atomic_uint16)_InterlockedExchangeAdd16((volatile short*)dst, (short)src);
2880  }
2881  #endif
2882  #if defined(C89ATOMIC_HAS_32)
2884  {
2885  (void)order;
2886  return (c89atomic_uint32)_InterlockedExchangeAdd((volatile long*)dst, (long)src);
2887  }
2888  #endif
2889  #if defined(C89ATOMIC_HAS_64) && defined(C89ATOMIC_64BIT)
2891  {
2892  (void)order;
2893  return (c89atomic_uint64)_InterlockedExchangeAdd64((volatile long long*)dst, (long long)src);
2894  }
2895  #else
2896  #endif
2897  #endif
2898  #if defined(C89ATOMIC_HAS_64) && !defined(C89ATOMIC_64BIT)
2900  {
2901  c89atomic_uint64 oldValue;
2902  c89atomic_uint64 newValue;
2903  do {
2904  oldValue = *dst;
2905  newValue = oldValue + src;
2906  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
2907  (void)order;
2908  return oldValue;
2909  }
2910  #endif
2911  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
2912  static C89ATOMIC_INLINE void __stdcall c89atomic_thread_fence(c89atomic_memory_order order)
2913  {
2914  (void)order;
2915  __asm {
2916  lock add [esp], 0
2917  }
2918  }
2919  #else
2920  #if defined(C89ATOMIC_X64)
2921  #define c89atomic_thread_fence(order) __faststorefence(), (void)order
2922  #else
2923  static C89ATOMIC_INLINE void c89atomic_thread_fence(c89atomic_memory_order order)
2924  {
2925  volatile c89atomic_uint32 barrier = 0;
2926  c89atomic_fetch_add_explicit_32(&barrier, 0, order);
2927  }
2928  #endif
2929  #endif
2930  #define c89atomic_compiler_fence() c89atomic_thread_fence(c89atomic_memory_order_seq_cst)
2931  #define c89atomic_signal_fence(order) c89atomic_thread_fence(order)
2932  #if defined(C89ATOMIC_HAS_8)
2934  {
2935  (void)order;
2936  return c89atomic_compare_and_swap_8((volatile c89atomic_uint8*)ptr, 0, 0);
2937  }
2938  #endif
2939  #if defined(C89ATOMIC_HAS_16)
2941  {
2942  (void)order;
2943  return c89atomic_compare_and_swap_16((volatile c89atomic_uint16*)ptr, 0, 0);
2944  }
2945  #endif
2946  #if defined(C89ATOMIC_HAS_32)
2948  {
2949  (void)order;
2950  return c89atomic_compare_and_swap_32((volatile c89atomic_uint32*)ptr, 0, 0);
2951  }
2952  #endif
2953  #if defined(C89ATOMIC_HAS_64)
2955  {
2956  (void)order;
2957  return c89atomic_compare_and_swap_64((volatile c89atomic_uint64*)ptr, 0, 0);
2958  }
2959  #endif
2960  #if defined(C89ATOMIC_HAS_8)
2961  #define c89atomic_store_explicit_8( dst, src, order) (void)c89atomic_exchange_explicit_8 (dst, src, order)
2962  #endif
2963  #if defined(C89ATOMIC_HAS_16)
2964  #define c89atomic_store_explicit_16(dst, src, order) (void)c89atomic_exchange_explicit_16(dst, src, order)
2965  #endif
2966  #if defined(C89ATOMIC_HAS_32)
2967  #define c89atomic_store_explicit_32(dst, src, order) (void)c89atomic_exchange_explicit_32(dst, src, order)
2968  #endif
2969  #if defined(C89ATOMIC_HAS_64)
2970  #define c89atomic_store_explicit_64(dst, src, order) (void)c89atomic_exchange_explicit_64(dst, src, order)
2971  #endif
2972  #if defined(C89ATOMIC_HAS_8)
2974  {
2975  c89atomic_uint8 oldValue;
2976  c89atomic_uint8 newValue;
2977  do {
2978  oldValue = *dst;
2979  newValue = (c89atomic_uint8)(oldValue - src);
2980  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
2981  (void)order;
2982  return oldValue;
2983  }
2984  #endif
2985  #if defined(C89ATOMIC_HAS_16)
2987  {
2988  c89atomic_uint16 oldValue;
2989  c89atomic_uint16 newValue;
2990  do {
2991  oldValue = *dst;
2992  newValue = (c89atomic_uint16)(oldValue - src);
2993  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
2994  (void)order;
2995  return oldValue;
2996  }
2997  #endif
2998  #if defined(C89ATOMIC_HAS_32)
3000  {
3001  c89atomic_uint32 oldValue;
3002  c89atomic_uint32 newValue;
3003  do {
3004  oldValue = *dst;
3005  newValue = oldValue - src;
3006  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3007  (void)order;
3008  return oldValue;
3009  }
3010  #endif
3011  #if defined(C89ATOMIC_HAS_64)
3013  {
3014  c89atomic_uint64 oldValue;
3015  c89atomic_uint64 newValue;
3016  do {
3017  oldValue = *dst;
3018  newValue = oldValue - src;
3019  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3020  (void)order;
3021  return oldValue;
3022  }
3023  #endif
3024  #if defined(C89ATOMIC_HAS_8)
3026  {
3027  c89atomic_uint8 oldValue;
3028  c89atomic_uint8 newValue;
3029  do {
3030  oldValue = *dst;
3031  newValue = (c89atomic_uint8)(oldValue & src);
3032  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3033  (void)order;
3034  return oldValue;
3035  }
3036  #endif
3037  #if defined(C89ATOMIC_HAS_16)
3039  {
3040  c89atomic_uint16 oldValue;
3041  c89atomic_uint16 newValue;
3042  do {
3043  oldValue = *dst;
3044  newValue = (c89atomic_uint16)(oldValue & src);
3045  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3046  (void)order;
3047  return oldValue;
3048  }
3049  #endif
3050  #if defined(C89ATOMIC_HAS_32)
3052  {
3053  c89atomic_uint32 oldValue;
3054  c89atomic_uint32 newValue;
3055  do {
3056  oldValue = *dst;
3057  newValue = oldValue & src;
3058  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3059  (void)order;
3060  return oldValue;
3061  }
3062  #endif
3063  #if defined(C89ATOMIC_HAS_64)
3065  {
3066  c89atomic_uint64 oldValue;
3067  c89atomic_uint64 newValue;
3068  do {
3069  oldValue = *dst;
3070  newValue = oldValue & src;
3071  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3072  (void)order;
3073  return oldValue;
3074  }
3075  #endif
3076  #if defined(C89ATOMIC_HAS_8)
3078  {
3079  c89atomic_uint8 oldValue;
3080  c89atomic_uint8 newValue;
3081  do {
3082  oldValue = *dst;
3083  newValue = (c89atomic_uint8)(oldValue ^ src);
3084  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3085  (void)order;
3086  return oldValue;
3087  }
3088  #endif
3089  #if defined(C89ATOMIC_HAS_16)
3091  {
3092  c89atomic_uint16 oldValue;
3093  c89atomic_uint16 newValue;
3094  do {
3095  oldValue = *dst;
3096  newValue = (c89atomic_uint16)(oldValue ^ src);
3097  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3098  (void)order;
3099  return oldValue;
3100  }
3101  #endif
3102  #if defined(C89ATOMIC_HAS_32)
3104  {
3105  c89atomic_uint32 oldValue;
3106  c89atomic_uint32 newValue;
3107  do {
3108  oldValue = *dst;
3109  newValue = oldValue ^ src;
3110  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3111  (void)order;
3112  return oldValue;
3113  }
3114  #endif
3115  #if defined(C89ATOMIC_HAS_64)
3117  {
3118  c89atomic_uint64 oldValue;
3119  c89atomic_uint64 newValue;
3120  do {
3121  oldValue = *dst;
3122  newValue = oldValue ^ src;
3123  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3124  (void)order;
3125  return oldValue;
3126  }
3127  #endif
3128  #if defined(C89ATOMIC_HAS_8)
3130  {
3131  c89atomic_uint8 oldValue;
3132  c89atomic_uint8 newValue;
3133  do {
3134  oldValue = *dst;
3135  newValue = (c89atomic_uint8)(oldValue | src);
3136  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3137  (void)order;
3138  return oldValue;
3139  }
3140  #endif
3141  #if defined(C89ATOMIC_HAS_16)
3143  {
3144  c89atomic_uint16 oldValue;
3145  c89atomic_uint16 newValue;
3146  do {
3147  oldValue = *dst;
3148  newValue = (c89atomic_uint16)(oldValue | src);
3149  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3150  (void)order;
3151  return oldValue;
3152  }
3153  #endif
3154  #if defined(C89ATOMIC_HAS_32)
3156  {
3157  c89atomic_uint32 oldValue;
3158  c89atomic_uint32 newValue;
3159  do {
3160  oldValue = *dst;
3161  newValue = oldValue | src;
3162  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3163  (void)order;
3164  return oldValue;
3165  }
3166  #endif
3167  #if defined(C89ATOMIC_HAS_64)
3169  {
3170  c89atomic_uint64 oldValue;
3171  c89atomic_uint64 newValue;
3172  do {
3173  oldValue = *dst;
3174  newValue = oldValue | src;
3175  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3176  (void)order;
3177  return oldValue;
3178  }
3179  #endif
3180  #if defined(C89ATOMIC_HAS_8)
3181  #define c89atomic_test_and_set_explicit_8( dst, order) c89atomic_exchange_explicit_8 (dst, 1, order)
3182  #endif
3183  #if defined(C89ATOMIC_HAS_16)
3184  #define c89atomic_test_and_set_explicit_16(dst, order) c89atomic_exchange_explicit_16(dst, 1, order)
3185  #endif
3186  #if defined(C89ATOMIC_HAS_32)
3187  #define c89atomic_test_and_set_explicit_32(dst, order) c89atomic_exchange_explicit_32(dst, 1, order)
3188  #endif
3189  #if defined(C89ATOMIC_HAS_64)
3190  #define c89atomic_test_and_set_explicit_64(dst, order) c89atomic_exchange_explicit_64(dst, 1, order)
3191  #endif
3192  #if defined(C89ATOMIC_HAS_8)
3193  #define c89atomic_clear_explicit_8( dst, order) c89atomic_store_explicit_8 (dst, 0, order)
3194  #endif
3195  #if defined(C89ATOMIC_HAS_16)
3196  #define c89atomic_clear_explicit_16(dst, order) c89atomic_store_explicit_16(dst, 0, order)
3197  #endif
3198  #if defined(C89ATOMIC_HAS_32)
3199  #define c89atomic_clear_explicit_32(dst, order) c89atomic_store_explicit_32(dst, 0, order)
3200  #endif
3201  #if defined(C89ATOMIC_HAS_64)
3202  #define c89atomic_clear_explicit_64(dst, order) c89atomic_store_explicit_64(dst, 0, order)
3203  #endif
3204  #if defined(C89ATOMIC_HAS_8)
3206  #define c89atomic_flag_test_and_set_explicit(ptr, order) (c89atomic_bool)c89atomic_test_and_set_explicit_8(ptr, order)
3207  #define c89atomic_flag_clear_explicit(ptr, order) c89atomic_clear_explicit_8(ptr, order)
3208  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_8(ptr, order)
3209  #else
3211  #define c89atomic_flag_test_and_set_explicit(ptr, order) (c89atomic_bool)c89atomic_test_and_set_explicit_32(ptr, order)
3212  #define c89atomic_flag_clear_explicit(ptr, order) c89atomic_clear_explicit_32(ptr, order)
3213  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_32(ptr, order)
3214  #endif
3215 #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
3216  #define C89ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE
3217  #define C89ATOMIC_HAS_NATIVE_IS_LOCK_FREE
3218  #define c89atomic_memory_order_relaxed __ATOMIC_RELAXED
3219  #define c89atomic_memory_order_consume __ATOMIC_CONSUME
3220  #define c89atomic_memory_order_acquire __ATOMIC_ACQUIRE
3221  #define c89atomic_memory_order_release __ATOMIC_RELEASE
3222  #define c89atomic_memory_order_acq_rel __ATOMIC_ACQ_REL
3223  #define c89atomic_memory_order_seq_cst __ATOMIC_SEQ_CST
3224  #define c89atomic_compiler_fence() __asm__ __volatile__("":::"memory")
3225  #define c89atomic_thread_fence(order) __atomic_thread_fence(order)
3226  #define c89atomic_signal_fence(order) __atomic_signal_fence(order)
3227  #define c89atomic_is_lock_free_8(ptr) __atomic_is_lock_free(1, ptr)
3228  #define c89atomic_is_lock_free_16(ptr) __atomic_is_lock_free(2, ptr)
3229  #define c89atomic_is_lock_free_32(ptr) __atomic_is_lock_free(4, ptr)
3230  #define c89atomic_is_lock_free_64(ptr) __atomic_is_lock_free(8, ptr)
3231  #define c89atomic_test_and_set_explicit_8( dst, order) __atomic_exchange_n(dst, 1, order)
3232  #define c89atomic_test_and_set_explicit_16(dst, order) __atomic_exchange_n(dst, 1, order)
3233  #define c89atomic_test_and_set_explicit_32(dst, order) __atomic_exchange_n(dst, 1, order)
3234  #define c89atomic_test_and_set_explicit_64(dst, order) __atomic_exchange_n(dst, 1, order)
3235  #define c89atomic_clear_explicit_8( dst, order) __atomic_store_n(dst, 0, order)
3236  #define c89atomic_clear_explicit_16(dst, order) __atomic_store_n(dst, 0, order)
3237  #define c89atomic_clear_explicit_32(dst, order) __atomic_store_n(dst, 0, order)
3238  #define c89atomic_clear_explicit_64(dst, order) __atomic_store_n(dst, 0, order)
3239  #define c89atomic_store_explicit_8( dst, src, order) __atomic_store_n(dst, src, order)
3240  #define c89atomic_store_explicit_16(dst, src, order) __atomic_store_n(dst, src, order)
3241  #define c89atomic_store_explicit_32(dst, src, order) __atomic_store_n(dst, src, order)
3242  #define c89atomic_store_explicit_64(dst, src, order) __atomic_store_n(dst, src, order)
3243  #define c89atomic_load_explicit_8( dst, order) __atomic_load_n(dst, order)
3244  #define c89atomic_load_explicit_16(dst, order) __atomic_load_n(dst, order)
3245  #define c89atomic_load_explicit_32(dst, order) __atomic_load_n(dst, order)
3246  #define c89atomic_load_explicit_64(dst, order) __atomic_load_n(dst, order)
3247  #define c89atomic_exchange_explicit_8( dst, src, order) __atomic_exchange_n(dst, src, order)
3248  #define c89atomic_exchange_explicit_16(dst, src, order) __atomic_exchange_n(dst, src, order)
3249  #define c89atomic_exchange_explicit_32(dst, src, order) __atomic_exchange_n(dst, src, order)
3250  #define c89atomic_exchange_explicit_64(dst, src, order) __atomic_exchange_n(dst, src, order)
3251  #define c89atomic_compare_exchange_strong_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
3252  #define c89atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
3253  #define c89atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
3254  #define c89atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
3255  #define c89atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
3256  #define c89atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
3257  #define c89atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
3258  #define c89atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
3259  #define c89atomic_fetch_add_explicit_8( dst, src, order) __atomic_fetch_add(dst, src, order)
3260  #define c89atomic_fetch_add_explicit_16(dst, src, order) __atomic_fetch_add(dst, src, order)
3261  #define c89atomic_fetch_add_explicit_32(dst, src, order) __atomic_fetch_add(dst, src, order)
3262  #define c89atomic_fetch_add_explicit_64(dst, src, order) __atomic_fetch_add(dst, src, order)
3263  #define c89atomic_fetch_sub_explicit_8( dst, src, order) __atomic_fetch_sub(dst, src, order)
3264  #define c89atomic_fetch_sub_explicit_16(dst, src, order) __atomic_fetch_sub(dst, src, order)
3265  #define c89atomic_fetch_sub_explicit_32(dst, src, order) __atomic_fetch_sub(dst, src, order)
3266  #define c89atomic_fetch_sub_explicit_64(dst, src, order) __atomic_fetch_sub(dst, src, order)
3267  #define c89atomic_fetch_or_explicit_8( dst, src, order) __atomic_fetch_or(dst, src, order)
3268  #define c89atomic_fetch_or_explicit_16(dst, src, order) __atomic_fetch_or(dst, src, order)
3269  #define c89atomic_fetch_or_explicit_32(dst, src, order) __atomic_fetch_or(dst, src, order)
3270  #define c89atomic_fetch_or_explicit_64(dst, src, order) __atomic_fetch_or(dst, src, order)
3271  #define c89atomic_fetch_xor_explicit_8( dst, src, order) __atomic_fetch_xor(dst, src, order)
3272  #define c89atomic_fetch_xor_explicit_16(dst, src, order) __atomic_fetch_xor(dst, src, order)
3273  #define c89atomic_fetch_xor_explicit_32(dst, src, order) __atomic_fetch_xor(dst, src, order)
3274  #define c89atomic_fetch_xor_explicit_64(dst, src, order) __atomic_fetch_xor(dst, src, order)
3275  #define c89atomic_fetch_and_explicit_8( dst, src, order) __atomic_fetch_and(dst, src, order)
3276  #define c89atomic_fetch_and_explicit_16(dst, src, order) __atomic_fetch_and(dst, src, order)
3277  #define c89atomic_fetch_and_explicit_32(dst, src, order) __atomic_fetch_and(dst, src, order)
3278  #define c89atomic_fetch_and_explicit_64(dst, src, order) __atomic_fetch_and(dst, src, order)
3279  #define c89atomic_compare_and_swap_8 (dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3280  #define c89atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3281  #define c89atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3282  #define c89atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3284  #define c89atomic_flag_test_and_set_explicit(dst, order) (c89atomic_bool)__atomic_test_and_set(dst, order)
3285  #define c89atomic_flag_clear_explicit(dst, order) __atomic_clear(dst, order)
3286  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_8(ptr, order)
3287 #else
3288  #define c89atomic_memory_order_relaxed 1
3289  #define c89atomic_memory_order_consume 2
3290  #define c89atomic_memory_order_acquire 3
3291  #define c89atomic_memory_order_release 4
3292  #define c89atomic_memory_order_acq_rel 5
3293  #define c89atomic_memory_order_seq_cst 6
3294  #define c89atomic_compiler_fence() __asm__ __volatile__("":::"memory")
3295  #if defined(__GNUC__)
3296  #define c89atomic_thread_fence(order) __sync_synchronize(), (void)order
3298  {
3299  if (order > c89atomic_memory_order_acquire) {
3300  __sync_synchronize();
3301  }
3302  return __sync_lock_test_and_set(dst, src);
3303  }
3305  {
3306  c89atomic_uint16 oldValue;
3307  do {
3308  oldValue = *dst;
3309  } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
3310  (void)order;
3311  return oldValue;
3312  }
3314  {
3315  c89atomic_uint32 oldValue;
3316  do {
3317  oldValue = *dst;
3318  } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
3319  (void)order;
3320  return oldValue;
3321  }
3323  {
3324  c89atomic_uint64 oldValue;
3325  do {
3326  oldValue = *dst;
3327  } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
3328  (void)order;
3329  return oldValue;
3330  }
3332  {
3333  (void)order;
3334  return __sync_fetch_and_add(dst, src);
3335  }
3337  {
3338  (void)order;
3339  return __sync_fetch_and_add(dst, src);
3340  }
3342  {
3343  (void)order;
3344  return __sync_fetch_and_add(dst, src);
3345  }
3347  {
3348  (void)order;
3349  return __sync_fetch_and_add(dst, src);
3350  }
3352  {
3353  (void)order;
3354  return __sync_fetch_and_sub(dst, src);
3355  }
3357  {
3358  (void)order;
3359  return __sync_fetch_and_sub(dst, src);
3360  }
3362  {
3363  (void)order;
3364  return __sync_fetch_and_sub(dst, src);
3365  }
3367  {
3368  (void)order;
3369  return __sync_fetch_and_sub(dst, src);
3370  }
3372  {
3373  (void)order;
3374  return __sync_fetch_and_or(dst, src);
3375  }
3377  {
3378  (void)order;
3379  return __sync_fetch_and_or(dst, src);
3380  }
3382  {
3383  (void)order;
3384  return __sync_fetch_and_or(dst, src);
3385  }
3387  {
3388  (void)order;
3389  return __sync_fetch_and_or(dst, src);
3390  }
3392  {
3393  (void)order;
3394  return __sync_fetch_and_xor(dst, src);
3395  }
3397  {
3398  (void)order;
3399  return __sync_fetch_and_xor(dst, src);
3400  }
3402  {
3403  (void)order;
3404  return __sync_fetch_and_xor(dst, src);
3405  }
3407  {
3408  (void)order;
3409  return __sync_fetch_and_xor(dst, src);
3410  }
3412  {
3413  (void)order;
3414  return __sync_fetch_and_and(dst, src);
3415  }
3417  {
3418  (void)order;
3419  return __sync_fetch_and_and(dst, src);
3420  }
3422  {
3423  (void)order;
3424  return __sync_fetch_and_and(dst, src);
3425  }
3427  {
3428  (void)order;
3429  return __sync_fetch_and_and(dst, src);
3430  }
3431  #define c89atomic_compare_and_swap_8( dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3432  #define c89atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3433  #define c89atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3434  #define c89atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
3435  #else
3436  #if defined(C89ATOMIC_X86)
3437  #define c89atomic_thread_fence(order) __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory", "cc")
3438  #elif defined(C89ATOMIC_X64)
3439  #define c89atomic_thread_fence(order) __asm__ __volatile__("lock; addq $0, (%%rsp)" ::: "memory", "cc")
3440  #else
3441  #error Unsupported architecture. Please submit a feature request.
3442  #endif
3444  {
3445  c89atomic_uint8 result;
3446  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3447  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
3448  #else
3449  #error Unsupported architecture. Please submit a feature request.
3450  #endif
3451  return result;
3452  }
3454  {
3455  c89atomic_uint16 result;
3456  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3457  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
3458  #else
3459  #error Unsupported architecture. Please submit a feature request.
3460  #endif
3461  return result;
3462  }
3464  {
3465  c89atomic_uint32 result;
3466  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3467  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
3468  #else
3469  #error Unsupported architecture. Please submit a feature request.
3470  #endif
3471  return result;
3472  }
3474  {
3475  volatile c89atomic_uint64 result;
3476  #if defined(C89ATOMIC_X86)
3477  c89atomic_uint32 resultEAX;
3478  c89atomic_uint32 resultEDX;
3479  __asm__ __volatile__("push %%ebx; xchg %5, %%ebx; lock; cmpxchg8b %0; pop %%ebx" : "+m"(*dst), "=a"(resultEAX), "=d"(resultEDX) : "a"(expected & 0xFFFFFFFF), "d"(expected >> 32), "r"(desired & 0xFFFFFFFF), "c"(desired >> 32) : "cc");
3480  result = ((c89atomic_uint64)resultEDX << 32) | resultEAX;
3481  #elif defined(C89ATOMIC_X64)
3482  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
3483  #else
3484  #error Unsupported architecture. Please submit a feature request.
3485  #endif
3486  return result;
3487  }
3489  {
3490  c89atomic_uint8 result = 0;
3491  (void)order;
3492  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3493  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
3494  #else
3495  #error Unsupported architecture. Please submit a feature request.
3496  #endif
3497  return result;
3498  }
3500  {
3501  c89atomic_uint16 result = 0;
3502  (void)order;
3503  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3504  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
3505  #else
3506  #error Unsupported architecture. Please submit a feature request.
3507  #endif
3508  return result;
3509  }
3511  {
3512  c89atomic_uint32 result;
3513  (void)order;
3514  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3515  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
3516  #else
3517  #error Unsupported architecture. Please submit a feature request.
3518  #endif
3519  return result;
3520  }
3522  {
3523  c89atomic_uint64 result;
3524  (void)order;
3525  #if defined(C89ATOMIC_X86)
3526  do {
3527  result = *dst;
3528  } while (c89atomic_compare_and_swap_64(dst, result, src) != result);
3529  #elif defined(C89ATOMIC_X64)
3530  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
3531  #else
3532  #error Unsupported architecture. Please submit a feature request.
3533  #endif
3534  return result;
3535  }
3537  {
3538  c89atomic_uint8 result;
3539  (void)order;
3540  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3541  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
3542  #else
3543  #error Unsupported architecture. Please submit a feature request.
3544  #endif
3545  return result;
3546  }
3548  {
3549  c89atomic_uint16 result;
3550  (void)order;
3551  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3552  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
3553  #else
3554  #error Unsupported architecture. Please submit a feature request.
3555  #endif
3556  return result;
3557  }
3559  {
3560  c89atomic_uint32 result;
3561  (void)order;
3562  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3563  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
3564  #else
3565  #error Unsupported architecture. Please submit a feature request.
3566  #endif
3567  return result;
3568  }
3570  {
3571  #if defined(C89ATOMIC_X86)
3572  c89atomic_uint64 oldValue;
3573  c89atomic_uint64 newValue;
3574  (void)order;
3575  do {
3576  oldValue = *dst;
3577  newValue = oldValue + src;
3578  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3579  return oldValue;
3580  #elif defined(C89ATOMIC_X64)
3581  c89atomic_uint64 result;
3582  (void)order;
3583  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
3584  return result;
3585  #endif
3586  }
3588  {
3589  c89atomic_uint8 oldValue;
3590  c89atomic_uint8 newValue;
3591  do {
3592  oldValue = *dst;
3593  newValue = (c89atomic_uint8)(oldValue - src);
3594  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3595  (void)order;
3596  return oldValue;
3597  }
3599  {
3600  c89atomic_uint16 oldValue;
3601  c89atomic_uint16 newValue;
3602  do {
3603  oldValue = *dst;
3604  newValue = (c89atomic_uint16)(oldValue - src);
3605  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3606  (void)order;
3607  return oldValue;
3608  }
3610  {
3611  c89atomic_uint32 oldValue;
3612  c89atomic_uint32 newValue;
3613  do {
3614  oldValue = *dst;
3615  newValue = oldValue - src;
3616  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3617  (void)order;
3618  return oldValue;
3619  }
3621  {
3622  c89atomic_uint64 oldValue;
3623  c89atomic_uint64 newValue;
3624  do {
3625  oldValue = *dst;
3626  newValue = oldValue - src;
3627  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3628  (void)order;
3629  return oldValue;
3630  }
3632  {
3633  c89atomic_uint8 oldValue;
3634  c89atomic_uint8 newValue;
3635  do {
3636  oldValue = *dst;
3637  newValue = (c89atomic_uint8)(oldValue & src);
3638  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3639  (void)order;
3640  return oldValue;
3641  }
3643  {
3644  c89atomic_uint16 oldValue;
3645  c89atomic_uint16 newValue;
3646  do {
3647  oldValue = *dst;
3648  newValue = (c89atomic_uint16)(oldValue & src);
3649  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3650  (void)order;
3651  return oldValue;
3652  }
3654  {
3655  c89atomic_uint32 oldValue;
3656  c89atomic_uint32 newValue;
3657  do {
3658  oldValue = *dst;
3659  newValue = oldValue & src;
3660  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3661  (void)order;
3662  return oldValue;
3663  }
3665  {
3666  c89atomic_uint64 oldValue;
3667  c89atomic_uint64 newValue;
3668  do {
3669  oldValue = *dst;
3670  newValue = oldValue & src;
3671  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3672  (void)order;
3673  return oldValue;
3674  }
3676  {
3677  c89atomic_uint8 oldValue;
3678  c89atomic_uint8 newValue;
3679  do {
3680  oldValue = *dst;
3681  newValue = (c89atomic_uint8)(oldValue ^ src);
3682  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3683  (void)order;
3684  return oldValue;
3685  }
3687  {
3688  c89atomic_uint16 oldValue;
3689  c89atomic_uint16 newValue;
3690  do {
3691  oldValue = *dst;
3692  newValue = (c89atomic_uint16)(oldValue ^ src);
3693  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3694  (void)order;
3695  return oldValue;
3696  }
3698  {
3699  c89atomic_uint32 oldValue;
3700  c89atomic_uint32 newValue;
3701  do {
3702  oldValue = *dst;
3703  newValue = oldValue ^ src;
3704  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3705  (void)order;
3706  return oldValue;
3707  }
3709  {
3710  c89atomic_uint64 oldValue;
3711  c89atomic_uint64 newValue;
3712  do {
3713  oldValue = *dst;
3714  newValue = oldValue ^ src;
3715  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3716  (void)order;
3717  return oldValue;
3718  }
3720  {
3721  c89atomic_uint8 oldValue;
3722  c89atomic_uint8 newValue;
3723  do {
3724  oldValue = *dst;
3725  newValue = (c89atomic_uint8)(oldValue | src);
3726  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
3727  (void)order;
3728  return oldValue;
3729  }
3731  {
3732  c89atomic_uint16 oldValue;
3733  c89atomic_uint16 newValue;
3734  do {
3735  oldValue = *dst;
3736  newValue = (c89atomic_uint16)(oldValue | src);
3737  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
3738  (void)order;
3739  return oldValue;
3740  }
3742  {
3743  c89atomic_uint32 oldValue;
3744  c89atomic_uint32 newValue;
3745  do {
3746  oldValue = *dst;
3747  newValue = oldValue | src;
3748  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
3749  (void)order;
3750  return oldValue;
3751  }
3753  {
3754  c89atomic_uint64 oldValue;
3755  c89atomic_uint64 newValue;
3756  do {
3757  oldValue = *dst;
3758  newValue = oldValue | src;
3759  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
3760  (void)order;
3761  return oldValue;
3762  }
3763  #endif
3764  #define c89atomic_signal_fence(order) c89atomic_thread_fence(order)
3766  {
3767  (void)order;
3768  return c89atomic_compare_and_swap_8((c89atomic_uint8*)ptr, 0, 0);
3769  }
3771  {
3772  (void)order;
3773  return c89atomic_compare_and_swap_16((c89atomic_uint16*)ptr, 0, 0);
3774  }
3776  {
3777  (void)order;
3778  return c89atomic_compare_and_swap_32((c89atomic_uint32*)ptr, 0, 0);
3779  }
3781  {
3782  (void)order;
3783  return c89atomic_compare_and_swap_64((c89atomic_uint64*)ptr, 0, 0);
3784  }
3785  #define c89atomic_store_explicit_8( dst, src, order) (void)c89atomic_exchange_explicit_8 (dst, src, order)
3786  #define c89atomic_store_explicit_16(dst, src, order) (void)c89atomic_exchange_explicit_16(dst, src, order)
3787  #define c89atomic_store_explicit_32(dst, src, order) (void)c89atomic_exchange_explicit_32(dst, src, order)
3788  #define c89atomic_store_explicit_64(dst, src, order) (void)c89atomic_exchange_explicit_64(dst, src, order)
3789  #define c89atomic_test_and_set_explicit_8( dst, order) c89atomic_exchange_explicit_8 (dst, 1, order)
3790  #define c89atomic_test_and_set_explicit_16(dst, order) c89atomic_exchange_explicit_16(dst, 1, order)
3791  #define c89atomic_test_and_set_explicit_32(dst, order) c89atomic_exchange_explicit_32(dst, 1, order)
3792  #define c89atomic_test_and_set_explicit_64(dst, order) c89atomic_exchange_explicit_64(dst, 1, order)
3793  #define c89atomic_clear_explicit_8( dst, order) c89atomic_store_explicit_8 (dst, 0, order)
3794  #define c89atomic_clear_explicit_16(dst, order) c89atomic_store_explicit_16(dst, 0, order)
3795  #define c89atomic_clear_explicit_32(dst, order) c89atomic_store_explicit_32(dst, 0, order)
3796  #define c89atomic_clear_explicit_64(dst, order) c89atomic_store_explicit_64(dst, 0, order)
3798  #define c89atomic_flag_test_and_set_explicit(ptr, order) (c89atomic_bool)c89atomic_test_and_set_explicit_8(ptr, order)
3799  #define c89atomic_flag_clear_explicit(ptr, order) c89atomic_clear_explicit_8(ptr, order)
3800  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_8(ptr, order)
3801 #endif
3802 #if !defined(C89ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE)
3803  #if defined(C89ATOMIC_HAS_8)
3805  {
3806  c89atomic_uint8 expectedValue;
3807  c89atomic_uint8 result;
3808  (void)successOrder;
3809  (void)failureOrder;
3810  expectedValue = c89atomic_load_explicit_8(expected, c89atomic_memory_order_seq_cst);
3811  result = c89atomic_compare_and_swap_8(dst, expectedValue, desired);
3812  if (result == expectedValue) {
3813  return 1;
3814  } else {
3815  c89atomic_store_explicit_8(expected, result, failureOrder);
3816  return 0;
3817  }
3818  }
3819  #endif
3820  #if defined(C89ATOMIC_HAS_16)
3822  {
3823  c89atomic_uint16 expectedValue;
3824  c89atomic_uint16 result;
3825  (void)successOrder;
3826  (void)failureOrder;
3828  result = c89atomic_compare_and_swap_16(dst, expectedValue, desired);
3829  if (result == expectedValue) {
3830  return 1;
3831  } else {
3832  c89atomic_store_explicit_16(expected, result, failureOrder);
3833  return 0;
3834  }
3835  }
3836  #endif
3837  #if defined(C89ATOMIC_HAS_32)
3839  {
3840  c89atomic_uint32 expectedValue;
3841  c89atomic_uint32 result;
3842  (void)successOrder;
3843  (void)failureOrder;
3845  result = c89atomic_compare_and_swap_32(dst, expectedValue, desired);
3846  if (result == expectedValue) {
3847  return 1;
3848  } else {
3849  c89atomic_store_explicit_32(expected, result, failureOrder);
3850  return 0;
3851  }
3852  }
3853  #endif
3854  #if defined(C89ATOMIC_HAS_64)
3856  {
3857  c89atomic_uint64 expectedValue;
3858  c89atomic_uint64 result;
3859  (void)successOrder;
3860  (void)failureOrder;
3862  result = c89atomic_compare_and_swap_64(dst, expectedValue, desired);
3863  if (result == expectedValue) {
3864  return 1;
3865  } else {
3866  c89atomic_store_explicit_64(expected, result, failureOrder);
3867  return 0;
3868  }
3869  }
3870  #endif
3871  #define c89atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_8 (dst, expected, desired, successOrder, failureOrder)
3872  #define c89atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder)
3873  #define c89atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder)
3874  #define c89atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder)
3875 #endif
3876 #if !defined(C89ATOMIC_HAS_NATIVE_IS_LOCK_FREE)
3878  {
3879  (void)ptr;
3880  return 1;
3881  }
3883  {
3884  (void)ptr;
3885  return 1;
3886  }
3888  {
3889  (void)ptr;
3890  return 1;
3891  }
3893  {
3894  (void)ptr;
3895  #if defined(C89ATOMIC_64BIT)
3896  return 1;
3897  #else
3898  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
3899  return 1;
3900  #else
3901  return 0;
3902  #endif
3903  #endif
3904  }
3905 #endif
3906 #if defined(C89ATOMIC_64BIT)
3908  {
3909  return c89atomic_is_lock_free_64((volatile c89atomic_uint64*)ptr);
3910  }
3912  {
3913  return (void*)c89atomic_load_explicit_64((volatile c89atomic_uint64*)ptr, order);
3914  }
3915  static C89ATOMIC_INLINE void c89atomic_store_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
3916  {
3917  c89atomic_store_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64)src, order);
3918  }
3919  static C89ATOMIC_INLINE void* c89atomic_exchange_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
3920  {
3921  return (void*)c89atomic_exchange_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64)src, order);
3922  }
3923  static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, volatile void** expected, void* desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
3924  {
3925  return c89atomic_compare_exchange_strong_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64*)expected, (c89atomic_uint64)desired, successOrder, failureOrder);
3926  }
3927  static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, volatile void** expected, void* desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
3928  {
3929  return c89atomic_compare_exchange_weak_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64*)expected, (c89atomic_uint64)desired, successOrder, failureOrder);
3930  }
3931  static C89ATOMIC_INLINE void* c89atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired)
3932  {
3933  return (void*)c89atomic_compare_and_swap_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64)expected, (c89atomic_uint64)desired);
3934  }
3935 #elif defined(C89ATOMIC_32BIT)
3936  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_ptr(volatile void** ptr)
3937  {
3938  return c89atomic_is_lock_free_32((volatile c89atomic_uint32*)ptr);
3939  }
3940  static C89ATOMIC_INLINE void* c89atomic_load_explicit_ptr(volatile void** ptr, c89atomic_memory_order order)
3941  {
3942  return (void*)c89atomic_load_explicit_32((volatile c89atomic_uint32*)ptr, order);
3943  }
3944  static C89ATOMIC_INLINE void c89atomic_store_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
3945  {
3946  c89atomic_store_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32)src, order);
3947  }
3948  static C89ATOMIC_INLINE void* c89atomic_exchange_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
3949  {
3950  return (void*)c89atomic_exchange_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32)src, order);
3951  }
3952  static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
3953  {
3954  return c89atomic_compare_exchange_strong_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32*)expected, (c89atomic_uint32)desired, successOrder, failureOrder);
3955  }
3956  static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, volatile void** expected, void* desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
3957  {
3958  return c89atomic_compare_exchange_weak_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32*)expected, (c89atomic_uint32)desired, successOrder, failureOrder);
3959  }
3960  static C89ATOMIC_INLINE void* c89atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired)
3961  {
3962  return (void*)c89atomic_compare_and_swap_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32)expected, (c89atomic_uint32)desired);
3963  }
3964 #else
3965  #error Unsupported architecture.
3966 #endif
3967 #define c89atomic_flag_test_and_set(ptr) c89atomic_flag_test_and_set_explicit(ptr, c89atomic_memory_order_seq_cst)
3968 #define c89atomic_flag_clear(ptr) c89atomic_flag_clear_explicit(ptr, c89atomic_memory_order_seq_cst)
3969 #define c89atomic_store_ptr(dst, src) c89atomic_store_explicit_ptr((volatile void**)dst, (void*)src, c89atomic_memory_order_seq_cst)
3970 #define c89atomic_load_ptr(ptr) c89atomic_load_explicit_ptr((volatile void**)ptr, c89atomic_memory_order_seq_cst)
3971 #define c89atomic_exchange_ptr(dst, src) c89atomic_exchange_explicit_ptr((volatile void**)dst, (void*)src, c89atomic_memory_order_seq_cst)
3972 #define c89atomic_compare_exchange_strong_ptr(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_ptr((volatile void**)dst, (volatile void**)expected, (void*)desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3973 #define c89atomic_compare_exchange_weak_ptr(dst, expected, desired) c89atomic_compare_exchange_weak_explicit_ptr((volatile void**)dst, (volatile void**)expected, (void*)desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3974 #define c89atomic_test_and_set_8( ptr) c89atomic_test_and_set_explicit_8( ptr, c89atomic_memory_order_seq_cst)
3975 #define c89atomic_test_and_set_16(ptr) c89atomic_test_and_set_explicit_16(ptr, c89atomic_memory_order_seq_cst)
3976 #define c89atomic_test_and_set_32(ptr) c89atomic_test_and_set_explicit_32(ptr, c89atomic_memory_order_seq_cst)
3977 #define c89atomic_test_and_set_64(ptr) c89atomic_test_and_set_explicit_64(ptr, c89atomic_memory_order_seq_cst)
3978 #define c89atomic_clear_8( ptr) c89atomic_clear_explicit_8( ptr, c89atomic_memory_order_seq_cst)
3979 #define c89atomic_clear_16(ptr) c89atomic_clear_explicit_16(ptr, c89atomic_memory_order_seq_cst)
3980 #define c89atomic_clear_32(ptr) c89atomic_clear_explicit_32(ptr, c89atomic_memory_order_seq_cst)
3981 #define c89atomic_clear_64(ptr) c89atomic_clear_explicit_64(ptr, c89atomic_memory_order_seq_cst)
3982 #define c89atomic_store_8( dst, src) c89atomic_store_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
3983 #define c89atomic_store_16(dst, src) c89atomic_store_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
3984 #define c89atomic_store_32(dst, src) c89atomic_store_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
3985 #define c89atomic_store_64(dst, src) c89atomic_store_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
3986 #define c89atomic_load_8( ptr) c89atomic_load_explicit_8( ptr, c89atomic_memory_order_seq_cst)
3987 #define c89atomic_load_16(ptr) c89atomic_load_explicit_16(ptr, c89atomic_memory_order_seq_cst)
3988 #define c89atomic_load_32(ptr) c89atomic_load_explicit_32(ptr, c89atomic_memory_order_seq_cst)
3989 #define c89atomic_load_64(ptr) c89atomic_load_explicit_64(ptr, c89atomic_memory_order_seq_cst)
3990 #define c89atomic_exchange_8( dst, src) c89atomic_exchange_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
3991 #define c89atomic_exchange_16(dst, src) c89atomic_exchange_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
3992 #define c89atomic_exchange_32(dst, src) c89atomic_exchange_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
3993 #define c89atomic_exchange_64(dst, src) c89atomic_exchange_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
3994 #define c89atomic_compare_exchange_strong_8( dst, expected, desired) c89atomic_compare_exchange_strong_explicit_8( dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3995 #define c89atomic_compare_exchange_strong_16(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_16(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3996 #define c89atomic_compare_exchange_strong_32(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_32(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3997 #define c89atomic_compare_exchange_strong_64(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_64(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3998 #define c89atomic_compare_exchange_weak_8( dst, expected, desired) c89atomic_compare_exchange_weak_explicit_8( dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
3999 #define c89atomic_compare_exchange_weak_16( dst, expected, desired) c89atomic_compare_exchange_weak_explicit_16(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4000 #define c89atomic_compare_exchange_weak_32( dst, expected, desired) c89atomic_compare_exchange_weak_explicit_32(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4001 #define c89atomic_compare_exchange_weak_64( dst, expected, desired) c89atomic_compare_exchange_weak_explicit_64(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4002 #define c89atomic_fetch_add_8( dst, src) c89atomic_fetch_add_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
4003 #define c89atomic_fetch_add_16(dst, src) c89atomic_fetch_add_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
4004 #define c89atomic_fetch_add_32(dst, src) c89atomic_fetch_add_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
4005 #define c89atomic_fetch_add_64(dst, src) c89atomic_fetch_add_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
4006 #define c89atomic_fetch_sub_8( dst, src) c89atomic_fetch_sub_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
4007 #define c89atomic_fetch_sub_16(dst, src) c89atomic_fetch_sub_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
4008 #define c89atomic_fetch_sub_32(dst, src) c89atomic_fetch_sub_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
4009 #define c89atomic_fetch_sub_64(dst, src) c89atomic_fetch_sub_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
4010 #define c89atomic_fetch_or_8( dst, src) c89atomic_fetch_or_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
4011 #define c89atomic_fetch_or_16(dst, src) c89atomic_fetch_or_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
4012 #define c89atomic_fetch_or_32(dst, src) c89atomic_fetch_or_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
4013 #define c89atomic_fetch_or_64(dst, src) c89atomic_fetch_or_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
4014 #define c89atomic_fetch_xor_8( dst, src) c89atomic_fetch_xor_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
4015 #define c89atomic_fetch_xor_16(dst, src) c89atomic_fetch_xor_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
4016 #define c89atomic_fetch_xor_32(dst, src) c89atomic_fetch_xor_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
4017 #define c89atomic_fetch_xor_64(dst, src) c89atomic_fetch_xor_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
4018 #define c89atomic_fetch_and_8( dst, src) c89atomic_fetch_and_explicit_8 (dst, src, c89atomic_memory_order_seq_cst)
4019 #define c89atomic_fetch_and_16(dst, src) c89atomic_fetch_and_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
4020 #define c89atomic_fetch_and_32(dst, src) c89atomic_fetch_and_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
4021 #define c89atomic_fetch_and_64(dst, src) c89atomic_fetch_and_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
4022 #define c89atomic_test_and_set_explicit_i8( ptr, order) (c89atomic_int8 )c89atomic_test_and_set_explicit_8( (c89atomic_uint8* )ptr, order)
4023 #define c89atomic_test_and_set_explicit_i16(ptr, order) (c89atomic_int16)c89atomic_test_and_set_explicit_16((c89atomic_uint16*)ptr, order)
4024 #define c89atomic_test_and_set_explicit_i32(ptr, order) (c89atomic_int32)c89atomic_test_and_set_explicit_32((c89atomic_uint32*)ptr, order)
4025 #define c89atomic_test_and_set_explicit_i64(ptr, order) (c89atomic_int64)c89atomic_test_and_set_explicit_64((c89atomic_uint64*)ptr, order)
4026 #define c89atomic_clear_explicit_i8( ptr, order) c89atomic_clear_explicit_8( (c89atomic_uint8* )ptr, order)
4027 #define c89atomic_clear_explicit_i16(ptr, order) c89atomic_clear_explicit_16((c89atomic_uint16*)ptr, order)
4028 #define c89atomic_clear_explicit_i32(ptr, order) c89atomic_clear_explicit_32((c89atomic_uint32*)ptr, order)
4029 #define c89atomic_clear_explicit_i64(ptr, order) c89atomic_clear_explicit_64((c89atomic_uint64*)ptr, order)
4030 #define c89atomic_store_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_store_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4031 #define c89atomic_store_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_store_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4032 #define c89atomic_store_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_store_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4033 #define c89atomic_store_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_store_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4034 #define c89atomic_load_explicit_i8( ptr, order) (c89atomic_int8 )c89atomic_load_explicit_8( (c89atomic_uint8* )ptr, order)
4035 #define c89atomic_load_explicit_i16(ptr, order) (c89atomic_int16)c89atomic_load_explicit_16((c89atomic_uint16*)ptr, order)
4036 #define c89atomic_load_explicit_i32(ptr, order) (c89atomic_int32)c89atomic_load_explicit_32((c89atomic_uint32*)ptr, order)
4037 #define c89atomic_load_explicit_i64(ptr, order) (c89atomic_int64)c89atomic_load_explicit_64((c89atomic_uint64*)ptr, order)
4038 #define c89atomic_exchange_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_exchange_explicit_8 ((c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4039 #define c89atomic_exchange_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_exchange_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4040 #define c89atomic_exchange_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_exchange_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4041 #define c89atomic_exchange_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_exchange_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4042 #define c89atomic_compare_exchange_strong_explicit_i8( dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8* )expected, (c89atomic_uint8 )desired, successOrder, failureOrder)
4043 #define c89atomic_compare_exchange_strong_explicit_i16(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16*)expected, (c89atomic_uint16)desired, successOrder, failureOrder)
4044 #define c89atomic_compare_exchange_strong_explicit_i32(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32*)expected, (c89atomic_uint32)desired, successOrder, failureOrder)
4045 #define c89atomic_compare_exchange_strong_explicit_i64(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64*)expected, (c89atomic_uint64)desired, successOrder, failureOrder)
4046 #define c89atomic_compare_exchange_weak_explicit_i8( dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_weak_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8* )expected, (c89atomic_uint8 )desired, successOrder, failureOrder)
4047 #define c89atomic_compare_exchange_weak_explicit_i16(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_weak_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16*)expected, (c89atomic_uint16)desired, successOrder, failureOrder)
4048 #define c89atomic_compare_exchange_weak_explicit_i32(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_weak_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32*)expected, (c89atomic_uint32)desired, successOrder, failureOrder)
4049 #define c89atomic_compare_exchange_weak_explicit_i64(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_weak_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64*)expected, (c89atomic_uint64)desired, successOrder, failureOrder)
4050 #define c89atomic_fetch_add_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_add_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4051 #define c89atomic_fetch_add_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_add_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4052 #define c89atomic_fetch_add_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_add_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4053 #define c89atomic_fetch_add_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_add_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4054 #define c89atomic_fetch_sub_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_sub_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4055 #define c89atomic_fetch_sub_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_sub_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4056 #define c89atomic_fetch_sub_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_sub_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4057 #define c89atomic_fetch_sub_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_sub_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4058 #define c89atomic_fetch_or_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_or_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4059 #define c89atomic_fetch_or_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_or_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4060 #define c89atomic_fetch_or_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_or_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4061 #define c89atomic_fetch_or_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_or_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4062 #define c89atomic_fetch_xor_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_xor_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4063 #define c89atomic_fetch_xor_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_xor_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4064 #define c89atomic_fetch_xor_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_xor_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4065 #define c89atomic_fetch_xor_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_xor_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4066 #define c89atomic_fetch_and_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_and_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
4067 #define c89atomic_fetch_and_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_and_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
4068 #define c89atomic_fetch_and_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_and_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
4069 #define c89atomic_fetch_and_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_and_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
4070 #define c89atomic_test_and_set_i8( ptr) c89atomic_test_and_set_explicit_i8( ptr, c89atomic_memory_order_seq_cst)
4071 #define c89atomic_test_and_set_i16(ptr) c89atomic_test_and_set_explicit_i16(ptr, c89atomic_memory_order_seq_cst)
4072 #define c89atomic_test_and_set_i32(ptr) c89atomic_test_and_set_explicit_i32(ptr, c89atomic_memory_order_seq_cst)
4073 #define c89atomic_test_and_set_i64(ptr) c89atomic_test_and_set_explicit_i64(ptr, c89atomic_memory_order_seq_cst)
4074 #define c89atomic_clear_i8( ptr) c89atomic_clear_explicit_i8( ptr, c89atomic_memory_order_seq_cst)
4075 #define c89atomic_clear_i16(ptr) c89atomic_clear_explicit_i16(ptr, c89atomic_memory_order_seq_cst)
4076 #define c89atomic_clear_i32(ptr) c89atomic_clear_explicit_i32(ptr, c89atomic_memory_order_seq_cst)
4077 #define c89atomic_clear_i64(ptr) c89atomic_clear_explicit_i64(ptr, c89atomic_memory_order_seq_cst)
4078 #define c89atomic_store_i8( dst, src) c89atomic_store_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4079 #define c89atomic_store_i16(dst, src) c89atomic_store_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4080 #define c89atomic_store_i32(dst, src) c89atomic_store_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4081 #define c89atomic_store_i64(dst, src) c89atomic_store_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4082 #define c89atomic_load_i8( ptr) c89atomic_load_explicit_i8( ptr, c89atomic_memory_order_seq_cst)
4083 #define c89atomic_load_i16(ptr) c89atomic_load_explicit_i16(ptr, c89atomic_memory_order_seq_cst)
4084 #define c89atomic_load_i32(ptr) c89atomic_load_explicit_i32(ptr, c89atomic_memory_order_seq_cst)
4085 #define c89atomic_load_i64(ptr) c89atomic_load_explicit_i64(ptr, c89atomic_memory_order_seq_cst)
4086 #define c89atomic_exchange_i8( dst, src) c89atomic_exchange_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4087 #define c89atomic_exchange_i16(dst, src) c89atomic_exchange_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4088 #define c89atomic_exchange_i32(dst, src) c89atomic_exchange_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4089 #define c89atomic_exchange_i64(dst, src) c89atomic_exchange_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4090 #define c89atomic_compare_exchange_strong_i8( dst, expected, desired) c89atomic_compare_exchange_strong_explicit_i8( dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4091 #define c89atomic_compare_exchange_strong_i16(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_i16(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4092 #define c89atomic_compare_exchange_strong_i32(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_i32(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4093 #define c89atomic_compare_exchange_strong_i64(dst, expected, desired) c89atomic_compare_exchange_strong_explicit_i64(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4094 #define c89atomic_compare_exchange_weak_i8( dst, expected, desired) c89atomic_compare_exchange_weak_explicit_i8( dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4095 #define c89atomic_compare_exchange_weak_i16(dst, expected, desired) c89atomic_compare_exchange_weak_explicit_i16(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4096 #define c89atomic_compare_exchange_weak_i32(dst, expected, desired) c89atomic_compare_exchange_weak_explicit_i32(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4097 #define c89atomic_compare_exchange_weak_i64(dst, expected, desired) c89atomic_compare_exchange_weak_explicit_i64(dst, expected, desired, c89atomic_memory_order_seq_cst, c89atomic_memory_order_seq_cst)
4098 #define c89atomic_fetch_add_i8( dst, src) c89atomic_fetch_add_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4099 #define c89atomic_fetch_add_i16(dst, src) c89atomic_fetch_add_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4100 #define c89atomic_fetch_add_i32(dst, src) c89atomic_fetch_add_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4101 #define c89atomic_fetch_add_i64(dst, src) c89atomic_fetch_add_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4102 #define c89atomic_fetch_sub_i8( dst, src) c89atomic_fetch_sub_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4103 #define c89atomic_fetch_sub_i16(dst, src) c89atomic_fetch_sub_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4104 #define c89atomic_fetch_sub_i32(dst, src) c89atomic_fetch_sub_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4105 #define c89atomic_fetch_sub_i64(dst, src) c89atomic_fetch_sub_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4106 #define c89atomic_fetch_or_i8( dst, src) c89atomic_fetch_or_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4107 #define c89atomic_fetch_or_i16(dst, src) c89atomic_fetch_or_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4108 #define c89atomic_fetch_or_i32(dst, src) c89atomic_fetch_or_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4109 #define c89atomic_fetch_or_i64(dst, src) c89atomic_fetch_or_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4110 #define c89atomic_fetch_xor_i8( dst, src) c89atomic_fetch_xor_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4111 #define c89atomic_fetch_xor_i16(dst, src) c89atomic_fetch_xor_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4112 #define c89atomic_fetch_xor_i32(dst, src) c89atomic_fetch_xor_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4113 #define c89atomic_fetch_xor_i64(dst, src) c89atomic_fetch_xor_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4114 #define c89atomic_fetch_and_i8( dst, src) c89atomic_fetch_and_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
4115 #define c89atomic_fetch_and_i16(dst, src) c89atomic_fetch_and_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
4116 #define c89atomic_fetch_and_i32(dst, src) c89atomic_fetch_and_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
4117 #define c89atomic_fetch_and_i64(dst, src) c89atomic_fetch_and_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
4118 typedef union
4119 {
4121  float f;
4122 } c89atomic_if32;
4123 typedef union
4124 {
4126  double f;
4127 } c89atomic_if64;
4128 #define c89atomic_clear_explicit_f32(ptr, order) c89atomic_clear_explicit_32((c89atomic_uint32*)ptr, order)
4129 #define c89atomic_clear_explicit_f64(ptr, order) c89atomic_clear_explicit_64((c89atomic_uint64*)ptr, order)
4130 static C89ATOMIC_INLINE void c89atomic_store_explicit_f32(volatile float* dst, float src, c89atomic_memory_order order)
4131 {
4132  c89atomic_if32 x;
4133  x.f = src;
4134  c89atomic_store_explicit_32((volatile c89atomic_uint32*)dst, x.i, order);
4135 }
4136 static C89ATOMIC_INLINE void c89atomic_store_explicit_f64(volatile double* dst, double src, c89atomic_memory_order order)
4137 {
4138  c89atomic_if64 x;
4139  x.f = src;
4140  c89atomic_store_explicit_64((volatile c89atomic_uint64*)dst, x.i, order);
4141 }
4143 {
4144  c89atomic_if32 r;
4145  r.i = c89atomic_load_explicit_32((volatile c89atomic_uint32*)ptr, order);
4146  return r.f;
4147 }
4148 static C89ATOMIC_INLINE double c89atomic_load_explicit_f64(volatile double* ptr, c89atomic_memory_order order)
4149 {
4150  c89atomic_if64 r;
4151  r.i = c89atomic_load_explicit_64((volatile c89atomic_uint64*)ptr, order);
4152  return r.f;
4153 }
4154 static C89ATOMIC_INLINE float c89atomic_exchange_explicit_f32(volatile float* dst, float src, c89atomic_memory_order order)
4155 {
4156  c89atomic_if32 r;
4157  c89atomic_if32 x;
4158  x.f = src;
4159  r.i = c89atomic_exchange_explicit_32((volatile c89atomic_uint32*)dst, x.i, order);
4160  return r.f;
4161 }
4162 static C89ATOMIC_INLINE double c89atomic_exchange_explicit_f64(volatile double* dst, double src, c89atomic_memory_order order)
4163 {
4164  c89atomic_if64 r;
4165  c89atomic_if64 x;
4166  x.f = src;
4167  r.i = c89atomic_exchange_explicit_64((volatile c89atomic_uint64*)dst, x.i, order);
4168  return r.f;
4169 }
4170 #define c89atomic_clear_f32(ptr) (float )c89atomic_clear_explicit_f32(ptr, c89atomic_memory_order_seq_cst)
4171 #define c89atomic_clear_f64(ptr) (double)c89atomic_clear_explicit_f64(ptr, c89atomic_memory_order_seq_cst)
4172 #define c89atomic_store_f32(dst, src) c89atomic_store_explicit_f32(dst, src, c89atomic_memory_order_seq_cst)
4173 #define c89atomic_store_f64(dst, src) c89atomic_store_explicit_f64(dst, src, c89atomic_memory_order_seq_cst)
4174 #define c89atomic_load_f32(ptr) (float )c89atomic_load_explicit_f32(ptr, c89atomic_memory_order_seq_cst)
4175 #define c89atomic_load_f64(ptr) (double)c89atomic_load_explicit_f64(ptr, c89atomic_memory_order_seq_cst)
4176 #define c89atomic_exchange_f32(dst, src) (float )c89atomic_exchange_explicit_f32(dst, src, c89atomic_memory_order_seq_cst)
4177 #define c89atomic_exchange_f64(dst, src) (double)c89atomic_exchange_explicit_f64(dst, src, c89atomic_memory_order_seq_cst)
4180 {
4181  for (;;) {
4183  break;
4184  }
4186  }
4187  }
4188 }
4190 {
4192 }
4193 #if defined(__cplusplus)
4194 }
4195 #endif
4196 #endif
4197 /* c89atomic.h end */
4198 
4199 
4200 
4202 {
4203  /* For robustness we're going to use a resampler object to calculate this since that already has a way of calculating this. */
4204  ma_result result;
4205  ma_uint64 frameCountOut;
4207  ma_resampler resampler;
4208 
4209  if (sampleRateOut == sampleRateIn) {
4210  return frameCountIn;
4211  }
4212 
4213  config = ma_resampler_config_init(ma_format_s16, 1, sampleRateIn, sampleRateOut, ma_resample_algorithm_linear);
4214  result = ma_resampler_init(&config, &resampler);
4215  if (result != MA_SUCCESS) {
4216  return 0;
4217  }
4218 
4219  frameCountOut = ma_resampler_get_expected_output_frame_count(&resampler, frameCountIn);
4220 
4221  ma_resampler_uninit(&resampler);
4222  return frameCountOut;
4223 }
4224 
4225 #ifndef MA_DATA_CONVERTER_STACK_BUFFER_SIZE
4226 #define MA_DATA_CONVERTER_STACK_BUFFER_SIZE 4096
4227 #endif
4228 
4229 
4230 
4231 #if defined(MA_WIN32)
4232 static ma_result ma_result_from_GetLastError(DWORD error)
4233 {
4234  switch (error)
4235  {
4236  case ERROR_SUCCESS: return MA_SUCCESS;
4237  case ERROR_PATH_NOT_FOUND: return MA_DOES_NOT_EXIST;
4238  case ERROR_TOO_MANY_OPEN_FILES: return MA_TOO_MANY_OPEN_FILES;
4239  case ERROR_NOT_ENOUGH_MEMORY: return MA_OUT_OF_MEMORY;
4240  case ERROR_DISK_FULL: return MA_NO_SPACE;
4241  case ERROR_HANDLE_EOF: return MA_AT_END;
4242  case ERROR_NEGATIVE_SEEK: return MA_BAD_SEEK;
4243  case ERROR_INVALID_PARAMETER: return MA_INVALID_ARGS;
4244  case ERROR_ACCESS_DENIED: return MA_ACCESS_DENIED;
4245  case ERROR_SEM_TIMEOUT: return MA_TIMEOUT;
4246  case ERROR_FILE_NOT_FOUND: return MA_DOES_NOT_EXIST;
4247  default: break;
4248  }
4249 
4250  return MA_ERROR;
4251 }
4252 #endif /* MA_WIN32 */
4253 
4254 
4255 /*******************************************************************************
4256 
4257 Threading
4258 
4259 *******************************************************************************/
4260 #ifndef MA_NO_THREADING
4261 #ifdef MA_WIN32
4262  #define MA_THREADCALL WINAPI
4263  typedef unsigned long ma_thread_result;
4264 #else
4265  #define MA_THREADCALL
4266  typedef void* ma_thread_result;
4267 #endif
4269 
4271 {
4272  if (pSpinlock == NULL) {
4273  return MA_INVALID_ARGS;
4274  }
4275 
4276  for (;;) {
4278  break;
4279  }
4280 
4282  if (yield) {
4283  ma_yield();
4284  }
4285  }
4286  }
4287 
4288  return MA_SUCCESS;
4289 }
4290 
4292 {
4293  return ma_spinlock_lock_ex(pSpinlock, MA_TRUE);
4294 }
4295 
4297 {
4298  return ma_spinlock_lock_ex(pSpinlock, MA_FALSE);
4299 }
4300 
4302 {
4303  if (pSpinlock == NULL) {
4304  return MA_INVALID_ARGS;
4305  }
4306 
4308  return MA_SUCCESS;
4309 }
4310 
4311 #ifdef MA_WIN32
4312 static int ma_thread_priority_to_win32(ma_thread_priority priority)
4313 {
4314  switch (priority) {
4315  case ma_thread_priority_idle: return THREAD_PRIORITY_IDLE;
4316  case ma_thread_priority_lowest: return THREAD_PRIORITY_LOWEST;
4317  case ma_thread_priority_low: return THREAD_PRIORITY_BELOW_NORMAL;
4318  case ma_thread_priority_normal: return THREAD_PRIORITY_NORMAL;
4319  case ma_thread_priority_high: return THREAD_PRIORITY_ABOVE_NORMAL;
4320  case ma_thread_priority_highest: return THREAD_PRIORITY_HIGHEST;
4321  case ma_thread_priority_realtime: return THREAD_PRIORITY_TIME_CRITICAL;
4322  default: return THREAD_PRIORITY_NORMAL;
4323  }
4324 }
4325 
4326 static ma_result ma_thread_create__win32(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
4327 {
4328  *pThread = CreateThread(NULL, stackSize, entryProc, pData, 0, NULL);
4329  if (*pThread == NULL) {
4330  return ma_result_from_GetLastError(GetLastError());
4331  }
4332 
4333  SetThreadPriority((HANDLE)*pThread, ma_thread_priority_to_win32(priority));
4334 
4335  return MA_SUCCESS;
4336 }
4337 
4338 static void ma_thread_wait__win32(ma_thread* pThread)
4339 {
4340  WaitForSingleObject((HANDLE)*pThread, INFINITE);
4341  CloseHandle((HANDLE)*pThread);
4342 }
4343 
4344 
4345 static ma_result ma_mutex_init__win32(ma_mutex* pMutex)
4346 {
4347  *pMutex = CreateEventW(NULL, FALSE, TRUE, NULL);
4348  if (*pMutex == NULL) {
4349  return ma_result_from_GetLastError(GetLastError());
4350  }
4351 
4352  return MA_SUCCESS;
4353 }
4354 
4355 static void ma_mutex_uninit__win32(ma_mutex* pMutex)
4356 {
4357  CloseHandle((HANDLE)*pMutex);
4358 }
4359 
4360 static void ma_mutex_lock__win32(ma_mutex* pMutex)
4361 {
4362  WaitForSingleObject((HANDLE)*pMutex, INFINITE);
4363 }
4364 
4365 static void ma_mutex_unlock__win32(ma_mutex* pMutex)
4366 {
4367  SetEvent((HANDLE)*pMutex);
4368 }
4369 
4370 
4371 static ma_result ma_event_init__win32(ma_event* pEvent)
4372 {
4373  *pEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
4374  if (*pEvent == NULL) {
4375  return ma_result_from_GetLastError(GetLastError());
4376  }
4377 
4378  return MA_SUCCESS;
4379 }
4380 
4381 static void ma_event_uninit__win32(ma_event* pEvent)
4382 {
4383  CloseHandle((HANDLE)*pEvent);
4384 }
4385 
4386 static ma_result ma_event_wait__win32(ma_event* pEvent)
4387 {
4388  DWORD result = WaitForSingleObject((HANDLE)*pEvent, INFINITE);
4389  if (result == WAIT_OBJECT_0) {
4390  return MA_SUCCESS;
4391  }
4392 
4393  if (result == WAIT_TIMEOUT) {
4394  return MA_TIMEOUT;
4395  }
4396 
4397  return ma_result_from_GetLastError(GetLastError());
4398 }
4399 
4400 static ma_result ma_event_signal__win32(ma_event* pEvent)
4401 {
4402  BOOL result = SetEvent((HANDLE)*pEvent);
4403  if (result == 0) {
4404  return ma_result_from_GetLastError(GetLastError());
4405  }
4406 
4407  return MA_SUCCESS;
4408 }
4409 
4410 
4411 static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemaphore)
4412 {
4413  *pSemaphore = CreateSemaphoreW(NULL, (LONG)initialValue, LONG_MAX, NULL);
4414  if (*pSemaphore == NULL) {
4415  return ma_result_from_GetLastError(GetLastError());
4416  }
4417 
4418  return MA_SUCCESS;
4419 }
4420 
4421 static void ma_semaphore_uninit__win32(ma_semaphore* pSemaphore)
4422 {
4423  CloseHandle((HANDLE)*pSemaphore);
4424 }
4425 
4426 static ma_result ma_semaphore_wait__win32(ma_semaphore* pSemaphore)
4427 {
4428  DWORD result = WaitForSingleObject((HANDLE)*pSemaphore, INFINITE);
4429  if (result == WAIT_OBJECT_0) {
4430  return MA_SUCCESS;
4431  }
4432 
4433  if (result == WAIT_TIMEOUT) {
4434  return MA_TIMEOUT;
4435  }
4436 
4437  return ma_result_from_GetLastError(GetLastError());
4438 }
4439 
4440 static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore)
4441 {
4442  BOOL result = ReleaseSemaphore((HANDLE)*pSemaphore, 1, NULL);
4443  if (result == 0) {
4444  return ma_result_from_GetLastError(GetLastError());
4445  }
4446 
4447  return MA_SUCCESS;
4448 }
4449 #endif
4450 
4451 
4452 #ifdef MA_POSIX
4453 static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
4454 {
4455  int result;
4456  pthread_attr_t* pAttr = NULL;
4457 
4458 #if !defined(__EMSCRIPTEN__)
4459  /* Try setting the thread priority. It's not critical if anything fails here. */
4460  pthread_attr_t attr;
4461  if (pthread_attr_init(&attr) == 0) {
4462  int scheduler = -1;
4463  if (priority == ma_thread_priority_idle) {
4464 #ifdef SCHED_IDLE
4465  if (pthread_attr_setschedpolicy(&attr, SCHED_IDLE) == 0) {
4466  scheduler = SCHED_IDLE;
4467  }
4468 #endif
4469  } else if (priority == ma_thread_priority_realtime) {
4470 #ifdef SCHED_FIFO
4471  if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0) {
4472  scheduler = SCHED_FIFO;
4473  }
4474 #endif
4475 #ifdef MA_LINUX
4476  } else {
4477  scheduler = sched_getscheduler(0);
4478 #endif
4479  }
4480 
4481  if (stackSize > 0) {
4482  pthread_attr_setstacksize(&attr, stackSize);
4483  }
4484 
4485  if (scheduler != -1) {
4486  int priorityMin = sched_get_priority_min(scheduler);
4487  int priorityMax = sched_get_priority_max(scheduler);
4488  int priorityStep = (priorityMax - priorityMin) / 7; /* 7 = number of priorities supported by miniaudio. */
4489 
4490  struct sched_param sched;
4491  if (pthread_attr_getschedparam(&attr, &sched) == 0) {
4492  if (priority == ma_thread_priority_idle) {
4493  sched.sched_priority = priorityMin;
4494  } else if (priority == ma_thread_priority_realtime) {
4495  sched.sched_priority = priorityMax;
4496  } else {
4497  sched.sched_priority += ((int)priority + 5) * priorityStep; /* +5 because the lowest priority is -5. */
4498  if (sched.sched_priority < priorityMin) {
4499  sched.sched_priority = priorityMin;
4500  }
4501  if (sched.sched_priority > priorityMax) {
4502  sched.sched_priority = priorityMax;
4503  }
4504  }
4505 
4506  if (pthread_attr_setschedparam(&attr, &sched) == 0) {
4507  pAttr = &attr;
4508  }
4509  }
4510  }
4511  }
4512 #else
4513  /* It's the emscripten build. We'll have a few unused parameters. */
4514  (void)priority;
4515  (void)stackSize;
4516 #endif
4517 
4518  result = pthread_create(pThread, pAttr, entryProc, pData);
4519 
4520  /* The thread attributes object is no longer required. */
4521  if (pAttr != NULL) {
4522  pthread_attr_destroy(pAttr);
4523  }
4524 
4525  if (result != 0) {
4526  return ma_result_from_errno(result);
4527  }
4528 
4529  return MA_SUCCESS;
4530 }
4531 
4532 static void ma_thread_wait__posix(ma_thread* pThread)
4533 {
4534  pthread_join(*pThread, NULL);
4535  pthread_detach(*pThread);
4536 }
4537 
4538 
4540 {
4541  int result = pthread_mutex_init((pthread_mutex_t*)pMutex, NULL);
4542  if (result != 0) {
4543  return ma_result_from_errno(result);
4544  }
4545 
4546  return MA_SUCCESS;
4547 }
4548 
4549 static void ma_mutex_uninit__posix(ma_mutex* pMutex)
4550 {
4551  pthread_mutex_destroy((pthread_mutex_t*)pMutex);
4552 }
4553 
4554 static void ma_mutex_lock__posix(ma_mutex* pMutex)
4555 {
4556  pthread_mutex_lock((pthread_mutex_t*)pMutex);
4557 }
4558 
4559 static void ma_mutex_unlock__posix(ma_mutex* pMutex)
4560 {
4561  pthread_mutex_unlock((pthread_mutex_t*)pMutex);
4562 }
4563 
4564 
4566 {
4567  int result;
4568 
4569  result = pthread_mutex_init(&pEvent->lock, NULL);
4570  if (result != 0) {
4571  return ma_result_from_errno(result);
4572  }
4573 
4574  result = pthread_cond_init(&pEvent->cond, NULL);
4575  if (result != 0) {
4576  pthread_mutex_destroy(&pEvent->lock);
4577  return ma_result_from_errno(result);
4578  }
4579 
4580  pEvent->value = 0;
4581  return MA_SUCCESS;
4582 }
4583 
4584 static void ma_event_uninit__posix(ma_event* pEvent)
4585 {
4586  pthread_cond_destroy(&pEvent->cond);
4587  pthread_mutex_destroy(&pEvent->lock);
4588 }
4589 
4591 {
4592  pthread_mutex_lock(&pEvent->lock);
4593  {
4594  while (pEvent->value == 0) {
4595  pthread_cond_wait(&pEvent->cond, &pEvent->lock);
4596  }
4597  pEvent->value = 0; /* Auto-reset. */
4598  }
4599  pthread_mutex_unlock(&pEvent->lock);
4600 
4601  return MA_SUCCESS;
4602 }
4603 
4605 {
4606  pthread_mutex_lock(&pEvent->lock);
4607  {
4608  pEvent->value = 1;
4609  pthread_cond_signal(&pEvent->cond);
4610  }
4611  pthread_mutex_unlock(&pEvent->lock);
4612 
4613  return MA_SUCCESS;
4614 }
4615 
4616 
4617 static ma_result ma_semaphore_init__posix(int initialValue, ma_semaphore* pSemaphore)
4618 {
4619  int result;
4620 
4621  if (pSemaphore == NULL) {
4622  return MA_INVALID_ARGS;
4623  }
4624 
4625  pSemaphore->value = initialValue;
4626 
4627  result = pthread_mutex_init(&pSemaphore->lock, NULL);
4628  if (result != 0) {
4629  return ma_result_from_errno(result); /* Failed to create mutex. */
4630  }
4631 
4632  result = pthread_cond_init(&pSemaphore->cond, NULL);
4633  if (result != 0) {
4634  pthread_mutex_destroy(&pSemaphore->lock);
4635  return ma_result_from_errno(result); /* Failed to create condition variable. */
4636  }
4637 
4638  return MA_SUCCESS;
4639 }
4640 
4642 {
4643  if (pSemaphore == NULL) {
4644  return;
4645  }
4646 
4647  pthread_cond_destroy(&pSemaphore->cond);
4648  pthread_mutex_destroy(&pSemaphore->lock);
4649 }
4650 
4652 {
4653  if (pSemaphore == NULL) {
4654  return MA_INVALID_ARGS;
4655  }
4656 
4657  pthread_mutex_lock(&pSemaphore->lock);
4658  {
4659  /* We need to wait on a condition variable before escaping. We can't return from this function until the semaphore has been signaled. */
4660  while (pSemaphore->value == 0) {
4661  pthread_cond_wait(&pSemaphore->cond, &pSemaphore->lock);
4662  }
4663 
4664  pSemaphore->value -= 1;
4665  }
4666  pthread_mutex_unlock(&pSemaphore->lock);
4667 
4668  return MA_SUCCESS;
4669 }
4670 
4672 {
4673  if (pSemaphore == NULL) {
4674  return MA_INVALID_ARGS;
4675  }
4676 
4677  pthread_mutex_lock(&pSemaphore->lock);
4678  {
4679  pSemaphore->value += 1;
4680  pthread_cond_signal(&pSemaphore->cond);
4681  }
4682  pthread_mutex_unlock(&pSemaphore->lock);
4683 
4684  return MA_SUCCESS;
4685 }
4686 #endif
4687 
4688 typedef struct
4689 {
4691  void* pData;
4694 
4696 {
4697  ma_thread_proxy_data* pProxyData = (ma_thread_proxy_data*)pData;
4698  ma_thread_entry_proc entryProc;
4699  void* pEntryProcData;
4700  ma_thread_result result;
4701 
4702  #if defined(MA_ON_THREAD_ENTRY)
4703  MA_ON_THREAD_ENTRY
4704  #endif
4705 
4706  entryProc = pProxyData->entryProc;
4707  pEntryProcData = pProxyData->pData;
4708 
4709  /* Free the proxy data before getting into the real thread entry proc. */
4710  ma_free(pProxyData, &pProxyData->allocationCallbacks);
4711 
4712  result = entryProc(pEntryProcData);
4713 
4714  #if defined(MA_ON_THREAD_EXIT)
4715  MA_ON_THREAD_EXIT
4716  #endif
4717 
4718  return result;
4719 }
4720 
4721 static ma_result ma_thread_create(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData, const ma_allocation_callbacks* pAllocationCallbacks)
4722 {
4723  ma_result result;
4724  ma_thread_proxy_data* pProxyData;
4725 
4726  if (pThread == NULL || entryProc == NULL) {
4727  return MA_FALSE;
4728  }
4729 
4730  pProxyData = (ma_thread_proxy_data*)ma_malloc(sizeof(*pProxyData), pAllocationCallbacks); /* Will be freed by the proxy entry proc. */
4731  if (pProxyData == NULL) {
4732  return MA_OUT_OF_MEMORY;
4733  }
4734 
4735  pProxyData->entryProc = entryProc;
4736  pProxyData->pData = pData;
4737  ma_allocation_callbacks_init_copy(&pProxyData->allocationCallbacks, pAllocationCallbacks);
4738 
4739 #ifdef MA_WIN32
4740  result = ma_thread_create__win32(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
4741 #endif
4742 #ifdef MA_POSIX
4743  result = ma_thread_create__posix(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
4744 #endif
4745 
4746  if (result != MA_SUCCESS) {
4747  ma_free(pProxyData, pAllocationCallbacks);
4748  return result;
4749  }
4750 
4751  return MA_SUCCESS;
4752 }
4753 
4754 static void ma_thread_wait(ma_thread* pThread)
4755 {
4756  if (pThread == NULL) {
4757  return;
4758  }
4759 
4760 #ifdef MA_WIN32
4761  ma_thread_wait__win32(pThread);
4762 #endif
4763 #ifdef MA_POSIX
4764  ma_thread_wait__posix(pThread);
4765 #endif
4766 }
4767 
4768 
4770 {
4771  if (pMutex == NULL) {
4772  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4773  return MA_INVALID_ARGS;
4774  }
4775 
4776 #ifdef MA_WIN32
4777  return ma_mutex_init__win32(pMutex);
4778 #endif
4779 #ifdef MA_POSIX
4780  return ma_mutex_init__posix(pMutex);
4781 #endif
4782 }
4783 
4785 {
4786  if (pMutex == NULL) {
4787  return;
4788  }
4789 
4790 #ifdef MA_WIN32
4791  ma_mutex_uninit__win32(pMutex);
4792 #endif
4793 #ifdef MA_POSIX
4794  ma_mutex_uninit__posix(pMutex);
4795 #endif
4796 }
4797 
4799 {
4800  if (pMutex == NULL) {
4801  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4802  return;
4803  }
4804 
4805 #ifdef MA_WIN32
4806  ma_mutex_lock__win32(pMutex);
4807 #endif
4808 #ifdef MA_POSIX
4809  ma_mutex_lock__posix(pMutex);
4810 #endif
4811 }
4812 
4814 {
4815  if (pMutex == NULL) {
4816  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4817  return;
4818 }
4819 
4820 #ifdef MA_WIN32
4821  ma_mutex_unlock__win32(pMutex);
4822 #endif
4823 #ifdef MA_POSIX
4824  ma_mutex_unlock__posix(pMutex);
4825 #endif
4826 }
4827 
4828 
4830 {
4831  if (pEvent == NULL) {
4832  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4833  return MA_INVALID_ARGS;
4834  }
4835 
4836 #ifdef MA_WIN32
4837  return ma_event_init__win32(pEvent);
4838 #endif
4839 #ifdef MA_POSIX
4840  return ma_event_init__posix(pEvent);
4841 #endif
4842 }
4843 
4844 #if 0
4845 static ma_result ma_event_alloc_and_init(ma_event** ppEvent, ma_allocation_callbacks* pAllocationCallbacks)
4846 {
4847  ma_result result;
4848  ma_event* pEvent;
4849 
4850  if (ppEvent == NULL) {
4851  return MA_INVALID_ARGS;
4852  }
4853 
4854  *ppEvent = NULL;
4855 
4856  pEvent = ma_malloc(sizeof(*pEvent), pAllocationCallbacks/*, MA_ALLOCATION_TYPE_EVENT*/);
4857  if (pEvent == NULL) {
4858  return MA_OUT_OF_MEMORY;
4859  }
4860 
4861  result = ma_event_init(pEvent);
4862  if (result != MA_SUCCESS) {
4863  ma_free(pEvent, pAllocationCallbacks/*, MA_ALLOCATION_TYPE_EVENT*/);
4864  return result;
4865  }
4866 
4867  *ppEvent = pEvent;
4868  return result;
4869 }
4870 #endif
4871 
4873 {
4874  if (pEvent == NULL) {
4875  return;
4876  }
4877 
4878 #ifdef MA_WIN32
4879  ma_event_uninit__win32(pEvent);
4880 #endif
4881 #ifdef MA_POSIX
4882  ma_event_uninit__posix(pEvent);
4883 #endif
4884 }
4885 
4886 #if 0
4887 static void ma_event_uninit_and_free(ma_event* pEvent, ma_allocation_callbacks* pAllocationCallbacks)
4888 {
4889  if (pEvent == NULL) {
4890  return;
4891  }
4892 
4893  ma_event_uninit(pEvent);
4894  ma_free(pEvent, pAllocationCallbacks/*, MA_ALLOCATION_TYPE_EVENT*/);
4895 }
4896 #endif
4897 
4899 {
4900  if (pEvent == NULL) {
4901  MA_ASSERT(MA_FALSE); /* Fire an assert to the caller is aware of this bug. */
4902  return MA_INVALID_ARGS;
4903  }
4904 
4905 #ifdef MA_WIN32
4906  return ma_event_wait__win32(pEvent);
4907 #endif
4908 #ifdef MA_POSIX
4909  return ma_event_wait__posix(pEvent);
4910 #endif
4911 }
4912 
4914 {
4915  if (pEvent == NULL) {
4916  MA_ASSERT(MA_FALSE); /* Fire an assert to the caller is aware of this bug. */
4917  return MA_INVALID_ARGS;
4918  }
4919 
4920 #ifdef MA_WIN32
4921  return ma_event_signal__win32(pEvent);
4922 #endif
4923 #ifdef MA_POSIX
4924  return ma_event_signal__posix(pEvent);
4925 #endif
4926 }
4927 
4928 
4929 MA_API ma_result ma_semaphore_init(int initialValue, ma_semaphore* pSemaphore)
4930 {
4931  if (pSemaphore == NULL) {
4932  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4933  return MA_INVALID_ARGS;
4934  }
4935 
4936 #ifdef MA_WIN32
4937  return ma_semaphore_init__win32(initialValue, pSemaphore);
4938 #endif
4939 #ifdef MA_POSIX
4940  return ma_semaphore_init__posix(initialValue, pSemaphore);
4941 #endif
4942 }
4943 
4945 {
4946  if (pSemaphore == NULL) {
4947  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4948  return;
4949  }
4950 
4951 #ifdef MA_WIN32
4952  ma_semaphore_uninit__win32(pSemaphore);
4953 #endif
4954 #ifdef MA_POSIX
4955  ma_semaphore_uninit__posix(pSemaphore);
4956 #endif
4957 }
4958 
4960 {
4961  if (pSemaphore == NULL) {
4962  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4963  return MA_INVALID_ARGS;
4964  }
4965 
4966 #ifdef MA_WIN32
4967  return ma_semaphore_wait__win32(pSemaphore);
4968 #endif
4969 #ifdef MA_POSIX
4970  return ma_semaphore_wait__posix(pSemaphore);
4971 #endif
4972 }
4973 
4975 {
4976  if (pSemaphore == NULL) {
4977  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
4978  return MA_INVALID_ARGS;
4979  }
4980 
4981 #ifdef MA_WIN32
4982  return ma_semaphore_release__win32(pSemaphore);
4983 #endif
4984 #ifdef MA_POSIX
4985  return ma_semaphore_release__posix(pSemaphore);
4986 #endif
4987 }
4988 #else
4989 /* MA_NO_THREADING is set which means threading is disabled. Threading is required by some API families. If any of these are enabled we need to throw an error. */
4990 #ifndef MA_NO_DEVICE_IO
4991 #error "MA_NO_THREADING cannot be used without MA_NO_DEVICE_IO";
4992 #endif
4993 #endif /* MA_NO_THREADING */
4994 
4995 
4996 
4997 /************************************************************************************************************************************************************
4998 *************************************************************************************************************************************************************
4999 
5000 DEVICE I/O
5001 ==========
5002 
5003 *************************************************************************************************************************************************************
5004 ************************************************************************************************************************************************************/
5005 #ifndef MA_NO_DEVICE_IO
5006 #ifdef MA_WIN32
5007  #include <objbase.h>
5008  #include <mmreg.h>
5009  #include <mmsystem.h>
5010 #endif
5011 
5012 #if defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
5013  #include <mach/mach_time.h> /* For mach_absolute_time() */
5014 #endif
5015 
5016 #ifdef MA_POSIX
5017  #include <sys/types.h>
5018  #include <unistd.h>
5019  #include <dlfcn.h>
5020 #endif
5021 
5022 /*
5023 Unfortunately using runtime linking for pthreads causes problems. This has occurred for me when testing on FreeBSD. When
5024 using runtime linking, deadlocks can occur (for me it happens when loading data from fread()). It turns out that doing
5025 compile-time linking fixes this. I'm not sure why this happens, but the safest way I can think of to fix this is to simply
5026 disable runtime linking by default. To enable runtime linking, #define this before the implementation of this file. I am
5027 not officially supporting this, but I'm leaving it here in case it's useful for somebody, somewhere.
5028 */
5029 /*#define MA_USE_RUNTIME_LINKING_FOR_PTHREAD*/
5030 
5031 /* Disable run-time linking on certain backends. */
5032 #ifndef MA_NO_RUNTIME_LINKING
5033  #if defined(MA_EMSCRIPTEN)
5034  #define MA_NO_RUNTIME_LINKING
5035  #endif
5036 #endif
5037 
5038 
5040 {
5041  if (pDeviceInfo == NULL) {
5042  return;
5043  }
5044 
5045  if (pDeviceInfo->nativeDataFormatCount < ma_countof(pDeviceInfo->nativeDataFormats)) {
5046  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
5047  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
5048  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
5049  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = flags;
5050  pDeviceInfo->nativeDataFormatCount += 1;
5051  }
5052 }
5053 
5054 
5056 {
5057  switch (backend)
5058  {
5059  case ma_backend_wasapi: return "WASAPI";
5060  case ma_backend_dsound: return "DirectSound";
5061  case ma_backend_winmm: return "WinMM";
5062  case ma_backend_coreaudio: return "Core Audio";
5063  case ma_backend_sndio: return "sndio";
5064  case ma_backend_audio4: return "audio(4)";
5065  case ma_backend_oss: return "OSS";
5066  case ma_backend_pulseaudio: return "PulseAudio";
5067  case ma_backend_alsa: return "ALSA";
5068  case ma_backend_jack: return "JACK";
5069  case ma_backend_aaudio: return "AAudio";
5070  case ma_backend_opensl: return "OpenSL|ES";
5071  case ma_backend_webaudio: return "Web Audio";
5072  case ma_backend_custom: return "Custom";
5073  case ma_backend_null: return "Null";
5074  default: return "Unknown";
5075  }
5076 }
5077 
5079 {
5080  /*
5081  This looks a little bit gross, but we want all backends to be included in the switch to avoid warnings on some compilers
5082  about some enums not being handled by the switch statement.
5083  */
5084  switch (backend)
5085  {
5086  case ma_backend_wasapi:
5087  #if defined(MA_HAS_WASAPI)
5088  return MA_TRUE;
5089  #else
5090  return MA_FALSE;
5091  #endif
5092  case ma_backend_dsound:
5093  #if defined(MA_HAS_DSOUND)
5094  return MA_TRUE;
5095  #else
5096  return MA_FALSE;
5097  #endif
5098  case ma_backend_winmm:
5099  #if defined(MA_HAS_WINMM)
5100  return MA_TRUE;
5101  #else
5102  return MA_FALSE;
5103  #endif
5104  case ma_backend_coreaudio:
5105  #if defined(MA_HAS_COREAUDIO)
5106  return MA_TRUE;
5107  #else
5108  return MA_FALSE;
5109  #endif
5110  case ma_backend_sndio:
5111  #if defined(MA_HAS_SNDIO)
5112  return MA_TRUE;
5113  #else
5114  return MA_FALSE;
5115  #endif
5116  case ma_backend_audio4:
5117  #if defined(MA_HAS_AUDIO4)
5118  return MA_TRUE;
5119  #else
5120  return MA_FALSE;
5121  #endif
5122  case ma_backend_oss:
5123  #if defined(MA_HAS_OSS)
5124  return MA_TRUE;
5125  #else
5126  return MA_FALSE;
5127  #endif
5128  case ma_backend_pulseaudio:
5129  #if defined(MA_HAS_PULSEAUDIO)
5130  return MA_TRUE;
5131  #else
5132  return MA_FALSE;
5133  #endif
5134  case ma_backend_alsa:
5135  #if defined(MA_HAS_ALSA)
5136  return MA_TRUE;
5137  #else
5138  return MA_FALSE;
5139  #endif
5140  case ma_backend_jack:
5141  #if defined(MA_HAS_JACK)
5142  return MA_TRUE;
5143  #else
5144  return MA_FALSE;
5145  #endif
5146  case ma_backend_aaudio:
5147  #if defined(MA_HAS_AAUDIO)
5148  return MA_TRUE;
5149  #else
5150  return MA_FALSE;
5151  #endif
5152  case ma_backend_opensl:
5153  #if defined(MA_HAS_OPENSL)
5154  return MA_TRUE;
5155  #else
5156  return MA_FALSE;
5157  #endif
5158  case ma_backend_webaudio:
5159  #if defined(MA_HAS_WEBAUDIO)
5160  return MA_TRUE;
5161  #else
5162  return MA_FALSE;
5163  #endif
5164  case ma_backend_custom:
5165  #if defined(MA_HAS_CUSTOM)
5166  return MA_TRUE;
5167  #else
5168  return MA_FALSE;
5169  #endif
5170  case ma_backend_null:
5171  #if defined(MA_HAS_NULL)
5172  return MA_TRUE;
5173  #else
5174  return MA_FALSE;
5175  #endif
5176 
5177  default: return MA_FALSE;
5178  }
5179 }
5180 
5181 MA_API ma_result ma_get_enabled_backends(ma_backend* pBackends, size_t backendCap, size_t* pBackendCount)
5182 {
5183  size_t backendCount;
5184  size_t iBackend;
5185  ma_result result = MA_SUCCESS;
5186 
5187  if (pBackendCount == NULL) {
5188  return MA_INVALID_ARGS;
5189  }
5190 
5191  backendCount = 0;
5192 
5193  for (iBackend = 0; iBackend <= ma_backend_null; iBackend += 1) {
5194  ma_backend backend = (ma_backend)iBackend;
5195 
5196  if (ma_is_backend_enabled(backend)) {
5197  /* The backend is enabled. Try adding it to the list. If there's no room, MA_NO_SPACE needs to be returned. */
5198  if (backendCount == backendCap) {
5199  result = MA_NO_SPACE;
5200  break;
5201  } else {
5202  pBackends[backendCount] = backend;
5203  backendCount += 1;
5204  }
5205  }
5206  }
5207 
5208  if (pBackendCount != NULL) {
5209  *pBackendCount = backendCount;
5210  }
5211 
5212  return result;
5213 }
5214 
5216 {
5217  switch (backend)
5218  {
5219  case ma_backend_wasapi: return MA_TRUE;
5220  case ma_backend_dsound: return MA_FALSE;
5221  case ma_backend_winmm: return MA_FALSE;
5222  case ma_backend_coreaudio: return MA_FALSE;
5223  case ma_backend_sndio: return MA_FALSE;
5224  case ma_backend_audio4: return MA_FALSE;
5225  case ma_backend_oss: return MA_FALSE;
5226  case ma_backend_pulseaudio: return MA_FALSE;
5227  case ma_backend_alsa: return MA_FALSE;
5228  case ma_backend_jack: return MA_FALSE;
5229  case ma_backend_aaudio: return MA_FALSE;
5230  case ma_backend_opensl: return MA_FALSE;
5231  case ma_backend_webaudio: return MA_FALSE;
5232  case ma_backend_custom: return MA_FALSE; /* <-- Will depend on the implementation of the backend. */
5233  case ma_backend_null: return MA_FALSE;
5234  default: return MA_FALSE;
5235  }
5236 }
5237 
5238 
5239 
5240 #ifdef MA_WIN32
5241 /* WASAPI error codes. */
5242 #define MA_AUDCLNT_E_NOT_INITIALIZED ((HRESULT)0x88890001)
5243 #define MA_AUDCLNT_E_ALREADY_INITIALIZED ((HRESULT)0x88890002)
5244 #define MA_AUDCLNT_E_WRONG_ENDPOINT_TYPE ((HRESULT)0x88890003)
5245 #define MA_AUDCLNT_E_DEVICE_INVALIDATED ((HRESULT)0x88890004)
5246 #define MA_AUDCLNT_E_NOT_STOPPED ((HRESULT)0x88890005)
5247 #define MA_AUDCLNT_E_BUFFER_TOO_LARGE ((HRESULT)0x88890006)
5248 #define MA_AUDCLNT_E_OUT_OF_ORDER ((HRESULT)0x88890007)
5249 #define MA_AUDCLNT_E_UNSUPPORTED_FORMAT ((HRESULT)0x88890008)
5250 #define MA_AUDCLNT_E_INVALID_SIZE ((HRESULT)0x88890009)
5251 #define MA_AUDCLNT_E_DEVICE_IN_USE ((HRESULT)0x8889000A)
5252 #define MA_AUDCLNT_E_BUFFER_OPERATION_PENDING ((HRESULT)0x8889000B)
5253 #define MA_AUDCLNT_E_THREAD_NOT_REGISTERED ((HRESULT)0x8889000C)
5254 #define MA_AUDCLNT_E_NO_SINGLE_PROCESS ((HRESULT)0x8889000D)
5255 #define MA_AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED ((HRESULT)0x8889000E)
5256 #define MA_AUDCLNT_E_ENDPOINT_CREATE_FAILED ((HRESULT)0x8889000F)
5257 #define MA_AUDCLNT_E_SERVICE_NOT_RUNNING ((HRESULT)0x88890010)
5258 #define MA_AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ((HRESULT)0x88890011)
5259 #define MA_AUDCLNT_E_EXCLUSIVE_MODE_ONLY ((HRESULT)0x88890012)
5260 #define MA_AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL ((HRESULT)0x88890013)
5261 #define MA_AUDCLNT_E_EVENTHANDLE_NOT_SET ((HRESULT)0x88890014)
5262 #define MA_AUDCLNT_E_INCORRECT_BUFFER_SIZE ((HRESULT)0x88890015)
5263 #define MA_AUDCLNT_E_BUFFER_SIZE_ERROR ((HRESULT)0x88890016)
5264 #define MA_AUDCLNT_E_CPUUSAGE_EXCEEDED ((HRESULT)0x88890017)
5265 #define MA_AUDCLNT_E_BUFFER_ERROR ((HRESULT)0x88890018)
5266 #define MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED ((HRESULT)0x88890019)
5267 #define MA_AUDCLNT_E_INVALID_DEVICE_PERIOD ((HRESULT)0x88890020)
5268 #define MA_AUDCLNT_E_INVALID_STREAM_FLAG ((HRESULT)0x88890021)
5269 #define MA_AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE ((HRESULT)0x88890022)
5270 #define MA_AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES ((HRESULT)0x88890023)
5271 #define MA_AUDCLNT_E_OFFLOAD_MODE_ONLY ((HRESULT)0x88890024)
5272 #define MA_AUDCLNT_E_NONOFFLOAD_MODE_ONLY ((HRESULT)0x88890025)
5273 #define MA_AUDCLNT_E_RESOURCES_INVALIDATED ((HRESULT)0x88890026)
5274 #define MA_AUDCLNT_E_RAW_MODE_UNSUPPORTED ((HRESULT)0x88890027)
5275 #define MA_AUDCLNT_E_ENGINE_PERIODICITY_LOCKED ((HRESULT)0x88890028)
5276 #define MA_AUDCLNT_E_ENGINE_FORMAT_LOCKED ((HRESULT)0x88890029)
5277 #define MA_AUDCLNT_E_HEADTRACKING_ENABLED ((HRESULT)0x88890030)
5278 #define MA_AUDCLNT_E_HEADTRACKING_UNSUPPORTED ((HRESULT)0x88890040)
5279 #define MA_AUDCLNT_S_BUFFER_EMPTY ((HRESULT)0x08890001)
5280 #define MA_AUDCLNT_S_THREAD_ALREADY_REGISTERED ((HRESULT)0x08890002)
5281 #define MA_AUDCLNT_S_POSITION_STALLED ((HRESULT)0x08890003)
5282 
5283 #define MA_DS_OK ((HRESULT)0)
5284 #define MA_DS_NO_VIRTUALIZATION ((HRESULT)0x0878000A)
5285 #define MA_DSERR_ALLOCATED ((HRESULT)0x8878000A)
5286 #define MA_DSERR_CONTROLUNAVAIL ((HRESULT)0x8878001E)
5287 #define MA_DSERR_INVALIDPARAM ((HRESULT)0x80070057) /*E_INVALIDARG*/
5288 #define MA_DSERR_INVALIDCALL ((HRESULT)0x88780032)
5289 #define MA_DSERR_GENERIC ((HRESULT)0x80004005) /*E_FAIL*/
5290 #define MA_DSERR_PRIOLEVELNEEDED ((HRESULT)0x88780046)
5291 #define MA_DSERR_OUTOFMEMORY ((HRESULT)0x8007000E) /*E_OUTOFMEMORY*/
5292 #define MA_DSERR_BADFORMAT ((HRESULT)0x88780064)
5293 #define MA_DSERR_UNSUPPORTED ((HRESULT)0x80004001) /*E_NOTIMPL*/
5294 #define MA_DSERR_NODRIVER ((HRESULT)0x88780078)
5295 #define MA_DSERR_ALREADYINITIALIZED ((HRESULT)0x88780082)
5296 #define MA_DSERR_NOAGGREGATION ((HRESULT)0x80040110) /*CLASS_E_NOAGGREGATION*/
5297 #define MA_DSERR_BUFFERLOST ((HRESULT)0x88780096)
5298 #define MA_DSERR_OTHERAPPHASPRIO ((HRESULT)0x887800A0)
5299 #define MA_DSERR_UNINITIALIZED ((HRESULT)0x887800AA)
5300 #define MA_DSERR_NOINTERFACE ((HRESULT)0x80004002) /*E_NOINTERFACE*/
5301 #define MA_DSERR_ACCESSDENIED ((HRESULT)0x80070005) /*E_ACCESSDENIED*/
5302 #define MA_DSERR_BUFFERTOOSMALL ((HRESULT)0x887800B4)
5303 #define MA_DSERR_DS8_REQUIRED ((HRESULT)0x887800BE)
5304 #define MA_DSERR_SENDLOOP ((HRESULT)0x887800C8)
5305 #define MA_DSERR_BADSENDBUFFERGUID ((HRESULT)0x887800D2)
5306 #define MA_DSERR_OBJECTNOTFOUND ((HRESULT)0x88781161)
5307 #define MA_DSERR_FXUNAVAILABLE ((HRESULT)0x887800DC)
5308 
5309 static ma_result ma_result_from_HRESULT(HRESULT hr)
5310 {
5311  switch (hr)
5312  {
5313  case NOERROR: return MA_SUCCESS;
5314  /*case S_OK: return MA_SUCCESS;*/
5315 
5316  case E_POINTER: return MA_INVALID_ARGS;
5317  case E_UNEXPECTED: return MA_ERROR;
5318  case E_NOTIMPL: return MA_NOT_IMPLEMENTED;
5319  case E_OUTOFMEMORY: return MA_OUT_OF_MEMORY;
5320  case E_INVALIDARG: return MA_INVALID_ARGS;
5321  case E_NOINTERFACE: return MA_API_NOT_FOUND;
5322  case E_HANDLE: return MA_INVALID_ARGS;
5323  case E_ABORT: return MA_ERROR;
5324  case E_FAIL: return MA_ERROR;
5325  case E_ACCESSDENIED: return MA_ACCESS_DENIED;
5326 
5327  /* WASAPI */
5328  case MA_AUDCLNT_E_NOT_INITIALIZED: return MA_DEVICE_NOT_INITIALIZED;
5329  case MA_AUDCLNT_E_ALREADY_INITIALIZED: return MA_DEVICE_ALREADY_INITIALIZED;
5330  case MA_AUDCLNT_E_WRONG_ENDPOINT_TYPE: return MA_INVALID_ARGS;
5331  case MA_AUDCLNT_E_DEVICE_INVALIDATED: return MA_UNAVAILABLE;
5332  case MA_AUDCLNT_E_NOT_STOPPED: return MA_DEVICE_NOT_STOPPED;
5333  case MA_AUDCLNT_E_BUFFER_TOO_LARGE: return MA_TOO_BIG;
5334  case MA_AUDCLNT_E_OUT_OF_ORDER: return MA_INVALID_OPERATION;
5335  case MA_AUDCLNT_E_UNSUPPORTED_FORMAT: return MA_FORMAT_NOT_SUPPORTED;
5336  case MA_AUDCLNT_E_INVALID_SIZE: return MA_INVALID_ARGS;
5337  case MA_AUDCLNT_E_DEVICE_IN_USE: return MA_BUSY;
5338  case MA_AUDCLNT_E_BUFFER_OPERATION_PENDING: return MA_INVALID_OPERATION;
5339  case MA_AUDCLNT_E_THREAD_NOT_REGISTERED: return MA_DOES_NOT_EXIST;
5340  case MA_AUDCLNT_E_NO_SINGLE_PROCESS: return MA_INVALID_OPERATION;
5341  case MA_AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: return MA_SHARE_MODE_NOT_SUPPORTED;
5342  case MA_AUDCLNT_E_ENDPOINT_CREATE_FAILED: return MA_FAILED_TO_OPEN_BACKEND_DEVICE;
5343  case MA_AUDCLNT_E_SERVICE_NOT_RUNNING: return MA_NOT_CONNECTED;
5344  case MA_AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: return MA_INVALID_ARGS;
5345  case MA_AUDCLNT_E_EXCLUSIVE_MODE_ONLY: return MA_SHARE_MODE_NOT_SUPPORTED;
5346  case MA_AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: return MA_INVALID_ARGS;
5347  case MA_AUDCLNT_E_EVENTHANDLE_NOT_SET: return MA_INVALID_ARGS;
5348  case MA_AUDCLNT_E_INCORRECT_BUFFER_SIZE: return MA_INVALID_ARGS;
5349  case MA_AUDCLNT_E_BUFFER_SIZE_ERROR: return MA_INVALID_ARGS;
5350  case MA_AUDCLNT_E_CPUUSAGE_EXCEEDED: return MA_ERROR;
5351  case MA_AUDCLNT_E_BUFFER_ERROR: return MA_ERROR;
5352  case MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED: return MA_INVALID_ARGS;
5353  case MA_AUDCLNT_E_INVALID_DEVICE_PERIOD: return MA_INVALID_ARGS;
5354  case MA_AUDCLNT_E_INVALID_STREAM_FLAG: return MA_INVALID_ARGS;
5355  case MA_AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE: return MA_INVALID_OPERATION;
5356  case MA_AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES: return MA_OUT_OF_MEMORY;
5357  case MA_AUDCLNT_E_OFFLOAD_MODE_ONLY: return MA_INVALID_OPERATION;
5358  case MA_AUDCLNT_E_NONOFFLOAD_MODE_ONLY: return MA_INVALID_OPERATION;
5359  case MA_AUDCLNT_E_RESOURCES_INVALIDATED: return MA_INVALID_DATA;
5360  case MA_AUDCLNT_E_RAW_MODE_UNSUPPORTED: return MA_INVALID_OPERATION;
5361  case MA_AUDCLNT_E_ENGINE_PERIODICITY_LOCKED: return MA_INVALID_OPERATION;
5362  case MA_AUDCLNT_E_ENGINE_FORMAT_LOCKED: return MA_INVALID_OPERATION;
5363  case MA_AUDCLNT_E_HEADTRACKING_ENABLED: return MA_INVALID_OPERATION;
5364  case MA_AUDCLNT_E_HEADTRACKING_UNSUPPORTED: return MA_INVALID_OPERATION;
5365  case MA_AUDCLNT_S_BUFFER_EMPTY: return MA_NO_SPACE;
5366  case MA_AUDCLNT_S_THREAD_ALREADY_REGISTERED: return MA_ALREADY_EXISTS;
5367  case MA_AUDCLNT_S_POSITION_STALLED: return MA_ERROR;
5368 
5369  /* DirectSound */
5370  /*case MA_DS_OK: return MA_SUCCESS;*/ /* S_OK */
5371  case MA_DS_NO_VIRTUALIZATION: return MA_SUCCESS;
5372  case MA_DSERR_ALLOCATED: return MA_ALREADY_IN_USE;
5373  case MA_DSERR_CONTROLUNAVAIL: return MA_INVALID_OPERATION;
5374  /*case MA_DSERR_INVALIDPARAM: return MA_INVALID_ARGS;*/ /* E_INVALIDARG */
5375  case MA_DSERR_INVALIDCALL: return MA_INVALID_OPERATION;
5376  /*case MA_DSERR_GENERIC: return MA_ERROR;*/ /* E_FAIL */
5377  case MA_DSERR_PRIOLEVELNEEDED: return MA_INVALID_OPERATION;
5378  /*case MA_DSERR_OUTOFMEMORY: return MA_OUT_OF_MEMORY;*/ /* E_OUTOFMEMORY */
5379  case MA_DSERR_BADFORMAT: return MA_FORMAT_NOT_SUPPORTED;
5380  /*case MA_DSERR_UNSUPPORTED: return MA_NOT_IMPLEMENTED;*/ /* E_NOTIMPL */
5381  case MA_DSERR_NODRIVER: return MA_FAILED_TO_INIT_BACKEND;
5382  case MA_DSERR_ALREADYINITIALIZED: return MA_DEVICE_ALREADY_INITIALIZED;
5383  case MA_DSERR_NOAGGREGATION: return MA_ERROR;
5384  case MA_DSERR_BUFFERLOST: return MA_UNAVAILABLE;
5385  case MA_DSERR_OTHERAPPHASPRIO: return MA_ACCESS_DENIED;
5386  case MA_DSERR_UNINITIALIZED: return MA_DEVICE_NOT_INITIALIZED;
5387  /*case MA_DSERR_NOINTERFACE: return MA_API_NOT_FOUND;*/ /* E_NOINTERFACE */
5388  /*case MA_DSERR_ACCESSDENIED: return MA_ACCESS_DENIED;*/ /* E_ACCESSDENIED */
5389  case MA_DSERR_BUFFERTOOSMALL: return MA_NO_SPACE;
5390  case MA_DSERR_DS8_REQUIRED: return MA_INVALID_OPERATION;
5391  case MA_DSERR_SENDLOOP: return MA_DEADLOCK;
5392  case MA_DSERR_BADSENDBUFFERGUID: return MA_INVALID_ARGS;
5393  case MA_DSERR_OBJECTNOTFOUND: return MA_NO_DEVICE;
5394  case MA_DSERR_FXUNAVAILABLE: return MA_UNAVAILABLE;
5395 
5396  default: return MA_ERROR;
5397  }
5398 }
5399 
5400 typedef HRESULT (WINAPI * MA_PFN_CoInitializeEx)(LPVOID pvReserved, DWORD dwCoInit);
5401 typedef void (WINAPI * MA_PFN_CoUninitialize)(void);
5402 typedef HRESULT (WINAPI * MA_PFN_CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);
5403 typedef void (WINAPI * MA_PFN_CoTaskMemFree)(LPVOID pv);
5404 typedef HRESULT (WINAPI * MA_PFN_PropVariantClear)(PROPVARIANT *pvar);
5405 typedef int (WINAPI * MA_PFN_StringFromGUID2)(const GUID* const rguid, LPOLESTR lpsz, int cchMax);
5406 
5407 typedef HWND (WINAPI * MA_PFN_GetForegroundWindow)(void);
5408 typedef HWND (WINAPI * MA_PFN_GetDesktopWindow)(void);
5409 
5410 /* Microsoft documents these APIs as returning LSTATUS, but the Win32 API shipping with some compilers do not define it. It's just a LONG. */
5411 typedef LONG (WINAPI * MA_PFN_RegOpenKeyExA)(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
5412 typedef LONG (WINAPI * MA_PFN_RegCloseKey)(HKEY hKey);
5413 typedef LONG (WINAPI * MA_PFN_RegQueryValueExA)(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
5414 #endif
5415 
5416 
5417 #define MA_DEFAULT_PLAYBACK_DEVICE_NAME "Default Playback Device"
5418 #define MA_DEFAULT_CAPTURE_DEVICE_NAME "Default Capture Device"
5419 
5420 
5421 /* Posts a log message. */
5422 static void ma_post_log_message(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message)
5423 {
5424  if (pContext == NULL) {
5425  if (pDevice != NULL) {
5426  pContext = pDevice->pContext;
5427  }
5428  }
5429 
5430  if (pContext == NULL) {
5431  return;
5432  }
5433 
5434  ma_log_post(ma_context_get_log(pContext), logLevel, message); /* <-- This will deal with MA_DEBUG_OUTPUT. */
5435 
5436  /* Legacy. */
5437 #if defined(MA_LOG_LEVEL)
5438  if (logLevel <= MA_LOG_LEVEL) {
5439  ma_log_proc onLog;
5440 
5441  onLog = pContext->logCallback;
5442  if (onLog) {
5443  onLog(pContext, pDevice, logLevel, message);
5444  }
5445  }
5446 #endif
5447 }
5448 
5449 /* Posts an log message. Throw a breakpoint in here if you're needing to debug. The return value is always "resultCode". */
5450 static ma_result ma_context_post_error(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message, ma_result resultCode)
5451 {
5452  ma_post_log_message(pContext, pDevice, logLevel, message);
5453  return resultCode;
5454 }
5455 
5456 static ma_result ma_post_error(ma_device* pDevice, ma_uint32 logLevel, const char* message, ma_result resultCode)
5457 {
5458  return ma_context_post_error(ma_device_get_context(pDevice), pDevice, logLevel, message, resultCode);
5459 }
5460 
5461 
5462 
5463 
5464 /*******************************************************************************
5465 
5466 Timing
5467 
5468 *******************************************************************************/
5469 #ifdef MA_WIN32
5470  static LARGE_INTEGER g_ma_TimerFrequency; /* <-- Initialized to zero since it's static. */
5471  static void ma_timer_init(ma_timer* pTimer)
5472  {
5473  LARGE_INTEGER counter;
5474 
5475  if (g_ma_TimerFrequency.QuadPart == 0) {
5476  QueryPerformanceFrequency(&g_ma_TimerFrequency);
5477  }
5478 
5479  QueryPerformanceCounter(&counter);
5480  pTimer->counter = counter.QuadPart;
5481  }
5482 
5483  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
5484  {
5485  LARGE_INTEGER counter;
5486  if (!QueryPerformanceCounter(&counter)) {
5487  return 0;
5488  }
5489 
5490  return (double)(counter.QuadPart - pTimer->counter) / g_ma_TimerFrequency.QuadPart;
5491  }
5492 #elif defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
5493  static ma_uint64 g_ma_TimerFrequency = 0;
5494  static void ma_timer_init(ma_timer* pTimer)
5495  {
5496  mach_timebase_info_data_t baseTime;
5497  mach_timebase_info(&baseTime);
5498  g_ma_TimerFrequency = (baseTime.denom * 1e9) / baseTime.numer;
5499 
5500  pTimer->counter = mach_absolute_time();
5501  }
5502 
5503  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
5504  {
5505  ma_uint64 newTimeCounter = mach_absolute_time();
5506  ma_uint64 oldTimeCounter = pTimer->counter;
5507 
5508  return (newTimeCounter - oldTimeCounter) / g_ma_TimerFrequency;
5509  }
5510 #elif defined(MA_EMSCRIPTEN)
5511  static MA_INLINE void ma_timer_init(ma_timer* pTimer)
5512  {
5513  pTimer->counterD = emscripten_get_now();
5514  }
5515 
5516  static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer)
5517  {
5518  return (emscripten_get_now() - pTimer->counterD) / 1000; /* Emscripten is in milliseconds. */
5519  }
5520 #else
5521  #if _POSIX_C_SOURCE >= 199309L
5522  #if defined(CLOCK_MONOTONIC)
5523  #define MA_CLOCK_ID CLOCK_MONOTONIC
5524  #else
5525  #define MA_CLOCK_ID CLOCK_REALTIME
5526  #endif
5527 
5528  static void ma_timer_init(ma_timer* pTimer)
5529  {
5530  struct timespec newTime;
5531  clock_gettime(MA_CLOCK_ID, &newTime);
5532 
5533  pTimer->counter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
5534  }
5535 
5536  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
5537  {
5538  ma_uint64 newTimeCounter;
5539  ma_uint64 oldTimeCounter;
5540 
5541  struct timespec newTime;
5542  clock_gettime(MA_CLOCK_ID, &newTime);
5543 
5544  newTimeCounter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
5545  oldTimeCounter = pTimer->counter;
5546 
5547  return (newTimeCounter - oldTimeCounter) / 1000000000.0;
5548  }
5549  #else
5550  static void ma_timer_init(ma_timer* pTimer)
5551  {
5552  struct timeval newTime;
5553  gettimeofday(&newTime, NULL);
5554 
5555  pTimer->counter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
5556  }
5557 
5559  {
5560  ma_uint64 newTimeCounter;
5561  ma_uint64 oldTimeCounter;
5562 
5563  struct timeval newTime;
5564  gettimeofday(&newTime, NULL);
5565 
5566  newTimeCounter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
5567  oldTimeCounter = pTimer->counter;
5568 
5569  return (newTimeCounter - oldTimeCounter) / 1000000.0;
5570  }
5571  #endif
5572 #endif
5573 
5574 
5575 /*******************************************************************************
5576 
5577 Dynamic Linking
5578 
5579 *******************************************************************************/
5580 MA_API ma_handle ma_dlopen(ma_context* pContext, const char* filename)
5581 {
5582  ma_handle handle;
5583 
5584  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename);
5585 
5586 #ifdef _WIN32
5587 #ifdef MA_WIN32_DESKTOP
5588  handle = (ma_handle)LoadLibraryA(filename);
5589 #else
5590  /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
5591  WCHAR filenameW[4096];
5592  if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) {
5593  handle = NULL;
5594  } else {
5595  handle = (ma_handle)LoadPackagedLibrary(filenameW, 0);
5596  }
5597 #endif
5598 #else
5599  handle = (ma_handle)dlopen(filename, RTLD_NOW);
5600 #endif
5601 
5602  /*
5603  I'm not considering failure to load a library an error nor a warning because seamlessly falling through to a lower-priority
5604  backend is a deliberate design choice. Instead I'm logging it as an informational message.
5605  */
5606  if (handle == NULL) {
5607  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_INFO, "Failed to load library: %s\n", filename);
5608  }
5609 
5610  (void)pContext; /* It's possible for pContext to be unused. */
5611  return handle;
5612 }
5613 
5614 MA_API void ma_dlclose(ma_context* pContext, ma_handle handle)
5615 {
5616 #ifdef _WIN32
5617  FreeLibrary((HMODULE)handle);
5618 #else
5619  dlclose((void*)handle);
5620 #endif
5621 
5622  (void)pContext;
5623 }
5624 
5625 MA_API ma_proc ma_dlsym(ma_context* pContext, ma_handle handle, const char* symbol)
5626 {
5627  ma_proc proc;
5628 
5629  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Loading symbol: %s\n", symbol);
5630 
5631 #ifdef _WIN32
5632  proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol);
5633 #else
5634 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
5635  #pragma GCC diagnostic push
5636  #pragma GCC diagnostic ignored "-Wpedantic"
5637 #endif
5638  proc = (ma_proc)dlsym((void*)handle, symbol);
5639 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
5640  #pragma GCC diagnostic pop
5641 #endif
5642 #endif
5643 
5644  if (proc == NULL) {
5645  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Failed to load symbol: %s\n", symbol);
5646  }
5647 
5648  (void)pContext; /* It's possible for pContext to be unused. */
5649  return proc;
5650 }
5651 
5652 
5653 #if 0
5654 static ma_uint32 ma_get_closest_standard_sample_rate(ma_uint32 sampleRateIn)
5655 {
5656  ma_uint32 closestRate = 0;
5657  ma_uint32 closestDiff = 0xFFFFFFFF;
5658  size_t iStandardRate;
5659 
5660  for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
5661  ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
5662  ma_uint32 diff;
5663 
5664  if (sampleRateIn > standardRate) {
5665  diff = sampleRateIn - standardRate;
5666  } else {
5667  diff = standardRate - sampleRateIn;
5668  }
5669 
5670  if (diff == 0) {
5671  return standardRate; /* The input sample rate is a standard rate. */
5672  }
5673 
5674  if (closestDiff > diff) {
5675  closestDiff = diff;
5676  closestRate = standardRate;
5677  }
5678  }
5679 
5680  return closestRate;
5681 }
5682 #endif
5683 
5684 
5685 static void ma_device__on_data(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
5686 {
5687  float masterVolumeFactor;
5688 
5689  ma_device_get_master_volume(pDevice, &masterVolumeFactor); /* Use ma_device_get_master_volume() to ensure the volume is loaded atomically. */
5690 
5691  if (pDevice->onData) {
5692  if (!pDevice->noPreZeroedOutputBuffer && pFramesOut != NULL) {
5693  ma_silence_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels);
5694  }
5695 
5696  /* Volume control of input makes things a bit awkward because the input buffer is read-only. We'll need to use a temp buffer and loop in this case. */
5697  if (pFramesIn != NULL && masterVolumeFactor < 1) {
5699  ma_uint32 bpfCapture = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
5700  ma_uint32 bpfPlayback = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
5701  ma_uint32 totalFramesProcessed = 0;
5702  while (totalFramesProcessed < frameCount) {
5703  ma_uint32 framesToProcessThisIteration = frameCount - totalFramesProcessed;
5704  if (framesToProcessThisIteration > sizeof(tempFramesIn)/bpfCapture) {
5705  framesToProcessThisIteration = sizeof(tempFramesIn)/bpfCapture;
5706  }
5707 
5708  ma_copy_and_apply_volume_factor_pcm_frames(tempFramesIn, ma_offset_ptr(pFramesIn, totalFramesProcessed*bpfCapture), framesToProcessThisIteration, pDevice->capture.format, pDevice->capture.channels, masterVolumeFactor);
5709 
5710  pDevice->onData(pDevice, ma_offset_ptr(pFramesOut, totalFramesProcessed*bpfPlayback), tempFramesIn, framesToProcessThisIteration);
5711 
5712  totalFramesProcessed += framesToProcessThisIteration;
5713  }
5714  } else {
5715  pDevice->onData(pDevice, pFramesOut, pFramesIn, frameCount);
5716  }
5717 
5718  /* Volume control and clipping for playback devices. */
5719  if (pFramesOut != NULL) {
5720  if (masterVolumeFactor < 1) {
5721  if (pFramesIn == NULL) { /* <-- In full-duplex situations, the volume will have been applied to the input samples before the data callback. Applying it again post-callback will incorrectly compound it. */
5722  ma_apply_volume_factor_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels, masterVolumeFactor);
5723  }
5724  }
5725 
5726  if (!pDevice->noClip && pDevice->playback.format == ma_format_f32) {
5727  ma_clip_pcm_frames_f32((float*)pFramesOut, frameCount, pDevice->playback.channels);
5728  }
5729  }
5730  }
5731 }
5732 
5733 
5734 
5735 /* A helper function for reading sample data from the client. */
5736 static void ma_device__read_frames_from_client(ma_device* pDevice, ma_uint32 frameCount, void* pFramesOut)
5737 {
5738  MA_ASSERT(pDevice != NULL);
5739  MA_ASSERT(frameCount > 0);
5740  MA_ASSERT(pFramesOut != NULL);
5741 
5742  if (pDevice->playback.converter.isPassthrough) {
5743  ma_device__on_data(pDevice, pFramesOut, NULL, frameCount);
5744  } else {
5745  ma_result result;
5746  ma_uint64 totalFramesReadOut;
5747  ma_uint64 totalFramesReadIn;
5748  void* pRunningFramesOut;
5749 
5750  totalFramesReadOut = 0;
5751  totalFramesReadIn = 0;
5752  pRunningFramesOut = pFramesOut;
5753 
5754  while (totalFramesReadOut < frameCount) {
5755  ma_uint8 pIntermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In client format. */
5756  ma_uint64 intermediaryBufferCap = sizeof(pIntermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
5757  ma_uint64 framesToReadThisIterationIn;
5758  ma_uint64 framesReadThisIterationIn;
5759  ma_uint64 framesToReadThisIterationOut;
5760  ma_uint64 framesReadThisIterationOut;
5761  ma_uint64 requiredInputFrameCount;
5762 
5763  framesToReadThisIterationOut = (frameCount - totalFramesReadOut);
5764  framesToReadThisIterationIn = framesToReadThisIterationOut;
5765  if (framesToReadThisIterationIn > intermediaryBufferCap) {
5766  framesToReadThisIterationIn = intermediaryBufferCap;
5767  }
5768 
5769  requiredInputFrameCount = ma_data_converter_get_required_input_frame_count(&pDevice->playback.converter, framesToReadThisIterationOut);
5770  if (framesToReadThisIterationIn > requiredInputFrameCount) {
5771  framesToReadThisIterationIn = requiredInputFrameCount;
5772  }
5773 
5774  if (framesToReadThisIterationIn > 0) {
5775  ma_device__on_data(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn);
5776  totalFramesReadIn += framesToReadThisIterationIn;
5777  }
5778 
5779  /*
5780  At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any
5781  input frames, we still want to try processing frames because there may some output frames generated from cached input data.
5782  */
5783  framesReadThisIterationIn = framesToReadThisIterationIn;
5784  framesReadThisIterationOut = framesToReadThisIterationOut;
5785  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
5786  if (result != MA_SUCCESS) {
5787  break;
5788  }
5789 
5790  totalFramesReadOut += framesReadThisIterationOut;
5791  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
5792 
5793  if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
5794  break; /* We're done. */
5795  }
5796  }
5797  }
5798 }
5799 
5800 /* A helper for sending sample data to the client. */
5801 static void ma_device__send_frames_to_client(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat)
5802 {
5803  MA_ASSERT(pDevice != NULL);
5804  MA_ASSERT(frameCountInDeviceFormat > 0);
5805  MA_ASSERT(pFramesInDeviceFormat != NULL);
5806 
5807  if (pDevice->capture.converter.isPassthrough) {
5808  ma_device__on_data(pDevice, NULL, pFramesInDeviceFormat, frameCountInDeviceFormat);
5809  } else {
5810  ma_result result;
5811  ma_uint8 pFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
5812  ma_uint64 framesInClientFormatCap = sizeof(pFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
5813  ma_uint64 totalDeviceFramesProcessed = 0;
5814  ma_uint64 totalClientFramesProcessed = 0;
5815  const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat;
5816 
5817  /* We just keep going until we've exhaused all of our input frames and cannot generate any more output frames. */
5818  for (;;) {
5819  ma_uint64 deviceFramesProcessedThisIteration;
5820  ma_uint64 clientFramesProcessedThisIteration;
5821 
5822  deviceFramesProcessedThisIteration = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
5823  clientFramesProcessedThisIteration = framesInClientFormatCap;
5824 
5825  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningFramesInDeviceFormat, &deviceFramesProcessedThisIteration, pFramesInClientFormat, &clientFramesProcessedThisIteration);
5826  if (result != MA_SUCCESS) {
5827  break;
5828  }
5829 
5830  if (clientFramesProcessedThisIteration > 0) {
5831  ma_device__on_data(pDevice, NULL, pFramesInClientFormat, (ma_uint32)clientFramesProcessedThisIteration); /* Safe cast. */
5832  }
5833 
5834  pRunningFramesInDeviceFormat = ma_offset_ptr(pRunningFramesInDeviceFormat, deviceFramesProcessedThisIteration * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
5835  totalDeviceFramesProcessed += deviceFramesProcessedThisIteration;
5836  totalClientFramesProcessed += clientFramesProcessedThisIteration;
5837 
5838  if (deviceFramesProcessedThisIteration == 0 && clientFramesProcessedThisIteration == 0) {
5839  break; /* We're done. */
5840  }
5841  }
5842  }
5843 }
5844 
5845 static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat, ma_pcm_rb* pRB)
5846 {
5847  ma_result result;
5848  ma_uint32 totalDeviceFramesProcessed = 0;
5849  const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat;
5850 
5851  MA_ASSERT(pDevice != NULL);
5852  MA_ASSERT(frameCountInDeviceFormat > 0);
5853  MA_ASSERT(pFramesInDeviceFormat != NULL);
5854  MA_ASSERT(pRB != NULL);
5855 
5856  /* Write to the ring buffer. The ring buffer is in the client format which means we need to convert. */
5857  for (;;) {
5858  ma_uint32 framesToProcessInDeviceFormat = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
5859  ma_uint32 framesToProcessInClientFormat = MA_DATA_CONVERTER_STACK_BUFFER_SIZE / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
5860  ma_uint64 framesProcessedInDeviceFormat;
5861  ma_uint64 framesProcessedInClientFormat;
5862  void* pFramesInClientFormat;
5863 
5864  result = ma_pcm_rb_acquire_write(pRB, &framesToProcessInClientFormat, &pFramesInClientFormat);
5865  if (result != MA_SUCCESS) {
5866  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "Failed to acquire capture PCM frames from ring buffer.", result);
5867  break;
5868  }
5869 
5870  if (framesToProcessInClientFormat == 0) {
5872  break; /* Overrun. Not enough room in the ring buffer for input frame. Excess frames are dropped. */
5873  }
5874  }
5875 
5876  /* Convert. */
5877  framesProcessedInDeviceFormat = framesToProcessInDeviceFormat;
5878  framesProcessedInClientFormat = framesToProcessInClientFormat;
5879  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningFramesInDeviceFormat, &framesProcessedInDeviceFormat, pFramesInClientFormat, &framesProcessedInClientFormat);
5880  if (result != MA_SUCCESS) {
5881  break;
5882  }
5883 
5884  result = ma_pcm_rb_commit_write(pRB, (ma_uint32)framesProcessedInClientFormat, pFramesInClientFormat); /* Safe cast. */
5885  if (result != MA_SUCCESS) {
5886  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "Failed to commit capture PCM frames to ring buffer.", result);
5887  break;
5888  }
5889 
5890  pRunningFramesInDeviceFormat = ma_offset_ptr(pRunningFramesInDeviceFormat, framesProcessedInDeviceFormat * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
5891  totalDeviceFramesProcessed += (ma_uint32)framesProcessedInDeviceFormat; /* Safe cast. */
5892 
5893  /* We're done when we're unable to process any client nor device frames. */
5894  if (framesProcessedInClientFormat == 0 && framesProcessedInDeviceFormat == 0) {
5895  break; /* Done. */
5896  }
5897  }
5898 
5899  return MA_SUCCESS;
5900 }
5901 
5902 static ma_result ma_device__handle_duplex_callback_playback(ma_device* pDevice, ma_uint32 frameCount, void* pFramesInInternalFormat, ma_pcm_rb* pRB)
5903 {
5904  ma_result result;
5905  ma_uint8 playbackFramesInExternalFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
5906  ma_uint8 silentInputFrames[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
5907  ma_uint32 totalFramesToReadFromClient;
5908  ma_uint32 totalFramesReadFromClient;
5909  ma_uint32 totalFramesReadOut = 0;
5910 
5911  MA_ASSERT(pDevice != NULL);
5912  MA_ASSERT(frameCount > 0);
5913  MA_ASSERT(pFramesInInternalFormat != NULL);
5914  MA_ASSERT(pRB != NULL);
5915 
5916  /*
5917  Sitting in the ring buffer should be captured data from the capture callback in external format. If there's not enough data in there for
5918  the whole frameCount frames we just use silence instead for the input data.
5919  */
5920  MA_ZERO_MEMORY(silentInputFrames, sizeof(silentInputFrames));
5921 
5922  /* We need to calculate how many output frames are required to be read from the client to completely fill frameCount internal frames. */
5923  totalFramesToReadFromClient = (ma_uint32)ma_data_converter_get_required_input_frame_count(&pDevice->playback.converter, frameCount);
5924  totalFramesReadFromClient = 0;
5925  while (totalFramesReadFromClient < totalFramesToReadFromClient && ma_device_is_started(pDevice)) {
5926  ma_uint32 framesRemainingFromClient;
5927  ma_uint32 framesToProcessFromClient;
5928  ma_uint32 inputFrameCount;
5929  void* pInputFrames;
5930 
5931  framesRemainingFromClient = (totalFramesToReadFromClient - totalFramesReadFromClient);
5932  framesToProcessFromClient = sizeof(playbackFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
5933  if (framesToProcessFromClient > framesRemainingFromClient) {
5934  framesToProcessFromClient = framesRemainingFromClient;
5935  }
5936 
5937  /* We need to grab captured samples before firing the callback. If there's not enough input samples we just pass silence. */
5938  inputFrameCount = framesToProcessFromClient;
5939  result = ma_pcm_rb_acquire_read(pRB, &inputFrameCount, &pInputFrames);
5940  if (result == MA_SUCCESS) {
5941  if (inputFrameCount > 0) {
5942  /* Use actual input frames. */
5943  ma_device__on_data(pDevice, playbackFramesInExternalFormat, pInputFrames, inputFrameCount);
5944  } else {
5945  if (ma_pcm_rb_pointer_distance(pRB) == 0) {
5946  break; /* Underrun. */
5947  }
5948  }
5949 
5950  /* We're done with the captured samples. */
5951  result = ma_pcm_rb_commit_read(pRB, inputFrameCount, pInputFrames);
5952  if (result != MA_SUCCESS) {
5953  break; /* Don't know what to do here... Just abandon ship. */
5954  }
5955  } else {
5956  /* Use silent input frames. */
5957  inputFrameCount = ma_min(
5958  sizeof(playbackFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels),
5959  sizeof(silentInputFrames) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels)
5960  );
5961 
5962  ma_device__on_data(pDevice, playbackFramesInExternalFormat, silentInputFrames, inputFrameCount);
5963  }
5964 
5965  /* We have samples in external format so now we need to convert to internal format and output to the device. */
5966  {
5967  ma_uint64 framesConvertedIn = inputFrameCount;
5968  ma_uint64 framesConvertedOut = (frameCount - totalFramesReadOut);
5969  ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackFramesInExternalFormat, &framesConvertedIn, pFramesInInternalFormat, &framesConvertedOut);
5970 
5971  totalFramesReadFromClient += (ma_uint32)framesConvertedIn; /* Safe cast. */
5972  totalFramesReadOut += (ma_uint32)framesConvertedOut; /* Safe cast. */
5973  pFramesInInternalFormat = ma_offset_ptr(pFramesInInternalFormat, framesConvertedOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
5974  }
5975  }
5976 
5977  return MA_SUCCESS;
5978 }
5979 
5980 /* A helper for changing the state of the device. */
5981 static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_uint32 newState)
5982 {
5983  c89atomic_exchange_32(&pDevice->state, newState);
5984 }
5985 
5986 
5987 #ifdef MA_WIN32
5988  GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
5989  GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
5990  /*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
5991  /*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
5992 #endif
5993 
5994 
5995 
5997 {
5998  ma_uint32 i;
5999  for (i = 0; i < ma_countof(g_maFormatPriorities); ++i) {
6000  if (g_maFormatPriorities[i] == format) {
6001  return i;
6002  }
6003  }
6004 
6005  /* Getting here means the format could not be found or is equal to ma_format_unknown. */
6006  return (ma_uint32)-1;
6007 }
6008 
6009 static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType);
6010 
6011 
6013 {
6014  if (pDeviceDescriptor == NULL) {
6015  return MA_FALSE;
6016  }
6017 
6018  if (pDeviceDescriptor->format == ma_format_unknown) {
6019  return MA_FALSE;
6020  }
6021 
6022  if (pDeviceDescriptor->channels < MA_MIN_CHANNELS || pDeviceDescriptor->channels > MA_MAX_CHANNELS) {
6023  return MA_FALSE;
6024  }
6025 
6026  if (pDeviceDescriptor->sampleRate == 0) {
6027  return MA_FALSE;
6028  }
6029 
6030  return MA_TRUE;
6031 }
6032 
6033 
6035 {
6036  ma_result result = MA_SUCCESS;
6037  ma_bool32 exitLoop = MA_FALSE;
6038  ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
6039  ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
6040  ma_uint32 capturedDeviceDataCapInFrames = 0;
6041  ma_uint32 playbackDeviceDataCapInFrames = 0;
6042 
6043  MA_ASSERT(pDevice != NULL);
6044 
6045  /* Just some quick validation on the device type and the available callbacks. */
6046  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
6047  if (pDevice->pContext->callbacks.onDeviceRead == NULL) {
6048  return MA_NOT_IMPLEMENTED;
6049  }
6050 
6051  capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
6052  }
6053 
6054  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
6055  if (pDevice->pContext->callbacks.onDeviceWrite == NULL) {
6056  return MA_NOT_IMPLEMENTED;
6057  }
6058 
6059  playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
6060  }
6061 
6062  /* NOTE: The device was started outside of this function, in the worker thread. */
6063 
6064  while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
6065  switch (pDevice->type) {
6066  case ma_device_type_duplex:
6067  {
6068  /* The process is: onDeviceRead() -> convert -> callback -> convert -> onDeviceWrite() */
6069  ma_uint32 totalCapturedDeviceFramesProcessed = 0;
6070  ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
6071 
6072  while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
6073  ma_uint32 capturedDeviceFramesRemaining;
6074  ma_uint32 capturedDeviceFramesProcessed;
6075  ma_uint32 capturedDeviceFramesToProcess;
6076  ma_uint32 capturedDeviceFramesToTryProcessing = capturedDevicePeriodSizeInFrames - totalCapturedDeviceFramesProcessed;
6077  if (capturedDeviceFramesToTryProcessing > capturedDeviceDataCapInFrames) {
6078  capturedDeviceFramesToTryProcessing = capturedDeviceDataCapInFrames;
6079  }
6080 
6081  result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, capturedDeviceFramesToTryProcessing, &capturedDeviceFramesToProcess);
6082  if (result != MA_SUCCESS) {
6083  exitLoop = MA_TRUE;
6084  break;
6085  }
6086 
6087  capturedDeviceFramesRemaining = capturedDeviceFramesToProcess;
6088  capturedDeviceFramesProcessed = 0;
6089 
6090  /* At this point we have our captured data in device format and we now need to convert it to client format. */
6091  for (;;) {
6092  ma_uint8 capturedClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
6093  ma_uint8 playbackClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
6094  ma_uint32 capturedClientDataCapInFrames = sizeof(capturedClientData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
6095  ma_uint32 playbackClientDataCapInFrames = sizeof(playbackClientData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
6096  ma_uint64 capturedClientFramesToProcessThisIteration = ma_min(capturedClientDataCapInFrames, playbackClientDataCapInFrames);
6097  ma_uint64 capturedDeviceFramesToProcessThisIteration = capturedDeviceFramesRemaining;
6098  ma_uint8* pRunningCapturedDeviceFrames = ma_offset_ptr(capturedDeviceData, capturedDeviceFramesProcessed * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
6099 
6100  /* Convert capture data from device format to client format. */
6101  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningCapturedDeviceFrames, &capturedDeviceFramesToProcessThisIteration, capturedClientData, &capturedClientFramesToProcessThisIteration);
6102  if (result != MA_SUCCESS) {
6103  break;
6104  }
6105 
6106  /*
6107  If we weren't able to generate any output frames it must mean we've exhaused all of our input. The only time this would not be the case is if capturedClientData was too small
6108  which should never be the case when it's of the size MA_DATA_CONVERTER_STACK_BUFFER_SIZE.
6109  */
6110  if (capturedClientFramesToProcessThisIteration == 0) {
6111  break;
6112  }
6113 
6114  ma_device__on_data(pDevice, playbackClientData, capturedClientData, (ma_uint32)capturedClientFramesToProcessThisIteration); /* Safe cast .*/
6115 
6116  capturedDeviceFramesProcessed += (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
6117  capturedDeviceFramesRemaining -= (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
6118 
6119  /* At this point the playbackClientData buffer should be holding data that needs to be written to the device. */
6120  for (;;) {
6121  ma_uint64 convertedClientFrameCount = capturedClientFramesToProcessThisIteration;
6122  ma_uint64 convertedDeviceFrameCount = playbackDeviceDataCapInFrames;
6123  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackClientData, &convertedClientFrameCount, playbackDeviceData, &convertedDeviceFrameCount);
6124  if (result != MA_SUCCESS) {
6125  break;
6126  }
6127 
6128  result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, (ma_uint32)convertedDeviceFrameCount, NULL); /* Safe cast. */
6129  if (result != MA_SUCCESS) {
6130  exitLoop = MA_TRUE;
6131  break;
6132  }
6133 
6134  capturedClientFramesToProcessThisIteration -= (ma_uint32)convertedClientFrameCount; /* Safe cast. */
6135  if (capturedClientFramesToProcessThisIteration == 0) {
6136  break;
6137  }
6138  }
6139 
6140  /* In case an error happened from ma_device_write__null()... */
6141  if (result != MA_SUCCESS) {
6142  exitLoop = MA_TRUE;
6143  break;
6144  }
6145  }
6146 
6147  totalCapturedDeviceFramesProcessed += capturedDeviceFramesProcessed;
6148  }
6149  } break;
6150 
6153  {
6154  ma_uint32 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
6155  ma_uint32 framesReadThisPeriod = 0;
6156  while (framesReadThisPeriod < periodSizeInFrames) {
6157  ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
6158  ma_uint32 framesProcessed;
6159  ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
6160  if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
6161  framesToReadThisIteration = capturedDeviceDataCapInFrames;
6162  }
6163 
6164  result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
6165  if (result != MA_SUCCESS) {
6166  exitLoop = MA_TRUE;
6167  break;
6168  }
6169 
6170  ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
6171 
6172  framesReadThisPeriod += framesProcessed;
6173  }
6174  } break;
6175 
6177  {
6178  /* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
6179  ma_uint32 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
6180  ma_uint32 framesWrittenThisPeriod = 0;
6181  while (framesWrittenThisPeriod < periodSizeInFrames) {
6182  ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
6183  ma_uint32 framesProcessed;
6184  ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
6185  if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
6186  framesToWriteThisIteration = playbackDeviceDataCapInFrames;
6187  }
6188 
6189  ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
6190 
6191  result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
6192  if (result != MA_SUCCESS) {
6193  exitLoop = MA_TRUE;
6194  break;
6195  }
6196 
6197  framesWrittenThisPeriod += framesProcessed;
6198  }
6199  } break;
6200 
6201  /* Should never get here. */
6202  default: break;
6203  }
6204  }
6205 
6206  return result;
6207 }
6208 
6209 
6210 
6211 /*******************************************************************************
6212 
6213 Null Backend
6214 
6215 *******************************************************************************/
6216 #ifdef MA_HAS_NULL
6217 
6218 #define MA_DEVICE_OP_NONE__NULL 0
6219 #define MA_DEVICE_OP_START__NULL 1
6220 #define MA_DEVICE_OP_SUSPEND__NULL 2
6221 #define MA_DEVICE_OP_KILL__NULL 3
6222 
6224 {
6225  ma_device* pDevice = (ma_device*)pData;
6226  MA_ASSERT(pDevice != NULL);
6227 
6228  for (;;) { /* Keep the thread alive until the device is uninitialized. */
6229  ma_uint32 operation;
6230 
6231  /* Wait for an operation to be requested. */
6232  ma_event_wait(&pDevice->null_device.operationEvent);
6233 
6234  /* At this point an event should have been triggered. */
6235  operation = pDevice->null_device.operation;
6236 
6237  /* Starting the device needs to put the thread into a loop. */
6238  if (operation == MA_DEVICE_OP_START__NULL) {
6239  /* Reset the timer just in case. */
6240  ma_timer_init(&pDevice->null_device.timer);
6241 
6242  /* Getting here means a suspend or kill operation has been requested. */
6243  pDevice->null_device.operationResult = MA_SUCCESS;
6244  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6245  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
6246  continue;
6247  }
6248 
6249  /* Suspending the device means we need to stop the timer and just continue the loop. */
6250  if (operation == MA_DEVICE_OP_SUSPEND__NULL) {
6251  /* We need to add the current run time to the prior run time, then reset the timer. */
6252  pDevice->null_device.priorRunTime += ma_timer_get_time_in_seconds(&pDevice->null_device.timer);
6253  ma_timer_init(&pDevice->null_device.timer);
6254 
6255  /* We're done. */
6256  pDevice->null_device.operationResult = MA_SUCCESS;
6257  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6258  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
6259  continue;
6260  }
6261 
6262  /* Killing the device means we need to get out of this loop so that this thread can terminate. */
6263  if (operation == MA_DEVICE_OP_KILL__NULL) {
6264  pDevice->null_device.operationResult = MA_SUCCESS;
6265  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6266  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
6267  break;
6268  }
6269 
6270  /* Getting a signal on a "none" operation probably means an error. Return invalid operation. */
6271  if (operation == MA_DEVICE_OP_NONE__NULL) {
6272  MA_ASSERT(MA_FALSE); /* <-- Trigger this in debug mode to ensure developers are aware they're doing something wrong (or there's a bug in a miniaudio). */
6273  pDevice->null_device.operationResult = MA_INVALID_OPERATION;
6274  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6275  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
6276  continue; /* Continue the loop. Don't terminate. */
6277  }
6278  }
6279 
6280  return (ma_thread_result)0;
6281 }
6282 
6284 {
6285  ma_result result;
6286 
6287  /*
6288  TODO: Need to review this and consider just using mutual exclusion. I think the original motivation
6289  for this was to just post the event to a queue and return immediately, but that has since changed
6290  and now this function is synchronous. I think this can be simplified to just use a mutex.
6291  */
6292 
6293  /*
6294  The first thing to do is wait for an operation slot to become available. We only have a single slot for this, but we could extend this later
6295  to support queing of operations.
6296  */
6297  result = ma_semaphore_wait(&pDevice->null_device.operationSemaphore);
6298  if (result != MA_SUCCESS) {
6299  return result; /* Failed to wait for the event. */
6300  }
6301 
6302  /*
6303  When we get here it means the background thread is not referencing the operation code and it can be changed. After changing this we need to
6304  signal an event to the worker thread to let it know that it can start work.
6305  */
6306  pDevice->null_device.operation = operation;
6307 
6308  /* Once the operation code has been set, the worker thread can start work. */
6309  if (ma_event_signal(&pDevice->null_device.operationEvent) != MA_SUCCESS) {
6310  return MA_ERROR;
6311  }
6312 
6313  /* We want everything to be synchronous so we're going to wait for the worker thread to complete it's operation. */
6314  if (ma_event_wait(&pDevice->null_device.operationCompletionEvent) != MA_SUCCESS) {
6315  return MA_ERROR;
6316  }
6317 
6318  return pDevice->null_device.operationResult;
6319 }
6320 
6322 {
6323  ma_uint32 internalSampleRate;
6324  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
6325  internalSampleRate = pDevice->capture.internalSampleRate;
6326  } else {
6327  internalSampleRate = pDevice->playback.internalSampleRate;
6328  }
6329 
6330  return (ma_uint64)((pDevice->null_device.priorRunTime + ma_timer_get_time_in_seconds(&pDevice->null_device.timer)) * internalSampleRate);
6331 }
6332 
6334 {
6335  ma_bool32 cbResult = MA_TRUE;
6336 
6337  MA_ASSERT(pContext != NULL);
6338  MA_ASSERT(callback != NULL);
6339 
6340  /* Playback. */
6341  if (cbResult) {
6342  ma_device_info deviceInfo;
6343  MA_ZERO_OBJECT(&deviceInfo);
6344  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), "NULL Playback Device", (size_t)-1);
6345  deviceInfo.isDefault = MA_TRUE; /* Only one playback and capture device for the null backend, so might as well mark as default. */
6346  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
6347  }
6348 
6349  /* Capture. */
6350  if (cbResult) {
6351  ma_device_info deviceInfo;
6352  MA_ZERO_OBJECT(&deviceInfo);
6353  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), "NULL Capture Device", (size_t)-1);
6354  deviceInfo.isDefault = MA_TRUE; /* Only one playback and capture device for the null backend, so might as well mark as default. */
6355  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
6356  }
6357 
6358  (void)cbResult; /* Silence a static analysis warning. */
6359 
6360  return MA_SUCCESS;
6361 }
6362 
6363 static ma_result ma_context_get_device_info__null(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
6364 {
6365  MA_ASSERT(pContext != NULL);
6366 
6367  if (pDeviceID != NULL && pDeviceID->nullbackend != 0) {
6368  return MA_NO_DEVICE; /* Don't know the device. */
6369  }
6370 
6371  /* Name / Description */
6372  if (deviceType == ma_device_type_playback) {
6373  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), "NULL Playback Device", (size_t)-1);
6374  } else {
6375  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), "NULL Capture Device", (size_t)-1);
6376  }
6377 
6378  pDeviceInfo->isDefault = MA_TRUE; /* Only one playback and capture device for the null backend, so might as well mark as default. */
6379 
6380  /* Support everything on the null backend. */
6381  pDeviceInfo->nativeDataFormats[0].format = ma_format_unknown;
6382  pDeviceInfo->nativeDataFormats[0].channels = 0;
6383  pDeviceInfo->nativeDataFormats[0].sampleRate = 0;
6384  pDeviceInfo->nativeDataFormats[0].flags = 0;
6385  pDeviceInfo->nativeDataFormatCount = 1;
6386 
6387  (void)pContext;
6388  return MA_SUCCESS;
6389 }
6390 
6391 
6393 {
6394  MA_ASSERT(pDevice != NULL);
6395 
6396  /* Keep it clean and wait for the device thread to finish before returning. */
6398 
6399  /* Wait for the thread to finish before continuing. */
6400  ma_thread_wait(&pDevice->null_device.deviceThread);
6401 
6402  /* At this point the loop in the device thread is as good as terminated so we can uninitialize our events. */
6403  ma_semaphore_uninit(&pDevice->null_device.operationSemaphore);
6404  ma_event_uninit(&pDevice->null_device.operationCompletionEvent);
6405  ma_event_uninit(&pDevice->null_device.operationEvent);
6406 
6407  return MA_SUCCESS;
6408 }
6409 
6410 static ma_result ma_device_init__null(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
6411 {
6412  ma_result result;
6413 
6414  MA_ASSERT(pDevice != NULL);
6415 
6416  MA_ZERO_OBJECT(&pDevice->null_device);
6417 
6418  if (pConfig->deviceType == ma_device_type_loopback) {
6420  }
6421 
6422  /* The null backend supports everything exactly as we specify it. */
6423  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
6424  pDescriptorCapture->format = (pDescriptorCapture->format != ma_format_unknown) ? pDescriptorCapture->format : MA_DEFAULT_FORMAT;
6425  pDescriptorCapture->channels = (pDescriptorCapture->channels != 0) ? pDescriptorCapture->channels : MA_DEFAULT_CHANNELS;
6426  pDescriptorCapture->sampleRate = (pDescriptorCapture->sampleRate != 0) ? pDescriptorCapture->sampleRate : MA_DEFAULT_SAMPLE_RATE;
6427 
6428  if (pDescriptorCapture->channelMap[0] == MA_CHANNEL_NONE) {
6429  ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
6430  }
6431 
6432  pDescriptorCapture->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorCapture, pDescriptorCapture->sampleRate, pConfig->performanceProfile);
6433  }
6434 
6435  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
6436  pDescriptorPlayback->format = (pDescriptorPlayback->format != ma_format_unknown) ? pDescriptorPlayback->format : MA_DEFAULT_FORMAT;
6437  pDescriptorPlayback->channels = (pDescriptorPlayback->channels != 0) ? pDescriptorPlayback->channels : MA_DEFAULT_CHANNELS;
6438  pDescriptorPlayback->sampleRate = (pDescriptorPlayback->sampleRate != 0) ? pDescriptorPlayback->sampleRate : MA_DEFAULT_SAMPLE_RATE;
6439 
6440  if (pDescriptorPlayback->channelMap[0] == MA_CHANNEL_NONE) {
6441  ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
6442  }
6443 
6444  pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
6445  }
6446 
6447  /*
6448  In order to get timing right, we need to create a thread that does nothing but keeps track of the timer. This timer is started when the
6449  first period is "written" to it, and then stopped in ma_device_stop__null().
6450  */
6451  result = ma_event_init(&pDevice->null_device.operationEvent);
6452  if (result != MA_SUCCESS) {
6453  return result;
6454  }
6455 
6456  result = ma_event_init(&pDevice->null_device.operationCompletionEvent);
6457  if (result != MA_SUCCESS) {
6458  return result;
6459  }
6460 
6461  result = ma_semaphore_init(1, &pDevice->null_device.operationSemaphore); /* <-- It's important that the initial value is set to 1. */
6462  if (result != MA_SUCCESS) {
6463  return result;
6464  }
6465 
6466  result = ma_thread_create(&pDevice->null_device.deviceThread, pDevice->pContext->threadPriority, 0, ma_device_thread__null, pDevice, &pDevice->pContext->allocationCallbacks);
6467  if (result != MA_SUCCESS) {
6468  return result;
6469  }
6470 
6471  return MA_SUCCESS;
6472 }
6473 
6475 {
6476  MA_ASSERT(pDevice != NULL);
6477 
6479 
6480  c89atomic_exchange_32(&pDevice->null_device.isStarted, MA_TRUE);
6481  return MA_SUCCESS;
6482 }
6483 
6485 {
6486  MA_ASSERT(pDevice != NULL);
6487 
6489 
6490  c89atomic_exchange_32(&pDevice->null_device.isStarted, MA_FALSE);
6491  return MA_SUCCESS;
6492 }
6493 
6494 static ma_result ma_device_write__null(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
6495 {
6496  ma_result result = MA_SUCCESS;
6497  ma_uint32 totalPCMFramesProcessed;
6498  ma_bool32 wasStartedOnEntry;
6499 
6500  if (pFramesWritten != NULL) {
6501  *pFramesWritten = 0;
6502  }
6503 
6504  wasStartedOnEntry = c89atomic_load_32(&pDevice->null_device.isStarted);
6505 
6506  /* Keep going until everything has been read. */
6507  totalPCMFramesProcessed = 0;
6508  while (totalPCMFramesProcessed < frameCount) {
6509  ma_uint64 targetFrame;
6510 
6511  /* If there are any frames remaining in the current period, consume those first. */
6512  if (pDevice->null_device.currentPeriodFramesRemainingPlayback > 0) {
6513  ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
6514  ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingPlayback;
6515  if (framesToProcess > framesRemaining) {
6516  framesToProcess = framesRemaining;
6517  }
6518 
6519  /* We don't actually do anything with pPCMFrames, so just mark it as unused to prevent a warning. */
6520  (void)pPCMFrames;
6521 
6522  pDevice->null_device.currentPeriodFramesRemainingPlayback -= framesToProcess;
6523  totalPCMFramesProcessed += framesToProcess;
6524  }
6525 
6526  /* If we've consumed the current period we'll need to mark it as such an ensure the device is started if it's not already. */
6527  if (pDevice->null_device.currentPeriodFramesRemainingPlayback == 0) {
6528  pDevice->null_device.currentPeriodFramesRemainingPlayback = 0;
6529 
6530  if (!c89atomic_load_32(&pDevice->null_device.isStarted) && !wasStartedOnEntry) {
6531  result = ma_device_start__null(pDevice);
6532  if (result != MA_SUCCESS) {
6533  break;
6534  }
6535  }
6536  }
6537 
6538  /* If we've consumed the whole buffer we can return now. */
6539  MA_ASSERT(totalPCMFramesProcessed <= frameCount);
6540  if (totalPCMFramesProcessed == frameCount) {
6541  break;
6542  }
6543 
6544  /* Getting here means we've still got more frames to consume, we but need to wait for it to become available. */
6545  targetFrame = pDevice->null_device.lastProcessedFramePlayback;
6546  for (;;) {
6547  ma_uint64 currentFrame;
6548 
6549  /* Stop waiting if the device has been stopped. */
6550  if (!c89atomic_load_32(&pDevice->null_device.isStarted)) {
6551  break;
6552  }
6553 
6554  currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
6555  if (currentFrame >= targetFrame) {
6556  break;
6557  }
6558 
6559  /* Getting here means we haven't yet reached the target sample, so continue waiting. */
6560  ma_sleep(10);
6561  }
6562 
6563  pDevice->null_device.lastProcessedFramePlayback += pDevice->playback.internalPeriodSizeInFrames;
6564  pDevice->null_device.currentPeriodFramesRemainingPlayback = pDevice->playback.internalPeriodSizeInFrames;
6565  }
6566 
6567  if (pFramesWritten != NULL) {
6568  *pFramesWritten = totalPCMFramesProcessed;
6569  }
6570 
6571  return result;
6572 }
6573 
6574 static ma_result ma_device_read__null(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
6575 {
6576  ma_result result = MA_SUCCESS;
6577  ma_uint32 totalPCMFramesProcessed;
6578 
6579  if (pFramesRead != NULL) {
6580  *pFramesRead = 0;
6581  }
6582 
6583  /* Keep going until everything has been read. */
6584  totalPCMFramesProcessed = 0;
6585  while (totalPCMFramesProcessed < frameCount) {
6586  ma_uint64 targetFrame;
6587 
6588  /* If there are any frames remaining in the current period, consume those first. */
6589  if (pDevice->null_device.currentPeriodFramesRemainingCapture > 0) {
6591  ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
6592  ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingCapture;
6593  if (framesToProcess > framesRemaining) {
6594  framesToProcess = framesRemaining;
6595  }
6596 
6597  /* We need to ensure the output buffer is zeroed. */
6598  MA_ZERO_MEMORY(ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed*bpf), framesToProcess*bpf);
6599 
6600  pDevice->null_device.currentPeriodFramesRemainingCapture -= framesToProcess;
6601  totalPCMFramesProcessed += framesToProcess;
6602  }
6603 
6604  /* If we've consumed the current period we'll need to mark it as such an ensure the device is started if it's not already. */
6605  if (pDevice->null_device.currentPeriodFramesRemainingCapture == 0) {
6606  pDevice->null_device.currentPeriodFramesRemainingCapture = 0;
6607  }
6608 
6609  /* If we've consumed the whole buffer we can return now. */
6610  MA_ASSERT(totalPCMFramesProcessed <= frameCount);
6611  if (totalPCMFramesProcessed == frameCount) {
6612  break;
6613  }
6614 
6615  /* Getting here means we've still got more frames to consume, we but need to wait for it to become available. */
6616  targetFrame = pDevice->null_device.lastProcessedFrameCapture + pDevice->capture.internalPeriodSizeInFrames;
6617  for (;;) {
6618  ma_uint64 currentFrame;
6619 
6620  /* Stop waiting if the device has been stopped. */
6621  if (!c89atomic_load_32(&pDevice->null_device.isStarted)) {
6622  break;
6623  }
6624 
6625  currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
6626  if (currentFrame >= targetFrame) {
6627  break;
6628  }
6629 
6630  /* Getting here means we haven't yet reached the target sample, so continue waiting. */
6631  ma_sleep(10);
6632  }
6633 
6634  pDevice->null_device.lastProcessedFrameCapture += pDevice->capture.internalPeriodSizeInFrames;
6635  pDevice->null_device.currentPeriodFramesRemainingCapture = pDevice->capture.internalPeriodSizeInFrames;
6636  }
6637 
6638  if (pFramesRead != NULL) {
6639  *pFramesRead = totalPCMFramesProcessed;
6640  }
6641 
6642  return result;
6643 }
6644 
6646 {
6647  MA_ASSERT(pContext != NULL);
6648  MA_ASSERT(pContext->backend == ma_backend_null);
6649 
6650  (void)pContext;
6651  return MA_SUCCESS;
6652 }
6653 
6655 {
6656  MA_ASSERT(pContext != NULL);
6657 
6658  (void)pConfig;
6659  (void)pContext;
6660 
6661  pCallbacks->onContextInit = ma_context_init__null;
6665  pCallbacks->onDeviceInit = ma_device_init__null;
6666  pCallbacks->onDeviceUninit = ma_device_uninit__null;
6667  pCallbacks->onDeviceStart = ma_device_start__null;
6668  pCallbacks->onDeviceStop = ma_device_stop__null;
6669  pCallbacks->onDeviceRead = ma_device_read__null;
6670  pCallbacks->onDeviceWrite = ma_device_write__null;
6671  pCallbacks->onDeviceDataLoop = NULL; /* Our backend is asynchronous with a blocking read-write API which means we can get miniaudio to deal with the audio thread. */
6672 
6673  /* The null backend always works. */
6674  return MA_SUCCESS;
6675 }
6676 #endif
6677 
6678 
6679 
6680 /*******************************************************************************
6681 
6682 WIN32 COMMON
6683 
6684 *******************************************************************************/
6685 #if defined(MA_WIN32)
6686 #if defined(MA_WIN32_DESKTOP)
6687  #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit)
6688  #define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
6689  #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
6690  #define ma_CoTaskMemFree(pContext, pv) ((MA_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pv)
6691  #define ma_PropVariantClear(pContext, pvar) ((MA_PFN_PropVariantClear)pContext->win32.PropVariantClear)(pvar)
6692 #else
6693  #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) CoInitializeEx(pvReserved, dwCoInit)
6694  #define ma_CoUninitialize(pContext) CoUninitialize()
6695  #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv)
6696  #define ma_CoTaskMemFree(pContext, pv) CoTaskMemFree(pv)
6697  #define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar)
6698 #endif
6699 
6700 #if !defined(MAXULONG_PTR) && !defined(__WATCOMC__)
6701 typedef size_t DWORD_PTR;
6702 #endif
6703 
6704 #if !defined(WAVE_FORMAT_44M08)
6705 #define WAVE_FORMAT_44M08 0x00000100
6706 #define WAVE_FORMAT_44S08 0x00000200
6707 #define WAVE_FORMAT_44M16 0x00000400
6708 #define WAVE_FORMAT_44S16 0x00000800
6709 #define WAVE_FORMAT_48M08 0x00001000
6710 #define WAVE_FORMAT_48S08 0x00002000
6711 #define WAVE_FORMAT_48M16 0x00004000
6712 #define WAVE_FORMAT_48S16 0x00008000
6713 #define WAVE_FORMAT_96M08 0x00010000
6714 #define WAVE_FORMAT_96S08 0x00020000
6715 #define WAVE_FORMAT_96M16 0x00040000
6716 #define WAVE_FORMAT_96S16 0x00080000
6717 #endif
6718 
6719 #ifndef SPEAKER_FRONT_LEFT
6720 #define SPEAKER_FRONT_LEFT 0x1
6721 #define SPEAKER_FRONT_RIGHT 0x2
6722 #define SPEAKER_FRONT_CENTER 0x4
6723 #define SPEAKER_LOW_FREQUENCY 0x8
6724 #define SPEAKER_BACK_LEFT 0x10
6725 #define SPEAKER_BACK_RIGHT 0x20
6726 #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
6727 #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
6728 #define SPEAKER_BACK_CENTER 0x100
6729 #define SPEAKER_SIDE_LEFT 0x200
6730 #define SPEAKER_SIDE_RIGHT 0x400
6731 #define SPEAKER_TOP_CENTER 0x800
6732 #define SPEAKER_TOP_FRONT_LEFT 0x1000
6733 #define SPEAKER_TOP_FRONT_CENTER 0x2000
6734 #define SPEAKER_TOP_FRONT_RIGHT 0x4000
6735 #define SPEAKER_TOP_BACK_LEFT 0x8000
6736 #define SPEAKER_TOP_BACK_CENTER 0x10000
6737 #define SPEAKER_TOP_BACK_RIGHT 0x20000
6738 #endif
6739 
6740 /*
6741 The SDK that comes with old versions of MSVC (VC6, for example) does not appear to define WAVEFORMATEXTENSIBLE. We
6742 define our own implementation in this case.
6743 */
6744 #if (defined(_MSC_VER) && !defined(_WAVEFORMATEXTENSIBLE_)) || defined(__DMC__)
6745 typedef struct
6746 {
6747  WAVEFORMATEX Format;
6748  union
6749  {
6750  WORD wValidBitsPerSample;
6751  WORD wSamplesPerBlock;
6752  WORD wReserved;
6753  } Samples;
6754  DWORD dwChannelMask;
6755  GUID SubFormat;
6756 } WAVEFORMATEXTENSIBLE;
6757 #endif
6758 
6759 #ifndef WAVE_FORMAT_EXTENSIBLE
6760 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
6761 #endif
6762 
6763 #ifndef WAVE_FORMAT_IEEE_FLOAT
6764 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
6765 #endif
6766 
6767 /* Converts an individual Win32-style channel identifier (SPEAKER_FRONT_LEFT, etc.) to miniaudio. */
6768 static ma_uint8 ma_channel_id_to_ma__win32(DWORD id)
6769 {
6770  switch (id)
6771  {
6772  case SPEAKER_FRONT_LEFT: return MA_CHANNEL_FRONT_LEFT;
6773  case SPEAKER_FRONT_RIGHT: return MA_CHANNEL_FRONT_RIGHT;
6774  case SPEAKER_FRONT_CENTER: return MA_CHANNEL_FRONT_CENTER;
6775  case SPEAKER_LOW_FREQUENCY: return MA_CHANNEL_LFE;
6776  case SPEAKER_BACK_LEFT: return MA_CHANNEL_BACK_LEFT;
6777  case SPEAKER_BACK_RIGHT: return MA_CHANNEL_BACK_RIGHT;
6778  case SPEAKER_FRONT_LEFT_OF_CENTER: return MA_CHANNEL_FRONT_LEFT_CENTER;
6779  case SPEAKER_FRONT_RIGHT_OF_CENTER: return MA_CHANNEL_FRONT_RIGHT_CENTER;
6780  case SPEAKER_BACK_CENTER: return MA_CHANNEL_BACK_CENTER;
6781  case SPEAKER_SIDE_LEFT: return MA_CHANNEL_SIDE_LEFT;
6782  case SPEAKER_SIDE_RIGHT: return MA_CHANNEL_SIDE_RIGHT;
6783  case SPEAKER_TOP_CENTER: return MA_CHANNEL_TOP_CENTER;
6784  case SPEAKER_TOP_FRONT_LEFT: return MA_CHANNEL_TOP_FRONT_LEFT;
6785  case SPEAKER_TOP_FRONT_CENTER: return MA_CHANNEL_TOP_FRONT_CENTER;
6786  case SPEAKER_TOP_FRONT_RIGHT: return MA_CHANNEL_TOP_FRONT_RIGHT;
6787  case SPEAKER_TOP_BACK_LEFT: return MA_CHANNEL_TOP_BACK_LEFT;
6788  case SPEAKER_TOP_BACK_CENTER: return MA_CHANNEL_TOP_BACK_CENTER;
6789  case SPEAKER_TOP_BACK_RIGHT: return MA_CHANNEL_TOP_BACK_RIGHT;
6790  default: return 0;
6791  }
6792 }
6793 
6794 /* Converts an individual miniaudio channel identifier (MA_CHANNEL_FRONT_LEFT, etc.) to Win32-style. */
6795 static DWORD ma_channel_id_to_win32(DWORD id)
6796 {
6797  switch (id)
6798  {
6799  case MA_CHANNEL_MONO: return SPEAKER_FRONT_CENTER;
6800  case MA_CHANNEL_FRONT_LEFT: return SPEAKER_FRONT_LEFT;
6801  case MA_CHANNEL_FRONT_RIGHT: return SPEAKER_FRONT_RIGHT;
6802  case MA_CHANNEL_FRONT_CENTER: return SPEAKER_FRONT_CENTER;
6803  case MA_CHANNEL_LFE: return SPEAKER_LOW_FREQUENCY;
6804  case MA_CHANNEL_BACK_LEFT: return SPEAKER_BACK_LEFT;
6805  case MA_CHANNEL_BACK_RIGHT: return SPEAKER_BACK_RIGHT;
6806  case MA_CHANNEL_FRONT_LEFT_CENTER: return SPEAKER_FRONT_LEFT_OF_CENTER;
6807  case MA_CHANNEL_FRONT_RIGHT_CENTER: return SPEAKER_FRONT_RIGHT_OF_CENTER;
6808  case MA_CHANNEL_BACK_CENTER: return SPEAKER_BACK_CENTER;
6809  case MA_CHANNEL_SIDE_LEFT: return SPEAKER_SIDE_LEFT;
6810  case MA_CHANNEL_SIDE_RIGHT: return SPEAKER_SIDE_RIGHT;
6811  case MA_CHANNEL_TOP_CENTER: return SPEAKER_TOP_CENTER;
6812  case MA_CHANNEL_TOP_FRONT_LEFT: return SPEAKER_TOP_FRONT_LEFT;
6813  case MA_CHANNEL_TOP_FRONT_CENTER: return SPEAKER_TOP_FRONT_CENTER;
6814  case MA_CHANNEL_TOP_FRONT_RIGHT: return SPEAKER_TOP_FRONT_RIGHT;
6815  case MA_CHANNEL_TOP_BACK_LEFT: return SPEAKER_TOP_BACK_LEFT;
6816  case MA_CHANNEL_TOP_BACK_CENTER: return SPEAKER_TOP_BACK_CENTER;
6817  case MA_CHANNEL_TOP_BACK_RIGHT: return SPEAKER_TOP_BACK_RIGHT;
6818  default: return 0;
6819  }
6820 }
6821 
6822 /* Converts a channel mapping to a Win32-style channel mask. */
6823 static DWORD ma_channel_map_to_channel_mask__win32(const ma_channel* pChannelMap, ma_uint32 channels)
6824 {
6825  DWORD dwChannelMask = 0;
6826  ma_uint32 iChannel;
6827 
6828  for (iChannel = 0; iChannel < channels; ++iChannel) {
6829  dwChannelMask |= ma_channel_id_to_win32(pChannelMap[iChannel]);
6830  }
6831 
6832  return dwChannelMask;
6833 }
6834 
6835 /* Converts a Win32-style channel mask to a miniaudio channel map. */
6836 static void ma_channel_mask_to_channel_map__win32(DWORD dwChannelMask, ma_uint32 channels, ma_channel* pChannelMap)
6837 {
6838  if (channels == 1 && dwChannelMask == 0) {
6839  pChannelMap[0] = MA_CHANNEL_MONO;
6840  } else if (channels == 2 && dwChannelMask == 0) {
6841  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
6842  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
6843  } else {
6844  if (channels == 1 && (dwChannelMask & SPEAKER_FRONT_CENTER) != 0) {
6845  pChannelMap[0] = MA_CHANNEL_MONO;
6846  } else {
6847  /* Just iterate over each bit. */
6848  ma_uint32 iChannel = 0;
6849  ma_uint32 iBit;
6850 
6851  for (iBit = 0; iBit < 32 && iChannel < channels; ++iBit) {
6852  DWORD bitValue = (dwChannelMask & (1UL << iBit));
6853  if (bitValue != 0) {
6854  /* The bit is set. */
6855  pChannelMap[iChannel] = ma_channel_id_to_ma__win32(bitValue);
6856  iChannel += 1;
6857  }
6858  }
6859  }
6860  }
6861 }
6862 
6863 #ifdef __cplusplus
6864 static ma_bool32 ma_is_guid_equal(const void* a, const void* b)
6865 {
6866  return IsEqualGUID(*(const GUID*)a, *(const GUID*)b);
6867 }
6868 #else
6869 #define ma_is_guid_equal(a, b) IsEqualGUID((const GUID*)a, (const GUID*)b)
6870 #endif
6871 
6872 static MA_INLINE ma_bool32 ma_is_guid_null(const void* guid)
6873 {
6874  static GUID nullguid = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
6875  return ma_is_guid_equal(guid, &nullguid);
6876 }
6877 
6878 static ma_format ma_format_from_WAVEFORMATEX(const WAVEFORMATEX* pWF)
6879 {
6880  MA_ASSERT(pWF != NULL);
6881 
6882  if (pWF->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
6883  const WAVEFORMATEXTENSIBLE* pWFEX = (const WAVEFORMATEXTENSIBLE*)pWF;
6884  if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_PCM)) {
6885  if (pWFEX->Samples.wValidBitsPerSample == 32) {
6886  return ma_format_s32;
6887  }
6888  if (pWFEX->Samples.wValidBitsPerSample == 24) {
6889  if (pWFEX->Format.wBitsPerSample == 32) {
6890  /*return ma_format_s24_32;*/
6891  }
6892  if (pWFEX->Format.wBitsPerSample == 24) {
6893  return ma_format_s24;
6894  }
6895  }
6896  if (pWFEX->Samples.wValidBitsPerSample == 16) {
6897  return ma_format_s16;
6898  }
6899  if (pWFEX->Samples.wValidBitsPerSample == 8) {
6900  return ma_format_u8;
6901  }
6902  }
6903  if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
6904  if (pWFEX->Samples.wValidBitsPerSample == 32) {
6905  return ma_format_f32;
6906  }
6907  /*
6908  if (pWFEX->Samples.wValidBitsPerSample == 64) {
6909  return ma_format_f64;
6910  }
6911  */
6912  }
6913  } else {
6914  if (pWF->wFormatTag == WAVE_FORMAT_PCM) {
6915  if (pWF->wBitsPerSample == 32) {
6916  return ma_format_s32;
6917  }
6918  if (pWF->wBitsPerSample == 24) {
6919  return ma_format_s24;
6920  }
6921  if (pWF->wBitsPerSample == 16) {
6922  return ma_format_s16;
6923  }
6924  if (pWF->wBitsPerSample == 8) {
6925  return ma_format_u8;
6926  }
6927  }
6928  if (pWF->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
6929  if (pWF->wBitsPerSample == 32) {
6930  return ma_format_f32;
6931  }
6932  if (pWF->wBitsPerSample == 64) {
6933  /*return ma_format_f64;*/
6934  }
6935  }
6936  }
6937 
6938  return ma_format_unknown;
6939 }
6940 #endif
6941 
6942 
6943 /*******************************************************************************
6944 
6945 WASAPI Backend
6946 
6947 *******************************************************************************/
6948 #ifdef MA_HAS_WASAPI
6949 #if 0
6950 #if defined(_MSC_VER)
6951  #pragma warning(push)
6952  #pragma warning(disable:4091) /* 'typedef ': ignored on left of '' when no variable is declared */
6953 #endif
6954 #include <audioclient.h>
6955 #include <mmdeviceapi.h>
6956 #if defined(_MSC_VER)
6957  #pragma warning(pop)
6958 #endif
6959 #endif /* 0 */
6960 
6961 static ma_result ma_device_reroute__wasapi(ma_device* pDevice, ma_device_type deviceType);
6962 
6963 /* Some compilers don't define VerifyVersionInfoW. Need to write this ourselves. */
6964 #define MA_WIN32_WINNT_VISTA 0x0600
6965 #define MA_VER_MINORVERSION 0x01
6966 #define MA_VER_MAJORVERSION 0x02
6967 #define MA_VER_SERVICEPACKMAJOR 0x20
6968 #define MA_VER_GREATER_EQUAL 0x03
6969 
6970 typedef struct {
6971  DWORD dwOSVersionInfoSize;
6972  DWORD dwMajorVersion;
6973  DWORD dwMinorVersion;
6974  DWORD dwBuildNumber;
6975  DWORD dwPlatformId;
6976  WCHAR szCSDVersion[128];
6977  WORD wServicePackMajor;
6978  WORD wServicePackMinor;
6979  WORD wSuiteMask;
6980  BYTE wProductType;
6981  BYTE wReserved;
6982 } ma_OSVERSIONINFOEXW;
6983 
6984 typedef BOOL (WINAPI * ma_PFNVerifyVersionInfoW) (ma_OSVERSIONINFOEXW* lpVersionInfo, DWORD dwTypeMask, DWORDLONG dwlConditionMask);
6985 typedef ULONGLONG (WINAPI * ma_PFNVerSetConditionMask)(ULONGLONG dwlConditionMask, DWORD dwTypeBitMask, BYTE dwConditionMask);
6986 
6987 
6988 #ifndef PROPERTYKEY_DEFINED
6989 #define PROPERTYKEY_DEFINED
6990 #ifndef __WATCOMC__
6991 typedef struct
6992 {
6993  GUID fmtid;
6994  DWORD pid;
6995 } PROPERTYKEY;
6996 #endif
6997 #endif
6998 
6999 /* Some compilers don't define PropVariantInit(). We just do this ourselves since it's just a memset(). */
7000 static MA_INLINE void ma_PropVariantInit(PROPVARIANT* pProp)
7001 {
7002  MA_ZERO_OBJECT(pProp);
7003 }
7004 
7005 
7006 static const PROPERTYKEY MA_PKEY_Device_FriendlyName = {{0xA45C254E, 0xDF1C, 0x4EFD, {0x80, 0x20, 0x67, 0xD1, 0x46, 0xA8, 0x50, 0xE0}}, 14};
7007 static const PROPERTYKEY MA_PKEY_AudioEngine_DeviceFormat = {{0xF19F064D, 0x82C, 0x4E27, {0xBC, 0x73, 0x68, 0x82, 0xA1, 0xBB, 0x8E, 0x4C}}, 0};
7008 
7009 static const IID MA_IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; /* 00000000-0000-0000-C000-000000000046 */
7010 #ifndef MA_WIN32_DESKTOP
7011 static const IID MA_IID_IAgileObject = {0x94EA2B94, 0xE9CC, 0x49E0, {0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90}}; /* 94EA2B94-E9CC-49E0-C0FF-EE64CA8F5B90 */
7012 #endif
7013 
7014 static const IID MA_IID_IAudioClient = {0x1CB9AD4C, 0xDBFA, 0x4C32, {0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}}; /* 1CB9AD4C-DBFA-4C32-B178-C2F568A703B2 = __uuidof(IAudioClient) */
7015 static const IID MA_IID_IAudioClient2 = {0x726778CD, 0xF60A, 0x4EDA, {0x82, 0xDE, 0xE4, 0x76, 0x10, 0xCD, 0x78, 0xAA}}; /* 726778CD-F60A-4EDA-82DE-E47610CD78AA = __uuidof(IAudioClient2) */
7016 static const IID MA_IID_IAudioClient3 = {0x7ED4EE07, 0x8E67, 0x4CD4, {0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42}}; /* 7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42 = __uuidof(IAudioClient3) */
7017 static const IID MA_IID_IAudioRenderClient = {0xF294ACFC, 0x3146, 0x4483, {0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}}; /* F294ACFC-3146-4483-A7BF-ADDCA7C260E2 = __uuidof(IAudioRenderClient) */
7018 static const IID MA_IID_IAudioCaptureClient = {0xC8ADBD64, 0xE71E, 0x48A0, {0xA4, 0xDE, 0x18, 0x5C, 0x39, 0x5C, 0xD3, 0x17}}; /* C8ADBD64-E71E-48A0-A4DE-185C395CD317 = __uuidof(IAudioCaptureClient) */
7019 static const IID MA_IID_IMMNotificationClient = {0x7991EEC9, 0x7E89, 0x4D85, {0x83, 0x90, 0x6C, 0x70, 0x3C, 0xEC, 0x60, 0xC0}}; /* 7991EEC9-7E89-4D85-8390-6C703CEC60C0 = __uuidof(IMMNotificationClient) */
7020 #ifndef MA_WIN32_DESKTOP
7021 static const IID MA_IID_DEVINTERFACE_AUDIO_RENDER = {0xE6327CAD, 0xDCEC, 0x4949, {0xAE, 0x8A, 0x99, 0x1E, 0x97, 0x6A, 0x79, 0xD2}}; /* E6327CAD-DCEC-4949-AE8A-991E976A79D2 */
7022 static const IID MA_IID_DEVINTERFACE_AUDIO_CAPTURE = {0x2EEF81BE, 0x33FA, 0x4800, {0x96, 0x70, 0x1C, 0xD4, 0x74, 0x97, 0x2C, 0x3F}}; /* 2EEF81BE-33FA-4800-9670-1CD474972C3F */
7023 static const IID MA_IID_IActivateAudioInterfaceCompletionHandler = {0x41D949AB, 0x9862, 0x444A, {0x80, 0xF6, 0xC2, 0x61, 0x33, 0x4D, 0xA5, 0xEB}}; /* 41D949AB-9862-444A-80F6-C261334DA5EB */
7024 #endif
7025 
7026 static const IID MA_CLSID_MMDeviceEnumerator_Instance = {0xBCDE0395, 0xE52F, 0x467C, {0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E}}; /* BCDE0395-E52F-467C-8E3D-C4579291692E = __uuidof(MMDeviceEnumerator) */
7027 static const IID MA_IID_IMMDeviceEnumerator_Instance = {0xA95664D2, 0x9614, 0x4F35, {0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6}}; /* A95664D2-9614-4F35-A746-DE8DB63617E6 = __uuidof(IMMDeviceEnumerator) */
7028 #ifdef __cplusplus
7029 #define MA_CLSID_MMDeviceEnumerator MA_CLSID_MMDeviceEnumerator_Instance
7030 #define MA_IID_IMMDeviceEnumerator MA_IID_IMMDeviceEnumerator_Instance
7031 #else
7032 #define MA_CLSID_MMDeviceEnumerator &MA_CLSID_MMDeviceEnumerator_Instance
7033 #define MA_IID_IMMDeviceEnumerator &MA_IID_IMMDeviceEnumerator_Instance
7034 #endif
7035 
7036 typedef struct ma_IUnknown ma_IUnknown;
7037 #ifdef MA_WIN32_DESKTOP
7038 #define MA_MM_DEVICE_STATE_ACTIVE 1
7039 #define MA_MM_DEVICE_STATE_DISABLED 2
7040 #define MA_MM_DEVICE_STATE_NOTPRESENT 4
7041 #define MA_MM_DEVICE_STATE_UNPLUGGED 8
7042 
7043 typedef struct ma_IMMDeviceEnumerator ma_IMMDeviceEnumerator;
7044 typedef struct ma_IMMDeviceCollection ma_IMMDeviceCollection;
7045 typedef struct ma_IMMDevice ma_IMMDevice;
7046 #else
7047 typedef struct ma_IActivateAudioInterfaceCompletionHandler ma_IActivateAudioInterfaceCompletionHandler;
7048 typedef struct ma_IActivateAudioInterfaceAsyncOperation ma_IActivateAudioInterfaceAsyncOperation;
7049 #endif
7050 typedef struct ma_IPropertyStore ma_IPropertyStore;
7051 typedef struct ma_IAudioClient ma_IAudioClient;
7052 typedef struct ma_IAudioClient2 ma_IAudioClient2;
7053 typedef struct ma_IAudioClient3 ma_IAudioClient3;
7054 typedef struct ma_IAudioRenderClient ma_IAudioRenderClient;
7055 typedef struct ma_IAudioCaptureClient ma_IAudioCaptureClient;
7056 
7057 typedef ma_int64 MA_REFERENCE_TIME;
7058 
7059 #define MA_AUDCLNT_STREAMFLAGS_CROSSPROCESS 0x00010000
7060 #define MA_AUDCLNT_STREAMFLAGS_LOOPBACK 0x00020000
7061 #define MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK 0x00040000
7062 #define MA_AUDCLNT_STREAMFLAGS_NOPERSIST 0x00080000
7063 #define MA_AUDCLNT_STREAMFLAGS_RATEADJUST 0x00100000
7064 #define MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000
7065 #define MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
7066 #define MA_AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED 0x10000000
7067 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE 0x20000000
7068 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED 0x40000000
7069 
7070 /* Buffer flags. */
7071 #define MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY 1
7072 #define MA_AUDCLNT_BUFFERFLAGS_SILENT 2
7073 #define MA_AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR 4
7074 
7075 typedef enum
7076 {
7077  ma_eRender = 0,
7078  ma_eCapture = 1,
7079  ma_eAll = 2
7080 } ma_EDataFlow;
7081 
7082 typedef enum
7083 {
7084  ma_eConsole = 0,
7085  ma_eMultimedia = 1,
7086  ma_eCommunications = 2
7087 } ma_ERole;
7088 
7089 typedef enum
7090 {
7091  MA_AUDCLNT_SHAREMODE_SHARED,
7092  MA_AUDCLNT_SHAREMODE_EXCLUSIVE
7093 } MA_AUDCLNT_SHAREMODE;
7094 
7095 typedef enum
7096 {
7097  MA_AudioCategory_Other = 0 /* <-- miniaudio is only caring about Other. */
7098 } MA_AUDIO_STREAM_CATEGORY;
7099 
7100 typedef struct
7101 {
7102  ma_uint32 cbSize;
7103  BOOL bIsOffload;
7104  MA_AUDIO_STREAM_CATEGORY eCategory;
7105 } ma_AudioClientProperties;
7106 
7107 /* IUnknown */
7108 typedef struct
7109 {
7110  /* IUnknown */
7111  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IUnknown* pThis, const IID* const riid, void** ppObject);
7112  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IUnknown* pThis);
7113  ULONG (STDMETHODCALLTYPE * Release) (ma_IUnknown* pThis);
7114 } ma_IUnknownVtbl;
7115 struct ma_IUnknown
7116 {
7117  ma_IUnknownVtbl* lpVtbl;
7118 };
7119 static MA_INLINE HRESULT ma_IUnknown_QueryInterface(ma_IUnknown* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7120 static MA_INLINE ULONG ma_IUnknown_AddRef(ma_IUnknown* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7121 static MA_INLINE ULONG ma_IUnknown_Release(ma_IUnknown* pThis) { return pThis->lpVtbl->Release(pThis); }
7122 
7123 #ifdef MA_WIN32_DESKTOP
7124  /* IMMNotificationClient */
7125  typedef struct
7126  {
7127  /* IUnknown */
7128  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMNotificationClient* pThis, const IID* const riid, void** ppObject);
7129  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMNotificationClient* pThis);
7130  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMNotificationClient* pThis);
7131 
7132  /* IMMNotificationClient */
7133  HRESULT (STDMETHODCALLTYPE * OnDeviceStateChanged) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, DWORD dwNewState);
7134  HRESULT (STDMETHODCALLTYPE * OnDeviceAdded) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID);
7135  HRESULT (STDMETHODCALLTYPE * OnDeviceRemoved) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID);
7136  HRESULT (STDMETHODCALLTYPE * OnDefaultDeviceChanged)(ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID);
7137  HRESULT (STDMETHODCALLTYPE * OnPropertyValueChanged)(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, const PROPERTYKEY key);
7138  } ma_IMMNotificationClientVtbl;
7139 
7140  /* IMMDeviceEnumerator */
7141  typedef struct
7142  {
7143  /* IUnknown */
7144  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceEnumerator* pThis, const IID* const riid, void** ppObject);
7145  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceEnumerator* pThis);
7146  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceEnumerator* pThis);
7147 
7148  /* IMMDeviceEnumerator */
7149  HRESULT (STDMETHODCALLTYPE * EnumAudioEndpoints) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices);
7150  HRESULT (STDMETHODCALLTYPE * GetDefaultAudioEndpoint) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint);
7151  HRESULT (STDMETHODCALLTYPE * GetDevice) (ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice);
7152  HRESULT (STDMETHODCALLTYPE * RegisterEndpointNotificationCallback) (ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient);
7153  HRESULT (STDMETHODCALLTYPE * UnregisterEndpointNotificationCallback)(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient);
7154  } ma_IMMDeviceEnumeratorVtbl;
7155  struct ma_IMMDeviceEnumerator
7156  {
7157  ma_IMMDeviceEnumeratorVtbl* lpVtbl;
7158  };
7159  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_QueryInterface(ma_IMMDeviceEnumerator* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7160  static MA_INLINE ULONG ma_IMMDeviceEnumerator_AddRef(ma_IMMDeviceEnumerator* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7161  static MA_INLINE ULONG ma_IMMDeviceEnumerator_Release(ma_IMMDeviceEnumerator* pThis) { return pThis->lpVtbl->Release(pThis); }
7162  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_EnumAudioEndpoints(ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices) { return pThis->lpVtbl->EnumAudioEndpoints(pThis, dataFlow, dwStateMask, ppDevices); }
7163  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint) { return pThis->lpVtbl->GetDefaultAudioEndpoint(pThis, dataFlow, role, ppEndpoint); }
7164  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_GetDevice(ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice) { return pThis->lpVtbl->GetDevice(pThis, pID, ppDevice); }
7165  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_RegisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient) { return pThis->lpVtbl->RegisterEndpointNotificationCallback(pThis, pClient); }
7166  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient) { return pThis->lpVtbl->UnregisterEndpointNotificationCallback(pThis, pClient); }
7167 
7168 
7169  /* IMMDeviceCollection */
7170  typedef struct
7171  {
7172  /* IUnknown */
7173  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceCollection* pThis, const IID* const riid, void** ppObject);
7174  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceCollection* pThis);
7175  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceCollection* pThis);
7176 
7177  /* IMMDeviceCollection */
7178  HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IMMDeviceCollection* pThis, UINT* pDevices);
7179  HRESULT (STDMETHODCALLTYPE * Item) (ma_IMMDeviceCollection* pThis, UINT nDevice, ma_IMMDevice** ppDevice);
7180  } ma_IMMDeviceCollectionVtbl;
7181  struct ma_IMMDeviceCollection
7182  {
7183  ma_IMMDeviceCollectionVtbl* lpVtbl;
7184  };
7185  static MA_INLINE HRESULT ma_IMMDeviceCollection_QueryInterface(ma_IMMDeviceCollection* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7186  static MA_INLINE ULONG ma_IMMDeviceCollection_AddRef(ma_IMMDeviceCollection* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7187  static MA_INLINE ULONG ma_IMMDeviceCollection_Release(ma_IMMDeviceCollection* pThis) { return pThis->lpVtbl->Release(pThis); }
7188  static MA_INLINE HRESULT ma_IMMDeviceCollection_GetCount(ma_IMMDeviceCollection* pThis, UINT* pDevices) { return pThis->lpVtbl->GetCount(pThis, pDevices); }
7189  static MA_INLINE HRESULT ma_IMMDeviceCollection_Item(ma_IMMDeviceCollection* pThis, UINT nDevice, ma_IMMDevice** ppDevice) { return pThis->lpVtbl->Item(pThis, nDevice, ppDevice); }
7190 
7191 
7192  /* IMMDevice */
7193  typedef struct
7194  {
7195  /* IUnknown */
7196  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDevice* pThis, const IID* const riid, void** ppObject);
7197  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDevice* pThis);
7198  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDevice* pThis);
7199 
7200  /* IMMDevice */
7201  HRESULT (STDMETHODCALLTYPE * Activate) (ma_IMMDevice* pThis, const IID* const iid, DWORD dwClsCtx, PROPVARIANT* pActivationParams, void** ppInterface);
7202  HRESULT (STDMETHODCALLTYPE * OpenPropertyStore)(ma_IMMDevice* pThis, DWORD stgmAccess, ma_IPropertyStore** ppProperties);
7203  HRESULT (STDMETHODCALLTYPE * GetId) (ma_IMMDevice* pThis, LPWSTR *pID);
7204  HRESULT (STDMETHODCALLTYPE * GetState) (ma_IMMDevice* pThis, DWORD *pState);
7205  } ma_IMMDeviceVtbl;
7206  struct ma_IMMDevice
7207  {
7208  ma_IMMDeviceVtbl* lpVtbl;
7209  };
7210  static MA_INLINE HRESULT ma_IMMDevice_QueryInterface(ma_IMMDevice* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7211  static MA_INLINE ULONG ma_IMMDevice_AddRef(ma_IMMDevice* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7212  static MA_INLINE ULONG ma_IMMDevice_Release(ma_IMMDevice* pThis) { return pThis->lpVtbl->Release(pThis); }
7213  static MA_INLINE HRESULT ma_IMMDevice_Activate(ma_IMMDevice* pThis, const IID* const iid, DWORD dwClsCtx, PROPVARIANT* pActivationParams, void** ppInterface) { return pThis->lpVtbl->Activate(pThis, iid, dwClsCtx, pActivationParams, ppInterface); }
7214  static MA_INLINE HRESULT ma_IMMDevice_OpenPropertyStore(ma_IMMDevice* pThis, DWORD stgmAccess, ma_IPropertyStore** ppProperties) { return pThis->lpVtbl->OpenPropertyStore(pThis, stgmAccess, ppProperties); }
7215  static MA_INLINE HRESULT ma_IMMDevice_GetId(ma_IMMDevice* pThis, LPWSTR *pID) { return pThis->lpVtbl->GetId(pThis, pID); }
7216  static MA_INLINE HRESULT ma_IMMDevice_GetState(ma_IMMDevice* pThis, DWORD *pState) { return pThis->lpVtbl->GetState(pThis, pState); }
7217 #else
7218  /* IActivateAudioInterfaceAsyncOperation */
7219  typedef struct
7220  {
7221  /* IUnknown */
7222  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IActivateAudioInterfaceAsyncOperation* pThis, const IID* const riid, void** ppObject);
7223  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
7224  ULONG (STDMETHODCALLTYPE * Release) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
7225 
7226  /* IActivateAudioInterfaceAsyncOperation */
7227  HRESULT (STDMETHODCALLTYPE * GetActivateResult)(ma_IActivateAudioInterfaceAsyncOperation* pThis, HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface);
7228  } ma_IActivateAudioInterfaceAsyncOperationVtbl;
7229  struct ma_IActivateAudioInterfaceAsyncOperation
7230  {
7231  ma_IActivateAudioInterfaceAsyncOperationVtbl* lpVtbl;
7232  };
7233  static MA_INLINE HRESULT ma_IActivateAudioInterfaceAsyncOperation_QueryInterface(ma_IActivateAudioInterfaceAsyncOperation* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7234  static MA_INLINE ULONG ma_IActivateAudioInterfaceAsyncOperation_AddRef(ma_IActivateAudioInterfaceAsyncOperation* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7235  static MA_INLINE ULONG ma_IActivateAudioInterfaceAsyncOperation_Release(ma_IActivateAudioInterfaceAsyncOperation* pThis) { return pThis->lpVtbl->Release(pThis); }
7236  static MA_INLINE HRESULT ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(ma_IActivateAudioInterfaceAsyncOperation* pThis, HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface) { return pThis->lpVtbl->GetActivateResult(pThis, pActivateResult, ppActivatedInterface); }
7237 #endif
7238 
7239 /* IPropertyStore */
7240 typedef struct
7241 {
7242  /* IUnknown */
7243  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IPropertyStore* pThis, const IID* const riid, void** ppObject);
7244  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IPropertyStore* pThis);
7245  ULONG (STDMETHODCALLTYPE * Release) (ma_IPropertyStore* pThis);
7246 
7247  /* IPropertyStore */
7248  HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IPropertyStore* pThis, DWORD* pPropCount);
7249  HRESULT (STDMETHODCALLTYPE * GetAt) (ma_IPropertyStore* pThis, DWORD propIndex, PROPERTYKEY* pPropKey);
7250  HRESULT (STDMETHODCALLTYPE * GetValue)(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, PROPVARIANT* pPropVar);
7251  HRESULT (STDMETHODCALLTYPE * SetValue)(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, const PROPVARIANT* const pPropVar);
7252  HRESULT (STDMETHODCALLTYPE * Commit) (ma_IPropertyStore* pThis);
7253 } ma_IPropertyStoreVtbl;
7254 struct ma_IPropertyStore
7255 {
7256  ma_IPropertyStoreVtbl* lpVtbl;
7257 };
7258 static MA_INLINE HRESULT ma_IPropertyStore_QueryInterface(ma_IPropertyStore* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7259 static MA_INLINE ULONG ma_IPropertyStore_AddRef(ma_IPropertyStore* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7260 static MA_INLINE ULONG ma_IPropertyStore_Release(ma_IPropertyStore* pThis) { return pThis->lpVtbl->Release(pThis); }
7261 static MA_INLINE HRESULT ma_IPropertyStore_GetCount(ma_IPropertyStore* pThis, DWORD* pPropCount) { return pThis->lpVtbl->GetCount(pThis, pPropCount); }
7262 static MA_INLINE HRESULT ma_IPropertyStore_GetAt(ma_IPropertyStore* pThis, DWORD propIndex, PROPERTYKEY* pPropKey) { return pThis->lpVtbl->GetAt(pThis, propIndex, pPropKey); }
7263 static MA_INLINE HRESULT ma_IPropertyStore_GetValue(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, PROPVARIANT* pPropVar) { return pThis->lpVtbl->GetValue(pThis, pKey, pPropVar); }
7264 static MA_INLINE HRESULT ma_IPropertyStore_SetValue(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, const PROPVARIANT* const pPropVar) { return pThis->lpVtbl->SetValue(pThis, pKey, pPropVar); }
7265 static MA_INLINE HRESULT ma_IPropertyStore_Commit(ma_IPropertyStore* pThis) { return pThis->lpVtbl->Commit(pThis); }
7266 
7267 
7268 /* IAudioClient */
7269 typedef struct
7270 {
7271  /* IUnknown */
7272  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient* pThis, const IID* const riid, void** ppObject);
7273  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient* pThis);
7274  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient* pThis);
7275 
7276  /* IAudioClient */
7277  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid);
7278  HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient* pThis, ma_uint32* pNumBufferFrames);
7279  HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency);
7280  HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient* pThis, ma_uint32* pNumPaddingFrames);
7281  HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
7282  HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat);
7283  HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
7284  HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient* pThis);
7285  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient* pThis);
7286  HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient* pThis);
7287  HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient* pThis, HANDLE eventHandle);
7288  HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient* pThis, const IID* const riid, void** pp);
7289 } ma_IAudioClientVtbl;
7290 struct ma_IAudioClient
7291 {
7292  ma_IAudioClientVtbl* lpVtbl;
7293 };
7294 static MA_INLINE HRESULT ma_IAudioClient_QueryInterface(ma_IAudioClient* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7295 static MA_INLINE ULONG ma_IAudioClient_AddRef(ma_IAudioClient* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7296 static MA_INLINE ULONG ma_IAudioClient_Release(ma_IAudioClient* pThis) { return pThis->lpVtbl->Release(pThis); }
7297 static MA_INLINE HRESULT ma_IAudioClient_Initialize(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid) { return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
7298 static MA_INLINE HRESULT ma_IAudioClient_GetBufferSize(ma_IAudioClient* pThis, ma_uint32* pNumBufferFrames) { return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
7299 static MA_INLINE HRESULT ma_IAudioClient_GetStreamLatency(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency) { return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
7300 static MA_INLINE HRESULT ma_IAudioClient_GetCurrentPadding(ma_IAudioClient* pThis, ma_uint32* pNumPaddingFrames) { return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
7301 static MA_INLINE HRESULT ma_IAudioClient_IsFormatSupported(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) { return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
7302 static MA_INLINE HRESULT ma_IAudioClient_GetMixFormat(ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat) { return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
7303 static MA_INLINE HRESULT ma_IAudioClient_GetDevicePeriod(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) { return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
7304 static MA_INLINE HRESULT ma_IAudioClient_Start(ma_IAudioClient* pThis) { return pThis->lpVtbl->Start(pThis); }
7305 static MA_INLINE HRESULT ma_IAudioClient_Stop(ma_IAudioClient* pThis) { return pThis->lpVtbl->Stop(pThis); }
7306 static MA_INLINE HRESULT ma_IAudioClient_Reset(ma_IAudioClient* pThis) { return pThis->lpVtbl->Reset(pThis); }
7307 static MA_INLINE HRESULT ma_IAudioClient_SetEventHandle(ma_IAudioClient* pThis, HANDLE eventHandle) { return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
7308 static MA_INLINE HRESULT ma_IAudioClient_GetService(ma_IAudioClient* pThis, const IID* const riid, void** pp) { return pThis->lpVtbl->GetService(pThis, riid, pp); }
7309 
7310 /* IAudioClient2 */
7311 typedef struct
7312 {
7313  /* IUnknown */
7314  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient2* pThis, const IID* const riid, void** ppObject);
7315  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient2* pThis);
7316  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient2* pThis);
7317 
7318  /* IAudioClient */
7319  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid);
7320  HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient2* pThis, ma_uint32* pNumBufferFrames);
7321  HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency);
7322  HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient2* pThis, ma_uint32* pNumPaddingFrames);
7323  HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
7324  HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat);
7325  HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
7326  HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient2* pThis);
7327  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient2* pThis);
7328  HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient2* pThis);
7329  HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient2* pThis, HANDLE eventHandle);
7330  HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient2* pThis, const IID* const riid, void** pp);
7331 
7332  /* IAudioClient2 */
7333  HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable);
7334  HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient2* pThis, const ma_AudioClientProperties* pProperties);
7335  HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient2* pThis, const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
7336 } ma_IAudioClient2Vtbl;
7337 struct ma_IAudioClient2
7338 {
7339  ma_IAudioClient2Vtbl* lpVtbl;
7340 };
7341 static MA_INLINE HRESULT ma_IAudioClient2_QueryInterface(ma_IAudioClient2* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7342 static MA_INLINE ULONG ma_IAudioClient2_AddRef(ma_IAudioClient2* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7343 static MA_INLINE ULONG ma_IAudioClient2_Release(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Release(pThis); }
7344 static MA_INLINE HRESULT ma_IAudioClient2_Initialize(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid) { return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
7345 static MA_INLINE HRESULT ma_IAudioClient2_GetBufferSize(ma_IAudioClient2* pThis, ma_uint32* pNumBufferFrames) { return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
7346 static MA_INLINE HRESULT ma_IAudioClient2_GetStreamLatency(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency) { return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
7347 static MA_INLINE HRESULT ma_IAudioClient2_GetCurrentPadding(ma_IAudioClient2* pThis, ma_uint32* pNumPaddingFrames) { return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
7348 static MA_INLINE HRESULT ma_IAudioClient2_IsFormatSupported(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) { return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
7349 static MA_INLINE HRESULT ma_IAudioClient2_GetMixFormat(ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat) { return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
7350 static MA_INLINE HRESULT ma_IAudioClient2_GetDevicePeriod(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) { return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
7351 static MA_INLINE HRESULT ma_IAudioClient2_Start(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Start(pThis); }
7352 static MA_INLINE HRESULT ma_IAudioClient2_Stop(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Stop(pThis); }
7353 static MA_INLINE HRESULT ma_IAudioClient2_Reset(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Reset(pThis); }
7354 static MA_INLINE HRESULT ma_IAudioClient2_SetEventHandle(ma_IAudioClient2* pThis, HANDLE eventHandle) { return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
7355 static MA_INLINE HRESULT ma_IAudioClient2_GetService(ma_IAudioClient2* pThis, const IID* const riid, void** pp) { return pThis->lpVtbl->GetService(pThis, riid, pp); }
7356 static MA_INLINE HRESULT ma_IAudioClient2_IsOffloadCapable(ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable) { return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
7357 static MA_INLINE HRESULT ma_IAudioClient2_SetClientProperties(ma_IAudioClient2* pThis, const ma_AudioClientProperties* pProperties) { return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
7358 static MA_INLINE HRESULT ma_IAudioClient2_GetBufferSizeLimits(ma_IAudioClient2* pThis, const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration) { return pThis->lpVtbl->GetBufferSizeLimits(pThis, pFormat, eventDriven, pMinBufferDuration, pMaxBufferDuration); }
7359 
7360 
7361 /* IAudioClient3 */
7362 typedef struct
7363 {
7364  /* IUnknown */
7365  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient3* pThis, const IID* const riid, void** ppObject);
7366  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient3* pThis);
7367  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient3* pThis);
7368 
7369  /* IAudioClient */
7370  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid);
7371  HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient3* pThis, ma_uint32* pNumBufferFrames);
7372  HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency);
7373  HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient3* pThis, ma_uint32* pNumPaddingFrames);
7374  HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
7375  HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat);
7376  HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
7377  HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient3* pThis);
7378  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient3* pThis);
7379  HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient3* pThis);
7380  HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient3* pThis, HANDLE eventHandle);
7381  HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient3* pThis, const IID* const riid, void** pp);
7382 
7383  /* IAudioClient2 */
7384  HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable);
7385  HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient3* pThis, const ma_AudioClientProperties* pProperties);
7386  HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient3* pThis, const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
7387 
7388  /* IAudioClient3 */
7389  HRESULT (STDMETHODCALLTYPE * GetSharedModeEnginePeriod) (ma_IAudioClient3* pThis, const WAVEFORMATEX* pFormat, ma_uint32* pDefaultPeriodInFrames, ma_uint32* pFundamentalPeriodInFrames, ma_uint32* pMinPeriodInFrames, ma_uint32* pMaxPeriodInFrames);
7390  HRESULT (STDMETHODCALLTYPE * GetCurrentSharedModeEnginePeriod)(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, ma_uint32* pCurrentPeriodInFrames);
7391  HRESULT (STDMETHODCALLTYPE * InitializeSharedAudioStream) (ma_IAudioClient3* pThis, DWORD streamFlags, ma_uint32 periodInFrames, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid);
7392 } ma_IAudioClient3Vtbl;
7393 struct ma_IAudioClient3
7394 {
7395  ma_IAudioClient3Vtbl* lpVtbl;
7396 };
7397 static MA_INLINE HRESULT ma_IAudioClient3_QueryInterface(ma_IAudioClient3* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7398 static MA_INLINE ULONG ma_IAudioClient3_AddRef(ma_IAudioClient3* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7399 static MA_INLINE ULONG ma_IAudioClient3_Release(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Release(pThis); }
7400 static MA_INLINE HRESULT ma_IAudioClient3_Initialize(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid) { return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
7401 static MA_INLINE HRESULT ma_IAudioClient3_GetBufferSize(ma_IAudioClient3* pThis, ma_uint32* pNumBufferFrames) { return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
7402 static MA_INLINE HRESULT ma_IAudioClient3_GetStreamLatency(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency) { return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
7403 static MA_INLINE HRESULT ma_IAudioClient3_GetCurrentPadding(ma_IAudioClient3* pThis, ma_uint32* pNumPaddingFrames) { return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
7404 static MA_INLINE HRESULT ma_IAudioClient3_IsFormatSupported(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) { return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
7405 static MA_INLINE HRESULT ma_IAudioClient3_GetMixFormat(ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat) { return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
7406 static MA_INLINE HRESULT ma_IAudioClient3_GetDevicePeriod(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) { return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
7407 static MA_INLINE HRESULT ma_IAudioClient3_Start(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Start(pThis); }
7408 static MA_INLINE HRESULT ma_IAudioClient3_Stop(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Stop(pThis); }
7409 static MA_INLINE HRESULT ma_IAudioClient3_Reset(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Reset(pThis); }
7410 static MA_INLINE HRESULT ma_IAudioClient3_SetEventHandle(ma_IAudioClient3* pThis, HANDLE eventHandle) { return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
7411 static MA_INLINE HRESULT ma_IAudioClient3_GetService(ma_IAudioClient3* pThis, const IID* const riid, void** pp) { return pThis->lpVtbl->GetService(pThis, riid, pp); }
7412 static MA_INLINE HRESULT ma_IAudioClient3_IsOffloadCapable(ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable) { return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
7413 static MA_INLINE HRESULT ma_IAudioClient3_SetClientProperties(ma_IAudioClient3* pThis, const ma_AudioClientProperties* pProperties) { return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
7414 static MA_INLINE HRESULT ma_IAudioClient3_GetBufferSizeLimits(ma_IAudioClient3* pThis, const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration) { return pThis->lpVtbl->GetBufferSizeLimits(pThis, pFormat, eventDriven, pMinBufferDuration, pMaxBufferDuration); }
7415 static MA_INLINE HRESULT ma_IAudioClient3_GetSharedModeEnginePeriod(ma_IAudioClient3* pThis, const WAVEFORMATEX* pFormat, ma_uint32* pDefaultPeriodInFrames, ma_uint32* pFundamentalPeriodInFrames, ma_uint32* pMinPeriodInFrames, ma_uint32* pMaxPeriodInFrames) { return pThis->lpVtbl->GetSharedModeEnginePeriod(pThis, pFormat, pDefaultPeriodInFrames, pFundamentalPeriodInFrames, pMinPeriodInFrames, pMaxPeriodInFrames); }
7416 static MA_INLINE HRESULT ma_IAudioClient3_GetCurrentSharedModeEnginePeriod(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, ma_uint32* pCurrentPeriodInFrames) { return pThis->lpVtbl->GetCurrentSharedModeEnginePeriod(pThis, ppFormat, pCurrentPeriodInFrames); }
7417 static MA_INLINE HRESULT ma_IAudioClient3_InitializeSharedAudioStream(ma_IAudioClient3* pThis, DWORD streamFlags, ma_uint32 periodInFrames, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGUID) { return pThis->lpVtbl->InitializeSharedAudioStream(pThis, streamFlags, periodInFrames, pFormat, pAudioSessionGUID); }
7418 
7419 
7420 /* IAudioRenderClient */
7421 typedef struct
7422 {
7423  /* IUnknown */
7424  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioRenderClient* pThis, const IID* const riid, void** ppObject);
7425  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioRenderClient* pThis);
7426  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioRenderClient* pThis);
7427 
7428  /* IAudioRenderClient */
7429  HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioRenderClient* pThis, ma_uint32 numFramesRequested, BYTE** ppData);
7430  HRESULT (STDMETHODCALLTYPE * ReleaseBuffer)(ma_IAudioRenderClient* pThis, ma_uint32 numFramesWritten, DWORD dwFlags);
7431 } ma_IAudioRenderClientVtbl;
7432 struct ma_IAudioRenderClient
7433 {
7434  ma_IAudioRenderClientVtbl* lpVtbl;
7435 };
7436 static MA_INLINE HRESULT ma_IAudioRenderClient_QueryInterface(ma_IAudioRenderClient* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7437 static MA_INLINE ULONG ma_IAudioRenderClient_AddRef(ma_IAudioRenderClient* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7438 static MA_INLINE ULONG ma_IAudioRenderClient_Release(ma_IAudioRenderClient* pThis) { return pThis->lpVtbl->Release(pThis); }
7439 static MA_INLINE HRESULT ma_IAudioRenderClient_GetBuffer(ma_IAudioRenderClient* pThis, ma_uint32 numFramesRequested, BYTE** ppData) { return pThis->lpVtbl->GetBuffer(pThis, numFramesRequested, ppData); }
7440 static MA_INLINE HRESULT ma_IAudioRenderClient_ReleaseBuffer(ma_IAudioRenderClient* pThis, ma_uint32 numFramesWritten, DWORD dwFlags) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesWritten, dwFlags); }
7441 
7442 
7443 /* IAudioCaptureClient */
7444 typedef struct
7445 {
7446  /* IUnknown */
7447  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioCaptureClient* pThis, const IID* const riid, void** ppObject);
7448  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioCaptureClient* pThis);
7449  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioCaptureClient* pThis);
7450 
7451  /* IAudioRenderClient */
7452  HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioCaptureClient* pThis, BYTE** ppData, ma_uint32* pNumFramesToRead, DWORD* pFlags, ma_uint64* pDevicePosition, ma_uint64* pQPCPosition);
7453  HRESULT (STDMETHODCALLTYPE * ReleaseBuffer) (ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead);
7454  HRESULT (STDMETHODCALLTYPE * GetNextPacketSize)(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket);
7455 } ma_IAudioCaptureClientVtbl;
7456 struct ma_IAudioCaptureClient
7457 {
7458  ma_IAudioCaptureClientVtbl* lpVtbl;
7459 };
7460 static MA_INLINE HRESULT ma_IAudioCaptureClient_QueryInterface(ma_IAudioCaptureClient* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7461 static MA_INLINE ULONG ma_IAudioCaptureClient_AddRef(ma_IAudioCaptureClient* pThis) { return pThis->lpVtbl->AddRef(pThis); }
7462 static MA_INLINE ULONG ma_IAudioCaptureClient_Release(ma_IAudioCaptureClient* pThis) { return pThis->lpVtbl->Release(pThis); }
7463 static MA_INLINE HRESULT ma_IAudioCaptureClient_GetBuffer(ma_IAudioCaptureClient* pThis, BYTE** ppData, ma_uint32* pNumFramesToRead, DWORD* pFlags, ma_uint64* pDevicePosition, ma_uint64* pQPCPosition) { return pThis->lpVtbl->GetBuffer(pThis, ppData, pNumFramesToRead, pFlags, pDevicePosition, pQPCPosition); }
7464 static MA_INLINE HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); }
7465 static MA_INLINE HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket) { return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); }
7466 
7467 #ifndef MA_WIN32_DESKTOP
7468 #include <mmdeviceapi.h>
7469 typedef struct ma_completion_handler_uwp ma_completion_handler_uwp;
7470 
7471 typedef struct
7472 {
7473  /* IUnknown */
7474  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_completion_handler_uwp* pThis, const IID* const riid, void** ppObject);
7475  ULONG (STDMETHODCALLTYPE * AddRef) (ma_completion_handler_uwp* pThis);
7476  ULONG (STDMETHODCALLTYPE * Release) (ma_completion_handler_uwp* pThis);
7477 
7478  /* IActivateAudioInterfaceCompletionHandler */
7479  HRESULT (STDMETHODCALLTYPE * ActivateCompleted)(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation);
7480 } ma_completion_handler_uwp_vtbl;
7481 struct ma_completion_handler_uwp
7482 {
7483  ma_completion_handler_uwp_vtbl* lpVtbl;
7484  MA_ATOMIC ma_uint32 counter;
7485  HANDLE hEvent;
7486 };
7487 
7488 static HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_QueryInterface(ma_completion_handler_uwp* pThis, const IID* const riid, void** ppObject)
7489 {
7490  /*
7491  We need to "implement" IAgileObject which is just an indicator that's used internally by WASAPI for some multithreading management. To
7492  "implement" this, we just make sure we return pThis when the IAgileObject is requested.
7493  */
7494  if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IActivateAudioInterfaceCompletionHandler) && !ma_is_guid_equal(riid, &MA_IID_IAgileObject)) {
7495  *ppObject = NULL;
7496  return E_NOINTERFACE;
7497  }
7498 
7499  /* Getting here means the IID is IUnknown or IMMNotificationClient. */
7500  *ppObject = (void*)pThis;
7501  ((ma_completion_handler_uwp_vtbl*)pThis->lpVtbl)->AddRef(pThis);
7502  return S_OK;
7503 }
7504 
7505 static ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_AddRef(ma_completion_handler_uwp* pThis)
7506 {
7507  return (ULONG)c89atomic_fetch_add_32(&pThis->counter, 1) + 1;
7508 }
7509 
7510 static ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_Release(ma_completion_handler_uwp* pThis)
7511 {
7512  ma_uint32 newRefCount = c89atomic_fetch_sub_32(&pThis->counter, 1) - 1;
7513  if (newRefCount == 0) {
7514  return 0; /* We don't free anything here because we never allocate the object on the heap. */
7515  }
7516 
7517  return (ULONG)newRefCount;
7518 }
7519 
7520 static HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_ActivateCompleted(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation)
7521 {
7522  (void)pActivateOperation;
7523  SetEvent(pThis->hEvent);
7524  return S_OK;
7525 }
7526 
7527 
7528 static ma_completion_handler_uwp_vtbl g_maCompletionHandlerVtblInstance = {
7529  ma_completion_handler_uwp_QueryInterface,
7530  ma_completion_handler_uwp_AddRef,
7531  ma_completion_handler_uwp_Release,
7532  ma_completion_handler_uwp_ActivateCompleted
7533 };
7534 
7535 static ma_result ma_completion_handler_uwp_init(ma_completion_handler_uwp* pHandler)
7536 {
7537  MA_ASSERT(pHandler != NULL);
7538  MA_ZERO_OBJECT(pHandler);
7539 
7540  pHandler->lpVtbl = &g_maCompletionHandlerVtblInstance;
7541  pHandler->counter = 1;
7542  pHandler->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
7543  if (pHandler->hEvent == NULL) {
7544  return ma_result_from_GetLastError(GetLastError());
7545  }
7546 
7547  return MA_SUCCESS;
7548 }
7549 
7550 static void ma_completion_handler_uwp_uninit(ma_completion_handler_uwp* pHandler)
7551 {
7552  if (pHandler->hEvent != NULL) {
7553  CloseHandle(pHandler->hEvent);
7554  }
7555 }
7556 
7557 static void ma_completion_handler_uwp_wait(ma_completion_handler_uwp* pHandler)
7558 {
7559  WaitForSingleObject(pHandler->hEvent, INFINITE);
7560 }
7561 #endif /* !MA_WIN32_DESKTOP */
7562 
7563 /* We need a virtual table for our notification client object that's used for detecting changes to the default device. */
7564 #ifdef MA_WIN32_DESKTOP
7565 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_QueryInterface(ma_IMMNotificationClient* pThis, const IID* const riid, void** ppObject)
7566 {
7567  /*
7568  We care about two interfaces - IUnknown and IMMNotificationClient. If the requested IID is something else
7569  we just return E_NOINTERFACE. Otherwise we need to increment the reference counter and return S_OK.
7570  */
7571  if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IMMNotificationClient)) {
7572  *ppObject = NULL;
7573  return E_NOINTERFACE;
7574  }
7575 
7576  /* Getting here means the IID is IUnknown or IMMNotificationClient. */
7577  *ppObject = (void*)pThis;
7578  ((ma_IMMNotificationClientVtbl*)pThis->lpVtbl)->AddRef(pThis);
7579  return S_OK;
7580 }
7581 
7582 static ULONG STDMETHODCALLTYPE ma_IMMNotificationClient_AddRef(ma_IMMNotificationClient* pThis)
7583 {
7584  return (ULONG)c89atomic_fetch_add_32(&pThis->counter, 1) + 1;
7585 }
7586 
7587 static ULONG STDMETHODCALLTYPE ma_IMMNotificationClient_Release(ma_IMMNotificationClient* pThis)
7588 {
7589  ma_uint32 newRefCount = c89atomic_fetch_sub_32(&pThis->counter, 1) - 1;
7590  if (newRefCount == 0) {
7591  return 0; /* We don't free anything here because we never allocate the object on the heap. */
7592  }
7593 
7594  return (ULONG)newRefCount;
7595 }
7596 
7597 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceStateChanged(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, DWORD dwNewState)
7598 {
7599  ma_bool32 isThisDevice = MA_FALSE;
7600  ma_bool32 isCapture = MA_FALSE;
7601  ma_bool32 isPlayback = MA_FALSE;
7602 
7603 #ifdef MA_DEBUG_OUTPUT
7604  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDeviceStateChanged(pDeviceID=%S, dwNewState=%u)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)", (unsigned int)dwNewState);*/
7605 #endif
7606 
7607  /*
7608  There have been reports of a hang when a playback device is disconnected. The idea with this code is to explicitly stop the device if we detect
7609  that the device is disabled or has been unplugged.
7610  */
7611  if (pThis->pDevice->wasapi.allowCaptureAutoStreamRouting && (pThis->pDevice->type == ma_device_type_capture || pThis->pDevice->type == ma_device_type_duplex || pThis->pDevice->type == ma_device_type_loopback)) {
7612  isCapture = MA_TRUE;
7613  if (wcscmp(pThis->pDevice->capture.id.wasapi, pDeviceID) == 0) {
7614  isThisDevice = MA_TRUE;
7615  }
7616  }
7617 
7618  if (pThis->pDevice->wasapi.allowPlaybackAutoStreamRouting && (pThis->pDevice->type == ma_device_type_playback || pThis->pDevice->type == ma_device_type_duplex)) {
7619  isPlayback = MA_TRUE;
7620  if (wcscmp(pThis->pDevice->playback.id.wasapi, pDeviceID) == 0) {
7621  isThisDevice = MA_TRUE;
7622  }
7623  }
7624 
7625 
7626  /*
7627  If the device ID matches our device we need to mark our device as detached and stop it. When a
7628  device is added in OnDeviceAdded(), we'll restart it. We only mark it as detached if the device
7629  was started at the time of being removed.
7630  */
7631  if (isThisDevice) {
7632  if ((dwNewState & MA_MM_DEVICE_STATE_ACTIVE) == 0) {
7633  /*
7634  Unplugged or otherwise unavailable. Mark as detached if we were in a playing state. We'll
7635  use this to determine whether or not we need to automatically start the device when it's
7636  plugged back in again.
7637  */
7638  if (ma_device_get_state(pThis->pDevice) == MA_STATE_STARTED) {
7639  if (isPlayback) {
7640  pThis->pDevice->wasapi.isDetachedPlayback = MA_TRUE;
7641  }
7642  if (isCapture) {
7643  pThis->pDevice->wasapi.isDetachedCapture = MA_TRUE;
7644  }
7645 
7646  ma_device_stop(pThis->pDevice);
7647  }
7648  }
7649 
7650  if ((dwNewState & MA_MM_DEVICE_STATE_ACTIVE) != 0) {
7651  /* The device was activated. If we were detached, we need to start it again. */
7652  ma_bool8 tryRestartingDevice = MA_FALSE;
7653 
7654  if (isPlayback) {
7655  if (pThis->pDevice->wasapi.isDetachedPlayback) {
7656  pThis->pDevice->wasapi.isDetachedPlayback = MA_FALSE;
7657  ma_device_reroute__wasapi(pThis->pDevice, ma_device_type_playback);
7658  tryRestartingDevice = MA_TRUE;
7659  }
7660  }
7661 
7662  if (isCapture) {
7663  if (pThis->pDevice->wasapi.isDetachedCapture) {
7664  pThis->pDevice->wasapi.isDetachedCapture = MA_FALSE;
7665  ma_device_reroute__wasapi(pThis->pDevice, (pThis->pDevice->type == ma_device_type_loopback) ? ma_device_type_loopback : ma_device_type_capture);
7666  tryRestartingDevice = MA_TRUE;
7667  }
7668  }
7669 
7670  if (tryRestartingDevice) {
7671  if (pThis->pDevice->wasapi.isDetachedPlayback == MA_FALSE && pThis->pDevice->wasapi.isDetachedCapture == MA_FALSE) {
7672  ma_device_start(pThis->pDevice);
7673  }
7674  }
7675  }
7676  }
7677 
7678  return S_OK;
7679 }
7680 
7681 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceAdded(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID)
7682 {
7683 #ifdef MA_DEBUG_OUTPUT
7684  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDeviceAdded(pDeviceID=%S)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)");*/
7685 #endif
7686 
7687  /* We don't need to worry about this event for our purposes. */
7688  (void)pThis;
7689  (void)pDeviceID;
7690  return S_OK;
7691 }
7692 
7693 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceRemoved(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID)
7694 {
7695 #ifdef MA_DEBUG_OUTPUT
7696  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDeviceRemoved(pDeviceID=%S)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)");*/
7697 #endif
7698 
7699  /* We don't need to worry about this event for our purposes. */
7700  (void)pThis;
7701  (void)pDeviceID;
7702  return S_OK;
7703 }
7704 
7705 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged(ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID)
7706 {
7707 #ifdef MA_DEBUG_OUTPUT
7708  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDefaultDeviceChanged(dataFlow=%d, role=%d, pDefaultDeviceID=%S)\n", dataFlow, role, (pDefaultDeviceID != NULL) ? pDefaultDeviceID : L"(NULL)");*/
7709 #endif
7710 
7711  /* We only ever use the eConsole role in miniaudio. */
7712  if (role != ma_eConsole) {
7713  ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting: role != eConsole\n");
7714  return S_OK;
7715  }
7716 
7717  /* We only care about devices with the same data flow and role as the current device. */
7718  if ((pThis->pDevice->type == ma_device_type_playback && dataFlow != ma_eRender) ||
7719  (pThis->pDevice->type == ma_device_type_capture && dataFlow != ma_eCapture)) {
7720  ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting abandoned because dataFlow does match device type.\n");
7721  return S_OK;
7722  }
7723 
7724  /* Don't do automatic stream routing if we're not allowed. */
7725  if ((dataFlow == ma_eRender && pThis->pDevice->wasapi.allowPlaybackAutoStreamRouting == MA_FALSE) ||
7726  (dataFlow == ma_eCapture && pThis->pDevice->wasapi.allowCaptureAutoStreamRouting == MA_FALSE)) {
7727  ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting abandoned because automatic stream routing has been disabled by the device config.\n");
7728  return S_OK;
7729  }
7730 
7731  /*
7732  Not currently supporting automatic stream routing in exclusive mode. This is not working correctly on my machine due to
7733  AUDCLNT_E_DEVICE_IN_USE errors when reinitializing the device. If this is a bug in miniaudio, we can try re-enabling this once
7734  it's fixed.
7735  */
7736  if ((dataFlow == ma_eRender && pThis->pDevice->playback.shareMode == ma_share_mode_exclusive) ||
7737  (dataFlow == ma_eCapture && pThis->pDevice->capture.shareMode == ma_share_mode_exclusive)) {
7738  ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting abandoned because the device shared mode is exclusive.\n");
7739  return S_OK;
7740  }
7741 
7742 
7743 
7744 
7745  /*
7746  Second attempt at device rerouting. We're going to retrieve the device's state at the time of
7747  the route change. We're then going to stop the device, reinitialize the device, and then start
7748  it again if the state before stopping was MA_STATE_STARTED.
7749  */
7750  {
7751  ma_uint32 previousState = ma_device_get_state(pThis->pDevice);
7752  ma_bool8 restartDevice = MA_FALSE;
7753 
7754  if (previousState == MA_STATE_STARTED) {
7755  ma_device_stop(pThis->pDevice);
7756  restartDevice = MA_TRUE;
7757  }
7758 
7759  if (pDefaultDeviceID != NULL) { /* <-- The input device ID will be null if there's no other device available. */
7760  if (dataFlow == ma_eRender) {
7761  ma_device_reroute__wasapi(pThis->pDevice, ma_device_type_playback);
7762 
7763  if (pThis->pDevice->wasapi.isDetachedPlayback) {
7764  pThis->pDevice->wasapi.isDetachedPlayback = MA_FALSE;
7765 
7766  if (pThis->pDevice->type == ma_device_type_duplex && pThis->pDevice->wasapi.isDetachedCapture) {
7767  restartDevice = MA_FALSE; /* It's a duplex device and the capture side is detached. We cannot be restarting the device just yet. */
7768  } else {
7769  restartDevice = MA_TRUE; /* It's not a duplex device, or the capture side is also attached so we can go ahead and restart the device. */
7770  }
7771  }
7772  } else {
7773  ma_device_reroute__wasapi(pThis->pDevice, (pThis->pDevice->type == ma_device_type_loopback) ? ma_device_type_loopback : ma_device_type_capture);
7774 
7775  if (pThis->pDevice->wasapi.isDetachedCapture) {
7776  pThis->pDevice->wasapi.isDetachedCapture = MA_FALSE;
7777 
7778  if (pThis->pDevice->type == ma_device_type_duplex && pThis->pDevice->wasapi.isDetachedPlayback) {
7779  restartDevice = MA_FALSE; /* It's a duplex device and the playback side is detached. We cannot be restarting the device just yet. */
7780  } else {
7781  restartDevice = MA_TRUE; /* It's not a duplex device, or the playback side is also attached so we can go ahead and restart the device. */
7782  }
7783  }
7784  }
7785 
7786  if (restartDevice) {
7787  ma_device_start(pThis->pDevice);
7788  }
7789  }
7790  }
7791 
7792  return S_OK;
7793 }
7794 
7795 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnPropertyValueChanged(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, const PROPERTYKEY key)
7796 {
7797 #ifdef MA_DEBUG_OUTPUT
7798  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnPropertyValueChanged(pDeviceID=%S)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)");*/
7799 #endif
7800 
7801  (void)pThis;
7802  (void)pDeviceID;
7803  (void)key;
7804  return S_OK;
7805 }
7806 
7807 static ma_IMMNotificationClientVtbl g_maNotificationCientVtbl = {
7808  ma_IMMNotificationClient_QueryInterface,
7809  ma_IMMNotificationClient_AddRef,
7810  ma_IMMNotificationClient_Release,
7811  ma_IMMNotificationClient_OnDeviceStateChanged,
7812  ma_IMMNotificationClient_OnDeviceAdded,
7813  ma_IMMNotificationClient_OnDeviceRemoved,
7814  ma_IMMNotificationClient_OnDefaultDeviceChanged,
7815  ma_IMMNotificationClient_OnPropertyValueChanged
7816 };
7817 #endif /* MA_WIN32_DESKTOP */
7818 
7819 #ifdef MA_WIN32_DESKTOP
7820 typedef ma_IMMDevice ma_WASAPIDeviceInterface;
7821 #else
7822 typedef ma_IUnknown ma_WASAPIDeviceInterface;
7823 #endif
7824 
7825 
7826 #define MA_CONTEXT_COMMAND_QUIT__WASAPI 1
7827 #define MA_CONTEXT_COMMAND_CREATE_IAUDIOCLIENT__WASAPI 2
7828 #define MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI 3
7829 
7830 static ma_context_command__wasapi ma_context_init_command__wasapi(int code)
7831 {
7833 
7834  MA_ZERO_OBJECT(&cmd);
7835  cmd.code = code;
7836 
7837  return cmd;
7838 }
7839 
7840 static ma_result ma_context_post_command__wasapi(ma_context* pContext, const ma_context_command__wasapi* pCmd)
7841 {
7842  /* For now we are doing everything synchronously, but I might relax this later if the need arises. */
7843  ma_result result;
7844  ma_bool32 isUsingLocalEvent = MA_FALSE;
7845  ma_event localEvent;
7846 
7847  MA_ASSERT(pContext != NULL);
7848  MA_ASSERT(pCmd != NULL);
7849 
7850  if (pCmd->pEvent == NULL) {
7851  isUsingLocalEvent = MA_TRUE;
7852 
7853  result = ma_event_init(&localEvent);
7854  if (result != MA_SUCCESS) {
7855  return result; /* Failed to create the event for this command. */
7856  }
7857  }
7858 
7859  /* Here is where we add the command to the list. If there's not enough room we'll spin until there is. */
7860  ma_mutex_lock(&pContext->wasapi.commandLock);
7861  {
7862  ma_uint32 index;
7863 
7864  /* Spin until we've got some space available. */
7865  while (pContext->wasapi.commandCount == ma_countof(pContext->wasapi.commands)) {
7866  ma_yield();
7867  }
7868 
7869  /* Space is now available. Can safely add to the list. */
7870  index = (pContext->wasapi.commandIndex + pContext->wasapi.commandCount) % ma_countof(pContext->wasapi.commands);
7871  pContext->wasapi.commands[index] = *pCmd;
7872  pContext->wasapi.commands[index].pEvent = &localEvent;
7873  pContext->wasapi.commandCount += 1;
7874 
7875  /* Now that the command has been added, release the semaphore so ma_context_next_command__wasapi() can return. */
7876  ma_semaphore_release(&pContext->wasapi.commandSem);
7877  }
7878  ma_mutex_unlock(&pContext->wasapi.commandLock);
7879 
7880  if (isUsingLocalEvent) {
7881  ma_event_wait(&localEvent);
7882  ma_event_uninit(&localEvent);
7883  }
7884 
7885  return MA_SUCCESS;
7886 }
7887 
7888 static ma_result ma_context_next_command__wasapi(ma_context* pContext, ma_context_command__wasapi* pCmd)
7889 {
7890  ma_result result = MA_SUCCESS;
7891 
7892  MA_ASSERT(pContext != NULL);
7893  MA_ASSERT(pCmd != NULL);
7894 
7895  result = ma_semaphore_wait(&pContext->wasapi.commandSem);
7896  if (result == MA_SUCCESS) {
7897  ma_mutex_lock(&pContext->wasapi.commandLock);
7898  {
7899  *pCmd = pContext->wasapi.commands[pContext->wasapi.commandIndex];
7900  pContext->wasapi.commandIndex = (pContext->wasapi.commandIndex + 1) % ma_countof(pContext->wasapi.commands);
7901  pContext->wasapi.commandCount -= 1;
7902  }
7903  ma_mutex_unlock(&pContext->wasapi.commandLock);
7904  }
7905 
7906  return result;
7907 }
7908 
7909 static ma_thread_result MA_THREADCALL ma_context_command_thread__wasapi(void* pUserData)
7910 {
7911  ma_result result;
7912  ma_context* pContext = (ma_context*)pUserData;
7913  MA_ASSERT(pContext != NULL);
7914 
7915  for (;;) {
7917  result = ma_context_next_command__wasapi(pContext, &cmd);
7918  if (result != MA_SUCCESS) {
7919  break;
7920  }
7921 
7922  switch (cmd.code)
7923  {
7924  case MA_CONTEXT_COMMAND_QUIT__WASAPI:
7925  {
7926  /* Do nothing. Handled after the switch. */
7927  } break;
7928 
7929  case MA_CONTEXT_COMMAND_CREATE_IAUDIOCLIENT__WASAPI:
7930  {
7931  if (cmd.data.createAudioClient.deviceType == ma_device_type_playback) {
7932  *cmd.data.createAudioClient.pResult = ma_result_from_HRESULT(ma_IAudioClient_GetService((ma_IAudioClient*)cmd.data.createAudioClient.pAudioClient, &MA_IID_IAudioRenderClient, cmd.data.createAudioClient.ppAudioClientService));
7933  } else {
7934  *cmd.data.createAudioClient.pResult = ma_result_from_HRESULT(ma_IAudioClient_GetService((ma_IAudioClient*)cmd.data.createAudioClient.pAudioClient, &MA_IID_IAudioCaptureClient, cmd.data.createAudioClient.ppAudioClientService));
7935  }
7936  } break;
7937 
7938  case MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI:
7939  {
7940  if (cmd.data.releaseAudioClient.deviceType == ma_device_type_playback) {
7941  if (cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientPlayback != NULL) {
7942  ma_IAudioClient_Release((ma_IAudioClient*)cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientPlayback);
7943  cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientPlayback = NULL;
7944  }
7945  }
7946 
7947  if (cmd.data.releaseAudioClient.deviceType == ma_device_type_capture) {
7948  if (cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientCapture != NULL) {
7949  ma_IAudioClient_Release((ma_IAudioClient*)cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientCapture);
7950  cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientCapture = NULL;
7951  }
7952  }
7953  } break;
7954 
7955  default:
7956  {
7957  /* Unknown command. Ignore it, but trigger an assert in debug mode so we're aware of it. */
7959  } break;
7960  }
7961 
7962  if (cmd.pEvent != NULL) {
7963  ma_event_signal(cmd.pEvent);
7964  }
7965 
7966  if (cmd.code == MA_CONTEXT_COMMAND_QUIT__WASAPI) {
7967  break; /* Received a quit message. Get out of here. */
7968  }
7969  }
7970 
7971  return (ma_thread_result)0;
7972 }
7973 
7974 static ma_result ma_device_create_IAudioClient_service__wasapi(ma_context* pContext, ma_device_type deviceType, ma_IAudioClient* pAudioClient, void** ppAudioClientService)
7975 {
7976  ma_result result;
7977  ma_result cmdResult;
7978  ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_CREATE_IAUDIOCLIENT__WASAPI);
7979  cmd.data.createAudioClient.deviceType = deviceType;
7980  cmd.data.createAudioClient.pAudioClient = (void*)pAudioClient;
7981  cmd.data.createAudioClient.ppAudioClientService = ppAudioClientService;
7982  cmd.data.createAudioClient.pResult = &cmdResult; /* Declared locally, but won't be dereferenced after this function returns since execution of the command will wait here. */
7983 
7984  result = ma_context_post_command__wasapi(pContext, &cmd); /* This will not return until the command has actually been run. */
7985  if (result != MA_SUCCESS) {
7986  return result;
7987  }
7988 
7989  return *cmd.data.createAudioClient.pResult;
7990 }
7991 
7992 #if 0 /* Not used at the moment, but leaving here for future use. */
7993 static ma_result ma_device_release_IAudioClient_service__wasapi(ma_device* pDevice, ma_device_type deviceType)
7994 {
7995  ma_result result;
7996  ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI);
7997  cmd.data.releaseAudioClient.pDevice = pDevice;
7998  cmd.data.releaseAudioClient.deviceType = deviceType;
7999 
8000  result = ma_context_post_command__wasapi(pDevice->pContext, &cmd); /* This will not return until the command has actually been run. */
8001  if (result != MA_SUCCESS) {
8002  return result;
8003  }
8004 
8005  return MA_SUCCESS;
8006 }
8007 #endif
8008 
8009 
8010 static void ma_add_native_data_format_to_device_info_from_WAVEFORMATEX(const WAVEFORMATEX* pWF, ma_share_mode shareMode, ma_device_info* pInfo)
8011 {
8012  MA_ASSERT(pWF != NULL);
8013  MA_ASSERT(pInfo != NULL);
8014 
8015  if (pInfo->nativeDataFormatCount >= ma_countof(pInfo->nativeDataFormats)) {
8016  return; /* Too many data formats. Need to ignore this one. Don't think this should ever happen with WASAPI. */
8017  }
8018 
8019  pInfo->nativeDataFormats[pInfo->nativeDataFormatCount].format = ma_format_from_WAVEFORMATEX(pWF);
8020  pInfo->nativeDataFormats[pInfo->nativeDataFormatCount].channels = pWF->nChannels;
8021  pInfo->nativeDataFormats[pInfo->nativeDataFormatCount].sampleRate = pWF->nSamplesPerSec;
8023  pInfo->nativeDataFormatCount += 1;
8024 }
8025 
8026 static ma_result ma_context_get_device_info_from_IAudioClient__wasapi(ma_context* pContext, /*ma_IMMDevice**/void* pMMDevice, ma_IAudioClient* pAudioClient, ma_device_info* pInfo)
8027 {
8028  HRESULT hr;
8029  WAVEFORMATEX* pWF = NULL;
8030 
8031  MA_ASSERT(pAudioClient != NULL);
8032  MA_ASSERT(pInfo != NULL);
8033 
8034  /* Shared Mode. We use GetMixFormat() here. */
8035  hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pAudioClient, (WAVEFORMATEX**)&pWF);
8036  if (SUCCEEDED(hr)) {
8037  ma_add_native_data_format_to_device_info_from_WAVEFORMATEX(pWF, ma_share_mode_shared, pInfo);
8038  } else {
8039  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve mix format for device info retrieval.", ma_result_from_HRESULT(hr));
8040  }
8041 
8042  /*
8043  Exlcusive Mode. We repeatedly call IsFormatSupported() here. This is not currently supported on
8044  UWP. Failure to retrieve the exclusive mode format is not considered an error, so from here on
8045  out, MA_SUCCESS is guaranteed to be returned.
8046  */
8047  #ifdef MA_WIN32_DESKTOP
8048  {
8049  ma_IPropertyStore *pProperties;
8050 
8051  /*
8052  The first thing to do is get the format from PKEY_AudioEngine_DeviceFormat. This should give us a channel count we assume is
8053  correct which will simplify our searching.
8054  */
8055  hr = ma_IMMDevice_OpenPropertyStore((ma_IMMDevice*)pMMDevice, STGM_READ, &pProperties);
8056  if (SUCCEEDED(hr)) {
8057  PROPVARIANT var;
8058  ma_PropVariantInit(&var);
8059 
8060  hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_AudioEngine_DeviceFormat, &var);
8061  if (SUCCEEDED(hr)) {
8062  pWF = (WAVEFORMATEX*)var.blob.pBlobData;
8063 
8064  /*
8065  In my testing, the format returned by PKEY_AudioEngine_DeviceFormat is suitable for exclusive mode so we check this format
8066  first. If this fails, fall back to a search.
8067  */
8068  hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pWF, NULL);
8069  if (SUCCEEDED(hr)) {
8070  /* The format returned by PKEY_AudioEngine_DeviceFormat is supported. */
8071  ma_add_native_data_format_to_device_info_from_WAVEFORMATEX(pWF, ma_share_mode_exclusive, pInfo);
8072  } else {
8073  /*
8074  The format returned by PKEY_AudioEngine_DeviceFormat is not supported, so fall back to a search. We assume the channel
8075  count returned by MA_PKEY_AudioEngine_DeviceFormat is valid and correct. For simplicity we're only returning one format.
8076  */
8077  ma_uint32 channels = pInfo->minChannels;
8078  ma_channel defaultChannelMap[MA_MAX_CHANNELS];
8079  WAVEFORMATEXTENSIBLE wf;
8080  ma_bool32 found;
8081  ma_uint32 iFormat;
8082 
8083  /* Make sure we don't overflow the channel map. */
8084  if (channels > MA_MAX_CHANNELS) {
8085  channels = MA_MAX_CHANNELS;
8086  }
8087 
8088  ma_get_standard_channel_map(ma_standard_channel_map_microsoft, channels, defaultChannelMap);
8089 
8090  MA_ZERO_OBJECT(&wf);
8091  wf.Format.cbSize = sizeof(wf);
8092  wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
8093  wf.Format.nChannels = (WORD)channels;
8094  wf.dwChannelMask = ma_channel_map_to_channel_mask__win32(defaultChannelMap, channels);
8095 
8096  found = MA_FALSE;
8097  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); ++iFormat) {
8098  ma_format format = g_maFormatPriorities[iFormat];
8099  ma_uint32 iSampleRate;
8100 
8101  wf.Format.wBitsPerSample = (WORD)(ma_get_bytes_per_sample(format)*8);
8102  wf.Format.nBlockAlign = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
8103  wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
8104  wf.Samples.wValidBitsPerSample = /*(format == ma_format_s24_32) ? 24 :*/ wf.Format.wBitsPerSample;
8105  if (format == ma_format_f32) {
8106  wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
8107  } else {
8108  wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
8109  }
8110 
8111  for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iSampleRate) {
8112  wf.Format.nSamplesPerSec = g_maStandardSampleRatePriorities[iSampleRate];
8113 
8114  hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, (WAVEFORMATEX*)&wf, NULL);
8115  if (SUCCEEDED(hr)) {
8116  ma_add_native_data_format_to_device_info_from_WAVEFORMATEX((WAVEFORMATEX*)&wf, ma_share_mode_exclusive, pInfo);
8117  found = MA_TRUE;
8118  break;
8119  }
8120  }
8121 
8122  if (found) {
8123  break;
8124  }
8125  }
8126 
8127  ma_PropVariantClear(pContext, &var);
8128 
8129  if (!found) {
8130  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "[WASAPI] Failed to find suitable device format for device info retrieval.", MA_FORMAT_NOT_SUPPORTED);
8131  }
8132  }
8133  } else {
8134  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "[WASAPI] Failed to retrieve device format for device info retrieval.", ma_result_from_HRESULT(hr));
8135  }
8136 
8137  ma_IPropertyStore_Release(pProperties);
8138  } else {
8139  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "[WASAPI] Failed to open property store for device info retrieval.", ma_result_from_HRESULT(hr));
8140  }
8141  }
8142  #endif
8143 
8144  return MA_SUCCESS;
8145 }
8146 
8147 #ifdef MA_WIN32_DESKTOP
8148 static ma_EDataFlow ma_device_type_to_EDataFlow(ma_device_type deviceType)
8149 {
8150  if (deviceType == ma_device_type_playback) {
8151  return ma_eRender;
8152  } else if (deviceType == ma_device_type_capture) {
8153  return ma_eCapture;
8154  } else {
8156  return ma_eRender; /* Should never hit this. */
8157  }
8158 }
8159 
8160 static ma_result ma_context_create_IMMDeviceEnumerator__wasapi(ma_context* pContext, ma_IMMDeviceEnumerator** ppDeviceEnumerator)
8161 {
8162  HRESULT hr;
8163  ma_IMMDeviceEnumerator* pDeviceEnumerator;
8164 
8165  MA_ASSERT(pContext != NULL);
8166  MA_ASSERT(ppDeviceEnumerator != NULL);
8167 
8168  *ppDeviceEnumerator = NULL; /* Safety. */
8169 
8170  hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
8171  if (FAILED(hr)) {
8172  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
8173  }
8174 
8175  *ppDeviceEnumerator = pDeviceEnumerator;
8176 
8177  return MA_SUCCESS;
8178 }
8179 
8180 static LPWSTR ma_context_get_default_device_id_from_IMMDeviceEnumerator__wasapi(ma_context* pContext, ma_IMMDeviceEnumerator* pDeviceEnumerator, ma_device_type deviceType)
8181 {
8182  HRESULT hr;
8183  ma_IMMDevice* pMMDefaultDevice = NULL;
8184  LPWSTR pDefaultDeviceID = NULL;
8185  ma_EDataFlow dataFlow;
8186  ma_ERole role;
8187 
8188  MA_ASSERT(pContext != NULL);
8189  MA_ASSERT(pDeviceEnumerator != NULL);
8190 
8191  (void)pContext;
8192 
8193  /* Grab the EDataFlow type from the device type. */
8194  dataFlow = ma_device_type_to_EDataFlow(deviceType);
8195 
8196  /* The role is always eConsole, but we may make this configurable later. */
8197  role = ma_eConsole;
8198 
8199  hr = ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(pDeviceEnumerator, dataFlow, role, &pMMDefaultDevice);
8200  if (FAILED(hr)) {
8201  return NULL;
8202  }
8203 
8204  hr = ma_IMMDevice_GetId(pMMDefaultDevice, &pDefaultDeviceID);
8205 
8206  ma_IMMDevice_Release(pMMDefaultDevice);
8207  pMMDefaultDevice = NULL;
8208 
8209  if (FAILED(hr)) {
8210  return NULL;
8211  }
8212 
8213  return pDefaultDeviceID;
8214 }
8215 
8216 static LPWSTR ma_context_get_default_device_id__wasapi(ma_context* pContext, ma_device_type deviceType) /* Free the returned pointer with ma_CoTaskMemFree() */
8217 {
8218  ma_result result;
8219  ma_IMMDeviceEnumerator* pDeviceEnumerator;
8220  LPWSTR pDefaultDeviceID = NULL;
8221 
8222  MA_ASSERT(pContext != NULL);
8223 
8224  result = ma_context_create_IMMDeviceEnumerator__wasapi(pContext, &pDeviceEnumerator);
8225  if (result != MA_SUCCESS) {
8226  return NULL;
8227  }
8228 
8229  pDefaultDeviceID = ma_context_get_default_device_id_from_IMMDeviceEnumerator__wasapi(pContext, pDeviceEnumerator, deviceType);
8230 
8231  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
8232  return pDefaultDeviceID;
8233 }
8234 
8235 static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_IMMDevice** ppMMDevice)
8236 {
8237  ma_IMMDeviceEnumerator* pDeviceEnumerator;
8238  HRESULT hr;
8239 
8240  MA_ASSERT(pContext != NULL);
8241  MA_ASSERT(ppMMDevice != NULL);
8242 
8243  hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
8244  if (FAILED(hr)) {
8245  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.", ma_result_from_HRESULT(hr));
8246  }
8247 
8248  if (pDeviceID == NULL) {
8249  hr = ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(pDeviceEnumerator, (deviceType == ma_device_type_capture) ? ma_eCapture : ma_eRender, ma_eConsole, ppMMDevice);
8250  } else {
8251  hr = ma_IMMDeviceEnumerator_GetDevice(pDeviceEnumerator, pDeviceID->wasapi, ppMMDevice);
8252  }
8253 
8254  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
8255  if (FAILED(hr)) {
8256  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve IMMDevice.", ma_result_from_HRESULT(hr));
8257  }
8258 
8259  return MA_SUCCESS;
8260 }
8261 
8262 static ma_result ma_context_get_device_id_from_MMDevice__wasapi(ma_context* pContext, ma_IMMDevice* pMMDevice, ma_device_id* pDeviceID)
8263 {
8264  LPWSTR pDeviceIDString;
8265  HRESULT hr;
8266 
8267  MA_ASSERT(pDeviceID != NULL);
8268 
8269  hr = ma_IMMDevice_GetId(pMMDevice, &pDeviceIDString);
8270  if (SUCCEEDED(hr)) {
8271  size_t idlen = wcslen(pDeviceIDString);
8272  if (idlen+1 > ma_countof(pDeviceID->wasapi)) {
8273  ma_CoTaskMemFree(pContext, pDeviceIDString);
8274  MA_ASSERT(MA_FALSE); /* NOTE: If this is triggered, please report it. It means the format of the ID must haved change and is too long to fit in our fixed sized buffer. */
8275  return MA_ERROR;
8276  }
8277 
8278  MA_COPY_MEMORY(pDeviceID->wasapi, pDeviceIDString, idlen * sizeof(wchar_t));
8279  pDeviceID->wasapi[idlen] = '\0';
8280 
8281  ma_CoTaskMemFree(pContext, pDeviceIDString);
8282 
8283  return MA_SUCCESS;
8284  }
8285 
8286  return MA_ERROR;
8287 }
8288 
8289 static ma_result ma_context_get_device_info_from_MMDevice__wasapi(ma_context* pContext, ma_IMMDevice* pMMDevice, LPWSTR pDefaultDeviceID, ma_bool32 onlySimpleInfo, ma_device_info* pInfo)
8290 {
8291  ma_result result;
8292  HRESULT hr;
8293 
8294  MA_ASSERT(pContext != NULL);
8295  MA_ASSERT(pMMDevice != NULL);
8296  MA_ASSERT(pInfo != NULL);
8297 
8298  /* ID. */
8299  result = ma_context_get_device_id_from_MMDevice__wasapi(pContext, pMMDevice, &pInfo->id);
8300  if (result == MA_SUCCESS) {
8301  if (pDefaultDeviceID != NULL) {
8302  if (wcscmp(pInfo->id.wasapi, pDefaultDeviceID) == 0) {
8303  pInfo->isDefault = MA_TRUE;
8304  }
8305  }
8306  }
8307 
8308  /* Description / Friendly Name */
8309  {
8310  ma_IPropertyStore *pProperties;
8311  hr = ma_IMMDevice_OpenPropertyStore(pMMDevice, STGM_READ, &pProperties);
8312  if (SUCCEEDED(hr)) {
8313  PROPVARIANT var;
8314 
8315  ma_PropVariantInit(&var);
8316  hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &var);
8317  if (SUCCEEDED(hr)) {
8318  WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, pInfo->name, sizeof(pInfo->name), 0, FALSE);
8319  ma_PropVariantClear(pContext, &var);
8320  }
8321 
8322  ma_IPropertyStore_Release(pProperties);
8323  }
8324  }
8325 
8326  /* Format */
8327  if (!onlySimpleInfo) {
8328  ma_IAudioClient* pAudioClient;
8329  hr = ma_IMMDevice_Activate(pMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
8330  if (SUCCEEDED(hr)) {
8331  result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext, pMMDevice, pAudioClient, pInfo);
8332 
8333  ma_IAudioClient_Release(pAudioClient);
8334  return result;
8335  } else {
8336  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to activate audio client for device info retrieval.", ma_result_from_HRESULT(hr));
8337  }
8338  }
8339 
8340  return MA_SUCCESS;
8341 }
8342 
8343 static ma_result ma_context_enumerate_devices_by_type__wasapi(ma_context* pContext, ma_IMMDeviceEnumerator* pDeviceEnumerator, ma_device_type deviceType, ma_enum_devices_callback_proc callback, void* pUserData)
8344 {
8345  ma_result result = MA_SUCCESS;
8346  UINT deviceCount;
8347  HRESULT hr;
8348  ma_uint32 iDevice;
8349  LPWSTR pDefaultDeviceID = NULL;
8350  ma_IMMDeviceCollection* pDeviceCollection = NULL;
8351 
8352  MA_ASSERT(pContext != NULL);
8353  MA_ASSERT(callback != NULL);
8354 
8355  /* Grab the default device. We use this to know whether or not flag the returned device info as being the default. */
8356  pDefaultDeviceID = ma_context_get_default_device_id_from_IMMDeviceEnumerator__wasapi(pContext, pDeviceEnumerator, deviceType);
8357 
8358  /* We need to enumerate the devices which returns a device collection. */
8359  hr = ma_IMMDeviceEnumerator_EnumAudioEndpoints(pDeviceEnumerator, ma_device_type_to_EDataFlow(deviceType), MA_MM_DEVICE_STATE_ACTIVE, &pDeviceCollection);
8360  if (SUCCEEDED(hr)) {
8361  hr = ma_IMMDeviceCollection_GetCount(pDeviceCollection, &deviceCount);
8362  if (FAILED(hr)) {
8363  result = ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to get device count.", ma_result_from_HRESULT(hr));
8364  goto done;
8365  }
8366 
8367  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
8368  ma_device_info deviceInfo;
8369  ma_IMMDevice* pMMDevice;
8370 
8371  MA_ZERO_OBJECT(&deviceInfo);
8372 
8373  hr = ma_IMMDeviceCollection_Item(pDeviceCollection, iDevice, &pMMDevice);
8374  if (SUCCEEDED(hr)) {
8375  result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, pDefaultDeviceID, MA_TRUE, &deviceInfo); /* MA_TRUE = onlySimpleInfo. */
8376 
8377  ma_IMMDevice_Release(pMMDevice);
8378  if (result == MA_SUCCESS) {
8379  ma_bool32 cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
8380  if (cbResult == MA_FALSE) {
8381  break;
8382  }
8383  }
8384  }
8385  }
8386  }
8387 
8388 done:
8389  if (pDefaultDeviceID != NULL) {
8390  ma_CoTaskMemFree(pContext, pDefaultDeviceID);
8391  pDefaultDeviceID = NULL;
8392  }
8393 
8394  if (pDeviceCollection != NULL) {
8395  ma_IMMDeviceCollection_Release(pDeviceCollection);
8396  pDeviceCollection = NULL;
8397  }
8398 
8399  return result;
8400 }
8401 
8402 static ma_result ma_context_get_IAudioClient_Desktop__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_IAudioClient** ppAudioClient, ma_IMMDevice** ppMMDevice)
8403 {
8404  ma_result result;
8405  HRESULT hr;
8406 
8407  MA_ASSERT(pContext != NULL);
8408  MA_ASSERT(ppAudioClient != NULL);
8409  MA_ASSERT(ppMMDevice != NULL);
8410 
8411  result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, ppMMDevice);
8412  if (result != MA_SUCCESS) {
8413  return result;
8414  }
8415 
8416  hr = ma_IMMDevice_Activate(*ppMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)ppAudioClient);
8417  if (FAILED(hr)) {
8418  return ma_result_from_HRESULT(hr);
8419  }
8420 
8421  return MA_SUCCESS;
8422 }
8423 #else
8424 static ma_result ma_context_get_IAudioClient_UWP__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_IAudioClient** ppAudioClient, ma_IUnknown** ppActivatedInterface)
8425 {
8426  ma_IActivateAudioInterfaceAsyncOperation *pAsyncOp = NULL;
8427  ma_completion_handler_uwp completionHandler;
8428  IID iid;
8429  LPOLESTR iidStr;
8430  HRESULT hr;
8431  ma_result result;
8432  HRESULT activateResult;
8433  ma_IUnknown* pActivatedInterface;
8434 
8435  MA_ASSERT(pContext != NULL);
8436  MA_ASSERT(ppAudioClient != NULL);
8437 
8438  if (pDeviceID != NULL) {
8439  MA_COPY_MEMORY(&iid, pDeviceID->wasapi, sizeof(iid));
8440  } else {
8441  if (deviceType == ma_device_type_playback) {
8442  iid = MA_IID_DEVINTERFACE_AUDIO_RENDER;
8443  } else {
8444  iid = MA_IID_DEVINTERFACE_AUDIO_CAPTURE;
8445  }
8446  }
8447 
8448 #if defined(__cplusplus)
8449  hr = StringFromIID(iid, &iidStr);
8450 #else
8451  hr = StringFromIID(&iid, &iidStr);
8452 #endif
8453  if (FAILED(hr)) {
8454  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to convert device IID to string for ActivateAudioInterfaceAsync(). Out of memory.", ma_result_from_HRESULT(hr));
8455  }
8456 
8457  result = ma_completion_handler_uwp_init(&completionHandler);
8458  if (result != MA_SUCCESS) {
8459  ma_CoTaskMemFree(pContext, iidStr);
8460  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for waiting for ActivateAudioInterfaceAsync().", result);
8461  }
8462 
8463 #if defined(__cplusplus)
8464  hr = ActivateAudioInterfaceAsync(iidStr, MA_IID_IAudioClient, NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
8465 #else
8466  hr = ActivateAudioInterfaceAsync(iidStr, &MA_IID_IAudioClient, NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
8467 #endif
8468  if (FAILED(hr)) {
8469  ma_completion_handler_uwp_uninit(&completionHandler);
8470  ma_CoTaskMemFree(pContext, iidStr);
8471  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] ActivateAudioInterfaceAsync() failed.", ma_result_from_HRESULT(hr));
8472  }
8473 
8474  ma_CoTaskMemFree(pContext, iidStr);
8475 
8476  /* Wait for the async operation for finish. */
8477  ma_completion_handler_uwp_wait(&completionHandler);
8478  ma_completion_handler_uwp_uninit(&completionHandler);
8479 
8480  hr = ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(pAsyncOp, &activateResult, &pActivatedInterface);
8481  ma_IActivateAudioInterfaceAsyncOperation_Release(pAsyncOp);
8482 
8483  if (FAILED(hr) || FAILED(activateResult)) {
8484  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to activate device.", FAILED(hr) ? ma_result_from_HRESULT(hr) : ma_result_from_HRESULT(activateResult));
8485  }
8486 
8487  /* Here is where we grab the IAudioClient interface. */
8488  hr = ma_IUnknown_QueryInterface(pActivatedInterface, &MA_IID_IAudioClient, (void**)ppAudioClient);
8489  if (FAILED(hr)) {
8490  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to query IAudioClient interface.", ma_result_from_HRESULT(hr));
8491  }
8492 
8493  if (ppActivatedInterface) {
8494  *ppActivatedInterface = pActivatedInterface;
8495  } else {
8496  ma_IUnknown_Release(pActivatedInterface);
8497  }
8498 
8499  return MA_SUCCESS;
8500 }
8501 #endif
8502 
8503 static ma_result ma_context_get_IAudioClient__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_IAudioClient** ppAudioClient, ma_WASAPIDeviceInterface** ppDeviceInterface)
8504 {
8505 #ifdef MA_WIN32_DESKTOP
8506  return ma_context_get_IAudioClient_Desktop__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
8507 #else
8508  return ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
8509 #endif
8510 }
8511 
8512 
8513 static ma_result ma_context_enumerate_devices__wasapi(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
8514 {
8515  /* Different enumeration for desktop and UWP. */
8516 #ifdef MA_WIN32_DESKTOP
8517  /* Desktop */
8518  HRESULT hr;
8519  ma_IMMDeviceEnumerator* pDeviceEnumerator;
8520 
8521  hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
8522  if (FAILED(hr)) {
8523  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
8524  }
8525 
8526  ma_context_enumerate_devices_by_type__wasapi(pContext, pDeviceEnumerator, ma_device_type_playback, callback, pUserData);
8527  ma_context_enumerate_devices_by_type__wasapi(pContext, pDeviceEnumerator, ma_device_type_capture, callback, pUserData);
8528 
8529  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
8530 #else
8531  /*
8532  UWP
8533 
8534  The MMDevice API is only supported on desktop applications. For now, while I'm still figuring out how to properly enumerate
8535  over devices without using MMDevice, I'm restricting devices to defaults.
8536 
8537  Hint: DeviceInformation::FindAllAsync() with DeviceClass.AudioCapture/AudioRender. https://blogs.windows.com/buildingapps/2014/05/15/real-time-audio-in-windows-store-and-windows-phone-apps/
8538  */
8539  if (callback) {
8540  ma_bool32 cbResult = MA_TRUE;
8541 
8542  /* Playback. */
8543  if (cbResult) {
8544  ma_device_info deviceInfo;
8545  MA_ZERO_OBJECT(&deviceInfo);
8546  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
8547  deviceInfo.isDefault = MA_TRUE;
8548  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
8549  }
8550 
8551  /* Capture. */
8552  if (cbResult) {
8553  ma_device_info deviceInfo;
8554  MA_ZERO_OBJECT(&deviceInfo);
8555  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
8556  deviceInfo.isDefault = MA_TRUE;
8557  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
8558  }
8559  }
8560 #endif
8561 
8562  return MA_SUCCESS;
8563 }
8564 
8565 static ma_result ma_context_get_device_info__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
8566 {
8567 #ifdef MA_WIN32_DESKTOP
8568  ma_result result;
8569  ma_IMMDevice* pMMDevice = NULL;
8570  LPWSTR pDefaultDeviceID = NULL;
8571 
8572  result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, &pMMDevice);
8573  if (result != MA_SUCCESS) {
8574  return result;
8575  }
8576 
8577  /* We need the default device ID so we can set the isDefault flag in the device info. */
8578  pDefaultDeviceID = ma_context_get_default_device_id__wasapi(pContext, deviceType);
8579 
8580  result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, pDefaultDeviceID, MA_FALSE, pDeviceInfo); /* MA_FALSE = !onlySimpleInfo. */
8581 
8582  if (pDefaultDeviceID != NULL) {
8583  ma_CoTaskMemFree(pContext, pDefaultDeviceID);
8584  pDefaultDeviceID = NULL;
8585  }
8586 
8587  ma_IMMDevice_Release(pMMDevice);
8588 
8589  return result;
8590 #else
8591  ma_IAudioClient* pAudioClient;
8592  ma_result result;
8593 
8594  /* UWP currently only uses default devices. */
8595  if (deviceType == ma_device_type_playback) {
8596  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
8597  } else {
8598  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
8599  }
8600 
8601  result = ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, &pAudioClient, NULL);
8602  if (result != MA_SUCCESS) {
8603  return result;
8604  }
8605 
8606  result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext, NULL, pAudioClient, pDeviceInfo);
8607 
8608  pDeviceInfo->isDefault = MA_TRUE; /* UWP only supports default devices. */
8609 
8610  ma_IAudioClient_Release(pAudioClient);
8611  return result;
8612 #endif
8613 }
8614 
8615 static ma_result ma_device_uninit__wasapi(ma_device* pDevice)
8616 {
8617  MA_ASSERT(pDevice != NULL);
8618 
8619 #ifdef MA_WIN32_DESKTOP
8620  if (pDevice->wasapi.pDeviceEnumerator) {
8621  ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient);
8622  ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator);
8623  }
8624 #endif
8625 
8626  if (pDevice->wasapi.pRenderClient) {
8627  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
8628  }
8629  if (pDevice->wasapi.pCaptureClient) {
8630  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8631  }
8632 
8633  if (pDevice->wasapi.pAudioClientPlayback) {
8634  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8635  }
8636  if (pDevice->wasapi.pAudioClientCapture) {
8637  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8638  }
8639 
8640  if (pDevice->wasapi.hEventPlayback) {
8641  CloseHandle(pDevice->wasapi.hEventPlayback);
8642  }
8643  if (pDevice->wasapi.hEventCapture) {
8644  CloseHandle(pDevice->wasapi.hEventCapture);
8645  }
8646 
8647  return MA_SUCCESS;
8648 }
8649 
8650 
8651 typedef struct
8652 {
8653  /* Input. */
8654  ma_format formatIn;
8655  ma_uint32 channelsIn;
8656  ma_uint32 sampleRateIn;
8657  ma_channel channelMapIn[MA_MAX_CHANNELS];
8658  ma_uint32 periodSizeInFramesIn;
8659  ma_uint32 periodSizeInMillisecondsIn;
8660  ma_uint32 periodsIn;
8661  ma_share_mode shareMode;
8662  ma_performance_profile performanceProfile;
8663  ma_bool32 noAutoConvertSRC;
8664  ma_bool32 noDefaultQualitySRC;
8665  ma_bool32 noHardwareOffloading;
8666 
8667  /* Output. */
8668  ma_IAudioClient* pAudioClient;
8669  ma_IAudioRenderClient* pRenderClient;
8670  ma_IAudioCaptureClient* pCaptureClient;
8671  ma_format formatOut;
8672  ma_uint32 channelsOut;
8673  ma_uint32 sampleRateOut;
8674  ma_channel channelMapOut[MA_MAX_CHANNELS];
8675  ma_uint32 periodSizeInFramesOut;
8676  ma_uint32 periodsOut;
8677  ma_bool32 usingAudioClient3;
8678  char deviceName[256];
8679  ma_device_id id;
8680 } ma_device_init_internal_data__wasapi;
8681 
8682 static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_init_internal_data__wasapi* pData)
8683 {
8684  HRESULT hr;
8685  ma_result result = MA_SUCCESS;
8686  const char* errorMsg = "";
8687  MA_AUDCLNT_SHAREMODE shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
8688  DWORD streamFlags = 0;
8689  MA_REFERENCE_TIME periodDurationInMicroseconds;
8690  ma_bool32 wasInitializedUsingIAudioClient3 = MA_FALSE;
8691  WAVEFORMATEXTENSIBLE wf;
8692  ma_WASAPIDeviceInterface* pDeviceInterface = NULL;
8693  ma_IAudioClient2* pAudioClient2;
8694  ma_uint32 nativeSampleRate;
8695 
8696  MA_ASSERT(pContext != NULL);
8697  MA_ASSERT(pData != NULL);
8698 
8699  /* This function is only used to initialize one device type: either playback, capture or loopback. Never full-duplex. */
8700  if (deviceType == ma_device_type_duplex) {
8701  return MA_INVALID_ARGS;
8702  }
8703 
8704  pData->pAudioClient = NULL;
8705  pData->pRenderClient = NULL;
8706  pData->pCaptureClient = NULL;
8707 
8708  streamFlags = MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
8709  if (!pData->noAutoConvertSRC && pData->sampleRateIn != 0 && pData->shareMode != ma_share_mode_exclusive) { /* <-- Exclusive streams must use the native sample rate. */
8710  streamFlags |= MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
8711  }
8712  if (!pData->noDefaultQualitySRC && pData->sampleRateIn != 0 && (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) != 0) {
8713  streamFlags |= MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
8714  }
8715  if (deviceType == ma_device_type_loopback) {
8716  streamFlags |= MA_AUDCLNT_STREAMFLAGS_LOOPBACK;
8717  }
8718 
8719  result = ma_context_get_IAudioClient__wasapi(pContext, deviceType, pDeviceID, &pData->pAudioClient, &pDeviceInterface);
8720  if (result != MA_SUCCESS) {
8721  goto done;
8722  }
8723 
8724  MA_ZERO_OBJECT(&wf);
8725 
8726  /* Try enabling hardware offloading. */
8727  if (!pData->noHardwareOffloading) {
8728  hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient2, (void**)&pAudioClient2);
8729  if (SUCCEEDED(hr)) {
8730  BOOL isHardwareOffloadingSupported = 0;
8731  hr = ma_IAudioClient2_IsOffloadCapable(pAudioClient2, MA_AudioCategory_Other, &isHardwareOffloadingSupported);
8732  if (SUCCEEDED(hr) && isHardwareOffloadingSupported) {
8733  ma_AudioClientProperties clientProperties;
8734  MA_ZERO_OBJECT(&clientProperties);
8735  clientProperties.cbSize = sizeof(clientProperties);
8736  clientProperties.bIsOffload = 1;
8737  clientProperties.eCategory = MA_AudioCategory_Other;
8738  ma_IAudioClient2_SetClientProperties(pAudioClient2, &clientProperties);
8739  }
8740 
8741  pAudioClient2->lpVtbl->Release(pAudioClient2);
8742  }
8743  }
8744 
8745  /* Here is where we try to determine the best format to use with the device. If the client if wanting exclusive mode, first try finding the best format for that. If this fails, fall back to shared mode. */
8746  result = MA_FORMAT_NOT_SUPPORTED;
8747  if (pData->shareMode == ma_share_mode_exclusive) {
8748  #ifdef MA_WIN32_DESKTOP
8749  /* In exclusive mode on desktop we always use the backend's native format. */
8750  ma_IPropertyStore* pStore = NULL;
8751  hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pStore);
8752  if (SUCCEEDED(hr)) {
8753  PROPVARIANT prop;
8754  ma_PropVariantInit(&prop);
8755  hr = ma_IPropertyStore_GetValue(pStore, &MA_PKEY_AudioEngine_DeviceFormat, &prop);
8756  if (SUCCEEDED(hr)) {
8757  WAVEFORMATEX* pActualFormat = (WAVEFORMATEX*)prop.blob.pBlobData;
8758  hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pData->pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pActualFormat, NULL);
8759  if (SUCCEEDED(hr)) {
8760  MA_COPY_MEMORY(&wf, pActualFormat, sizeof(WAVEFORMATEXTENSIBLE));
8761  }
8762 
8763  ma_PropVariantClear(pContext, &prop);
8764  }
8765 
8766  ma_IPropertyStore_Release(pStore);
8767  }
8768  #else
8769  /*
8770  I do not know how to query the device's native format on UWP so for now I'm just disabling support for
8771  exclusive mode. The alternative is to enumerate over different formats and check IsFormatSupported()
8772  until you find one that works.
8773 
8774  TODO: Add support for exclusive mode to UWP.
8775  */
8776  hr = S_FALSE;
8777  #endif
8778 
8779  if (hr == S_OK) {
8780  shareMode = MA_AUDCLNT_SHAREMODE_EXCLUSIVE;
8781  result = MA_SUCCESS;
8782  } else {
8783  result = MA_SHARE_MODE_NOT_SUPPORTED;
8784  }
8785  } else {
8786  /* In shared mode we are always using the format reported by the operating system. */
8787  WAVEFORMATEXTENSIBLE* pNativeFormat = NULL;
8788  hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pData->pAudioClient, (WAVEFORMATEX**)&pNativeFormat);
8789  if (hr != S_OK) {
8790  result = MA_FORMAT_NOT_SUPPORTED;
8791  } else {
8792  MA_COPY_MEMORY(&wf, pNativeFormat, sizeof(wf));
8793  result = MA_SUCCESS;
8794  }
8795 
8796  ma_CoTaskMemFree(pContext, pNativeFormat);
8797 
8798  shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
8799  }
8800 
8801  /* Return an error if we still haven't found a format. */
8802  if (result != MA_SUCCESS) {
8803  errorMsg = "[WASAPI] Failed to find best device mix format.";
8804  goto done;
8805  }
8806 
8807  /*
8808  Override the native sample rate with the one requested by the caller, but only if we're not using the default sample rate. We'll use
8809  WASAPI to perform the sample rate conversion.
8810  */
8811  nativeSampleRate = wf.Format.nSamplesPerSec;
8812  if (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) {
8813  wf.Format.nSamplesPerSec = (pData->sampleRateIn != 0) ? pData->sampleRateIn : MA_DEFAULT_SAMPLE_RATE;
8814  wf.Format.nAvgBytesPerSec = wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
8815  }
8816 
8817  pData->formatOut = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)&wf);
8818  if (pData->formatOut == ma_format_unknown) {
8819  /*
8820  The format isn't supported. This is almost certainly because the exclusive mode format isn't supported by miniaudio. We need to return MA_SHARE_MODE_NOT_SUPPORTED
8821  in this case so that the caller can detect it and fall back to shared mode if desired. We should never get here if shared mode was requested, but just for
8822  completeness we'll check for it and return MA_FORMAT_NOT_SUPPORTED.
8823  */
8824  if (shareMode == MA_AUDCLNT_SHAREMODE_EXCLUSIVE) {
8825  result = MA_SHARE_MODE_NOT_SUPPORTED;
8826  } else {
8827  result = MA_FORMAT_NOT_SUPPORTED;
8828  }
8829 
8830  errorMsg = "[WASAPI] Native format not supported.";
8831  goto done;
8832  }
8833 
8834  pData->channelsOut = wf.Format.nChannels;
8835  pData->sampleRateOut = wf.Format.nSamplesPerSec;
8836 
8837  /* Get the internal channel map based on the channel mask. */
8838  ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
8839 
8840  /* Period size. */
8841  pData->periodsOut = (pData->periodsIn != 0) ? pData->periodsIn : MA_DEFAULT_PERIODS;
8842  pData->periodSizeInFramesOut = pData->periodSizeInFramesIn;
8843  if (pData->periodSizeInFramesOut == 0) {
8844  if (pData->periodSizeInMillisecondsIn == 0) {
8845  if (pData->performanceProfile == ma_performance_profile_low_latency) {
8846  pData->periodSizeInFramesOut = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY, wf.Format.nSamplesPerSec);
8847  } else {
8849  }
8850  } else {
8851  pData->periodSizeInFramesOut = ma_calculate_buffer_size_in_frames_from_milliseconds(pData->periodSizeInMillisecondsIn, wf.Format.nSamplesPerSec);
8852  }
8853  }
8854 
8855  periodDurationInMicroseconds = ((ma_uint64)pData->periodSizeInFramesOut * 1000 * 1000) / wf.Format.nSamplesPerSec;
8856 
8857 
8858  /* Slightly different initialization for shared and exclusive modes. We try exclusive mode first, and if it fails, fall back to shared mode. */
8859  if (shareMode == MA_AUDCLNT_SHAREMODE_EXCLUSIVE) {
8860  MA_REFERENCE_TIME bufferDuration = periodDurationInMicroseconds * 10;
8861 
8862  /*
8863  If the periodicy is too small, Initialize() will fail with AUDCLNT_E_INVALID_DEVICE_PERIOD. In this case we should just keep increasing
8864  it and trying it again.
8865  */
8866  hr = E_FAIL;
8867  for (;;) {
8868  hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf, NULL);
8869  if (hr == MA_AUDCLNT_E_INVALID_DEVICE_PERIOD) {
8870  if (bufferDuration > 500*10000) {
8871  break;
8872  } else {
8873  if (bufferDuration == 0) { /* <-- Just a sanity check to prevent an infinit loop. Should never happen, but it makes me feel better. */
8874  break;
8875  }
8876 
8877  bufferDuration = bufferDuration * 2;
8878  continue;
8879  }
8880  } else {
8881  break;
8882  }
8883  }
8884 
8885  if (hr == MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
8886  ma_uint32 bufferSizeInFrames;
8887  hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
8888  if (SUCCEEDED(hr)) {
8889  bufferDuration = (MA_REFERENCE_TIME)((10000.0 * 1000 / wf.Format.nSamplesPerSec * bufferSizeInFrames) + 0.5);
8890 
8891  /* Unfortunately we need to release and re-acquire the audio client according to MSDN. Seems silly - why not just call IAudioClient_Initialize() again?! */
8892  ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
8893 
8894  #ifdef MA_WIN32_DESKTOP
8895  hr = ma_IMMDevice_Activate(pDeviceInterface, &MA_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pData->pAudioClient);
8896  #else
8897  hr = ma_IUnknown_QueryInterface(pDeviceInterface, &MA_IID_IAudioClient, (void**)&pData->pAudioClient);
8898  #endif
8899 
8900  if (SUCCEEDED(hr)) {
8901  hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf, NULL);
8902  }
8903  }
8904  }
8905 
8906  if (FAILED(hr)) {
8907  /* Failed to initialize in exclusive mode. Don't fall back to shared mode - instead tell the client about it. They can reinitialize in shared mode if they want. */
8908  if (hr == E_ACCESSDENIED) {
8909  errorMsg = "[WASAPI] Failed to initialize device in exclusive mode. Access denied.", result = MA_ACCESS_DENIED;
8910  } else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
8911  errorMsg = "[WASAPI] Failed to initialize device in exclusive mode. Device in use.", result = MA_BUSY;
8912  } else {
8913  errorMsg = "[WASAPI] Failed to initialize device in exclusive mode."; result = ma_result_from_HRESULT(hr);
8914  }
8915  goto done;
8916  }
8917  }
8918 
8919  if (shareMode == MA_AUDCLNT_SHAREMODE_SHARED) {
8920  /*
8921  Low latency shared mode via IAudioClient3.
8922 
8923  NOTE
8924  ====
8925  Contrary to the documentation on MSDN (https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-initializesharedaudiostream), the
8926  use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM and AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY with IAudioClient3_InitializeSharedAudioStream() absolutely does not work. Using
8927  any of these flags will result in HRESULT code 0x88890021. The other problem is that calling IAudioClient3_GetSharedModeEnginePeriod() with a sample rate different to
8928  that returned by IAudioClient_GetMixFormat() also results in an error. I'm therefore disabling low-latency shared mode with AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM.
8929  */
8930  #ifndef MA_WASAPI_NO_LOW_LATENCY_SHARED_MODE
8931  {
8932  if ((streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) == 0 || nativeSampleRate == wf.Format.nSamplesPerSec) {
8933  ma_IAudioClient3* pAudioClient3 = NULL;
8934  hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient3, (void**)&pAudioClient3);
8935  if (SUCCEEDED(hr)) {
8936  ma_uint32 defaultPeriodInFrames;
8937  ma_uint32 fundamentalPeriodInFrames;
8938  ma_uint32 minPeriodInFrames;
8939  ma_uint32 maxPeriodInFrames;
8940  hr = ma_IAudioClient3_GetSharedModeEnginePeriod(pAudioClient3, (WAVEFORMATEX*)&wf, &defaultPeriodInFrames, &fundamentalPeriodInFrames, &minPeriodInFrames, &maxPeriodInFrames);
8941  if (SUCCEEDED(hr)) {
8942  ma_uint32 desiredPeriodInFrames = pData->periodSizeInFramesOut;
8943  ma_uint32 actualPeriodInFrames = desiredPeriodInFrames;
8944 
8945  /* Make sure the period size is a multiple of fundamentalPeriodInFrames. */
8946  actualPeriodInFrames = actualPeriodInFrames / fundamentalPeriodInFrames;
8947  actualPeriodInFrames = actualPeriodInFrames * fundamentalPeriodInFrames;
8948 
8949  /* The period needs to be clamped between minPeriodInFrames and maxPeriodInFrames. */
8950  actualPeriodInFrames = ma_clamp(actualPeriodInFrames, minPeriodInFrames, maxPeriodInFrames);
8951 
8952  #if defined(MA_DEBUG_OUTPUT)
8953  {
8954  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] Trying IAudioClient3_InitializeSharedAudioStream(actualPeriodInFrames=%d)\n", actualPeriodInFrames);
8955  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " defaultPeriodInFrames=%d\n", defaultPeriodInFrames);
8956  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " fundamentalPeriodInFrames=%d\n", fundamentalPeriodInFrames);
8957  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " minPeriodInFrames=%d\n", minPeriodInFrames);
8958  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " maxPeriodInFrames=%d\n", maxPeriodInFrames);
8959  }
8960  #endif
8961 
8962  /* If the client requested a largish buffer than we don't actually want to use low latency shared mode because it forces small buffers. */
8963  if (actualPeriodInFrames >= desiredPeriodInFrames) {
8964  /*
8965  MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY must not be in the stream flags. If either of these are specified,
8966  IAudioClient3_InitializeSharedAudioStream() will fail.
8967  */
8968  hr = ma_IAudioClient3_InitializeSharedAudioStream(pAudioClient3, streamFlags & ~(MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY), actualPeriodInFrames, (WAVEFORMATEX*)&wf, NULL);
8969  if (SUCCEEDED(hr)) {
8970  wasInitializedUsingIAudioClient3 = MA_TRUE;
8971  pData->periodSizeInFramesOut = actualPeriodInFrames;
8972  #if defined(MA_DEBUG_OUTPUT)
8973  {
8974  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] Using IAudioClient3\n");
8975  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " periodSizeInFramesOut=%d\n", pData->periodSizeInFramesOut);
8976  }
8977  #endif
8978  } else {
8979  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] IAudioClient3_InitializeSharedAudioStream failed. Falling back to IAudioClient.\n");
8980  }
8981  } else {
8982  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] Not using IAudioClient3 because the desired period size is larger than the maximum supported by IAudioClient3.\n");
8983  }
8984  } else {
8985  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] IAudioClient3_GetSharedModeEnginePeriod failed. Falling back to IAudioClient.\n");
8986  }
8987 
8988  ma_IAudioClient3_Release(pAudioClient3);
8989  pAudioClient3 = NULL;
8990  }
8991  }
8992  }
8993  #else
8994  {
8995  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] Not using IAudioClient3 because MA_WASAPI_NO_LOW_LATENCY_SHARED_MODE is enabled.\n");
8996  }
8997  #endif
8998 
8999  /* If we don't have an IAudioClient3 then we need to use the normal initialization routine. */
9000  if (!wasInitializedUsingIAudioClient3) {
9001  MA_REFERENCE_TIME bufferDuration = periodDurationInMicroseconds * pData->periodsOut * 10; /* <-- Multiply by 10 for microseconds to 100-nanoseconds. */
9002  hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, 0, (WAVEFORMATEX*)&wf, NULL);
9003  if (FAILED(hr)) {
9004  if (hr == E_ACCESSDENIED) {
9005  errorMsg = "[WASAPI] Failed to initialize device. Access denied.", result = MA_ACCESS_DENIED;
9006  } else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
9007  errorMsg = "[WASAPI] Failed to initialize device. Device in use.", result = MA_BUSY;
9008  } else {
9009  errorMsg = "[WASAPI] Failed to initialize device.", result = ma_result_from_HRESULT(hr);
9010  }
9011 
9012  goto done;
9013  }
9014  }
9015  }
9016 
9017  if (!wasInitializedUsingIAudioClient3) {
9018  ma_uint32 bufferSizeInFrames;
9019  hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
9020  if (FAILED(hr)) {
9021  errorMsg = "[WASAPI] Failed to get audio client's actual buffer size.", result = ma_result_from_HRESULT(hr);
9022  goto done;
9023  }
9024 
9025  pData->periodSizeInFramesOut = bufferSizeInFrames / pData->periodsOut;
9026  }
9027 
9028  pData->usingAudioClient3 = wasInitializedUsingIAudioClient3;
9029 
9030 
9031  if (deviceType == ma_device_type_playback) {
9032  result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pRenderClient);
9033  } else {
9034  result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pCaptureClient);
9035  }
9036 
9037  /*if (FAILED(hr)) {*/
9038  if (result != MA_SUCCESS) {
9039  errorMsg = "[WASAPI] Failed to get audio client service.";
9040  goto done;
9041  }
9042 
9043 
9044  /* Grab the name of the device. */
9045  #ifdef MA_WIN32_DESKTOP
9046  {
9047  ma_IPropertyStore *pProperties;
9048  hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pProperties);
9049  if (SUCCEEDED(hr)) {
9050  PROPVARIANT varName;
9051  ma_PropVariantInit(&varName);
9052  hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &varName);
9053  if (SUCCEEDED(hr)) {
9054  WideCharToMultiByte(CP_UTF8, 0, varName.pwszVal, -1, pData->deviceName, sizeof(pData->deviceName), 0, FALSE);
9055  ma_PropVariantClear(pContext, &varName);
9056  }
9057 
9058  ma_IPropertyStore_Release(pProperties);
9059  }
9060  }
9061  #endif
9062 
9063  /*
9064  For the WASAPI backend we need to know the actual IDs of the device in order to do automatic
9065  stream routing so that IDs can be compared and we can determine which device has been detached
9066  and whether or not it matches with our ma_device.
9067  */
9068  #ifdef MA_WIN32_DESKTOP
9069  {
9070  /* Desktop */
9071  ma_context_get_device_id_from_MMDevice__wasapi(pContext, pDeviceInterface, &pData->id);
9072  }
9073  #else
9074  {
9075  /* UWP */
9076  /* TODO: Implement me. Need to figure out how to get the ID of the default device. */
9077  }
9078  #endif
9079 
9080 done:
9081  /* Clean up. */
9082 #ifdef MA_WIN32_DESKTOP
9083  if (pDeviceInterface != NULL) {
9084  ma_IMMDevice_Release(pDeviceInterface);
9085  }
9086 #else
9087  if (pDeviceInterface != NULL) {
9088  ma_IUnknown_Release(pDeviceInterface);
9089  }
9090 #endif
9091 
9092  if (result != MA_SUCCESS) {
9093  if (pData->pRenderClient) {
9094  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pData->pRenderClient);
9095  pData->pRenderClient = NULL;
9096  }
9097  if (pData->pCaptureClient) {
9098  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pData->pCaptureClient);
9099  pData->pCaptureClient = NULL;
9100  }
9101  if (pData->pAudioClient) {
9102  ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
9103  pData->pAudioClient = NULL;
9104  }
9105 
9106  if (errorMsg != NULL && errorMsg[0] != '\0') {
9107  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_ERROR, errorMsg);
9108  }
9109 
9110  return result;
9111  } else {
9112  return MA_SUCCESS;
9113  }
9114 }
9115 
9116 static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type deviceType)
9117 {
9118  ma_device_init_internal_data__wasapi data;
9119  ma_result result;
9120 
9121  MA_ASSERT(pDevice != NULL);
9122 
9123  /* We only re-initialize the playback or capture device. Never a full-duplex device. */
9124  if (deviceType == ma_device_type_duplex) {
9125  return MA_INVALID_ARGS;
9126  }
9127 
9128 
9129  /*
9130  Before reinitializing the device we need to free the previous audio clients.
9131 
9132  There's a known memory leak here. We will be calling this from the routing change callback that
9133  is fired by WASAPI. If we attempt to release the IAudioClient we will deadlock. In my opinion
9134  this is a bug. I'm not sure what I need to do to handle this cleanly, but I think we'll probably
9135  need some system where we post an event, but delay the execution of it until the callback has
9136  returned. I'm not sure how to do this reliably, however. I have set up some infrastructure for
9137  a command thread which might be useful for this.
9138  */
9139  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
9140  if (pDevice->wasapi.pCaptureClient) {
9141  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
9142  pDevice->wasapi.pCaptureClient = NULL;
9143  }
9144 
9145  if (pDevice->wasapi.pAudioClientCapture) {
9146  /*ma_device_release_IAudioClient_service__wasapi(pDevice, ma_device_type_capture);*/
9147  pDevice->wasapi.pAudioClientCapture = NULL;
9148  }
9149  }
9150 
9151  if (deviceType == ma_device_type_playback) {
9152  if (pDevice->wasapi.pRenderClient) {
9153  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
9154  pDevice->wasapi.pRenderClient = NULL;
9155  }
9156 
9157  if (pDevice->wasapi.pAudioClientPlayback) {
9158  /*ma_device_release_IAudioClient_service__wasapi(pDevice, ma_device_type_playback);*/
9159  pDevice->wasapi.pAudioClientPlayback = NULL;
9160  }
9161  }
9162 
9163 
9164  if (deviceType == ma_device_type_playback) {
9165  data.formatIn = pDevice->playback.format;
9166  data.channelsIn = pDevice->playback.channels;
9167  MA_COPY_MEMORY(data.channelMapIn, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
9168  data.shareMode = pDevice->playback.shareMode;
9169  } else {
9170  data.formatIn = pDevice->capture.format;
9171  data.channelsIn = pDevice->capture.channels;
9172  MA_COPY_MEMORY(data.channelMapIn, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
9173  data.shareMode = pDevice->capture.shareMode;
9174  }
9175 
9176  data.sampleRateIn = pDevice->sampleRate;
9177  data.periodSizeInFramesIn = pDevice->wasapi.originalPeriodSizeInFrames;
9178  data.periodSizeInMillisecondsIn = pDevice->wasapi.originalPeriodSizeInMilliseconds;
9179  data.periodsIn = pDevice->wasapi.originalPeriods;
9180  data.performanceProfile = pDevice->wasapi.originalPerformanceProfile;
9181  data.noAutoConvertSRC = pDevice->wasapi.noAutoConvertSRC;
9182  data.noDefaultQualitySRC = pDevice->wasapi.noDefaultQualitySRC;
9183  data.noHardwareOffloading = pDevice->wasapi.noHardwareOffloading;
9184  result = ma_device_init_internal__wasapi(pDevice->pContext, deviceType, NULL, &data);
9185  if (result != MA_SUCCESS) {
9186  return result;
9187  }
9188 
9189  /* At this point we have some new objects ready to go. We need to uninitialize the previous ones and then set the new ones. */
9190  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
9191  pDevice->wasapi.pAudioClientCapture = data.pAudioClient;
9192  pDevice->wasapi.pCaptureClient = data.pCaptureClient;
9193 
9194  pDevice->capture.internalFormat = data.formatOut;
9195  pDevice->capture.internalChannels = data.channelsOut;
9196  pDevice->capture.internalSampleRate = data.sampleRateOut;
9197  MA_COPY_MEMORY(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
9198  pDevice->capture.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
9199  pDevice->capture.internalPeriods = data.periodsOut;
9200  ma_strcpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), data.deviceName);
9201 
9202  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
9203 
9204  pDevice->wasapi.periodSizeInFramesCapture = data.periodSizeInFramesOut;
9205  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualPeriodSizeInFramesCapture);
9206 
9207  /* We must always have a valid ID. */
9208  ma_wcscpy_s(pDevice->capture.id.wasapi, sizeof(pDevice->capture.id.wasapi), data.id.wasapi);
9209  }
9210 
9211  if (deviceType == ma_device_type_playback) {
9212  pDevice->wasapi.pAudioClientPlayback = data.pAudioClient;
9213  pDevice->wasapi.pRenderClient = data.pRenderClient;
9214 
9215  pDevice->playback.internalFormat = data.formatOut;
9216  pDevice->playback.internalChannels = data.channelsOut;
9217  pDevice->playback.internalSampleRate = data.sampleRateOut;
9218  MA_COPY_MEMORY(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
9219  pDevice->playback.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
9220  pDevice->playback.internalPeriods = data.periodsOut;
9221  ma_strcpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), data.deviceName);
9222 
9223  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
9224 
9225  pDevice->wasapi.periodSizeInFramesPlayback = data.periodSizeInFramesOut;
9226  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualPeriodSizeInFramesPlayback);
9227 
9228  /* We must always have a valid ID. */
9229  ma_wcscpy_s(pDevice->playback.id.wasapi, sizeof(pDevice->playback.id.wasapi), data.id.wasapi);
9230  }
9231 
9232  return MA_SUCCESS;
9233 }
9234 
9235 static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
9236 {
9237  ma_result result = MA_SUCCESS;
9238 
9239 #ifdef MA_WIN32_DESKTOP
9240  HRESULT hr;
9241  ma_IMMDeviceEnumerator* pDeviceEnumerator;
9242 #endif
9243 
9244  MA_ASSERT(pDevice != NULL);
9245 
9246  MA_ZERO_OBJECT(&pDevice->wasapi);
9247  pDevice->wasapi.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
9248  pDevice->wasapi.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
9249  pDevice->wasapi.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
9250 
9251  /* Exclusive mode is not allowed with loopback. */
9253  return MA_INVALID_DEVICE_CONFIG;
9254  }
9255 
9257  ma_device_init_internal_data__wasapi data;
9258  data.formatIn = pDescriptorCapture->format;
9259  data.channelsIn = pDescriptorCapture->channels;
9260  data.sampleRateIn = pDescriptorCapture->sampleRate;
9261  MA_COPY_MEMORY(data.channelMapIn, pDescriptorCapture->channelMap, sizeof(pDescriptorCapture->channelMap));
9262  data.periodSizeInFramesIn = pDescriptorCapture->periodSizeInFrames;
9263  data.periodSizeInMillisecondsIn = pDescriptorCapture->periodSizeInMilliseconds;
9264  data.periodsIn = pDescriptorCapture->periodCount;
9265  data.shareMode = pDescriptorCapture->shareMode;
9266  data.performanceProfile = pConfig->performanceProfile;
9267  data.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
9268  data.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
9269  data.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
9270 
9271  result = ma_device_init_internal__wasapi(pDevice->pContext, (pConfig->deviceType == ma_device_type_loopback) ? ma_device_type_loopback : ma_device_type_capture, pDescriptorCapture->pDeviceID, &data);
9272  if (result != MA_SUCCESS) {
9273  return result;
9274  }
9275 
9276  pDevice->wasapi.pAudioClientCapture = data.pAudioClient;
9277  pDevice->wasapi.pCaptureClient = data.pCaptureClient;
9278  pDevice->wasapi.originalPeriodSizeInMilliseconds = pDescriptorCapture->periodSizeInMilliseconds;
9279  pDevice->wasapi.originalPeriodSizeInFrames = pDescriptorCapture->periodSizeInFrames;
9280  pDevice->wasapi.originalPeriods = pDescriptorCapture->periodCount;
9281  pDevice->wasapi.originalPerformanceProfile = pConfig->performanceProfile;
9282 
9283  /*
9284  The event for capture needs to be manual reset for the same reason as playback. We keep the initial state set to unsignaled,
9285  however, because we want to block until we actually have something for the first call to ma_device_read().
9286  */
9287  pDevice->wasapi.hEventCapture = CreateEventW(NULL, FALSE, FALSE, NULL); /* Auto reset, unsignaled by default. */
9288  if (pDevice->wasapi.hEventCapture == NULL) {
9289  result = ma_result_from_GetLastError(GetLastError());
9290 
9291  if (pDevice->wasapi.pCaptureClient != NULL) {
9292  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
9293  pDevice->wasapi.pCaptureClient = NULL;
9294  }
9295  if (pDevice->wasapi.pAudioClientCapture != NULL) {
9296  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9297  pDevice->wasapi.pAudioClientCapture = NULL;
9298  }
9299 
9300  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for capture.", result);
9301  }
9302  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
9303 
9304  pDevice->wasapi.periodSizeInFramesCapture = data.periodSizeInFramesOut;
9305  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualPeriodSizeInFramesCapture);
9306 
9307  /* We must always have a valid ID. */
9308  ma_wcscpy_s(pDevice->capture.id.wasapi, sizeof(pDevice->capture.id.wasapi), data.id.wasapi);
9309 
9310  /* The descriptor needs to be updated with actual values. */
9311  pDescriptorCapture->format = data.formatOut;
9312  pDescriptorCapture->channels = data.channelsOut;
9313  pDescriptorCapture->sampleRate = data.sampleRateOut;
9314  MA_COPY_MEMORY(pDescriptorCapture->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
9315  pDescriptorCapture->periodSizeInFrames = data.periodSizeInFramesOut;
9316  pDescriptorCapture->periodCount = data.periodsOut;
9317  }
9318 
9319  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
9320  ma_device_init_internal_data__wasapi data;
9321  data.formatIn = pDescriptorPlayback->format;
9322  data.channelsIn = pDescriptorPlayback->channels;
9323  data.sampleRateIn = pDescriptorPlayback->sampleRate;
9324  MA_COPY_MEMORY(data.channelMapIn, pDescriptorPlayback->channelMap, sizeof(pDescriptorPlayback->channelMap));
9325  data.periodSizeInFramesIn = pDescriptorPlayback->periodSizeInFrames;
9326  data.periodSizeInMillisecondsIn = pDescriptorPlayback->periodSizeInMilliseconds;
9327  data.periodsIn = pDescriptorPlayback->periodCount;
9328  data.shareMode = pDescriptorPlayback->shareMode;
9329  data.performanceProfile = pConfig->performanceProfile;
9330  data.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
9331  data.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
9332  data.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
9333 
9334  result = ma_device_init_internal__wasapi(pDevice->pContext, ma_device_type_playback, pDescriptorPlayback->pDeviceID, &data);
9335  if (result != MA_SUCCESS) {
9336  if (pConfig->deviceType == ma_device_type_duplex) {
9337  if (pDevice->wasapi.pCaptureClient != NULL) {
9338  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
9339  pDevice->wasapi.pCaptureClient = NULL;
9340  }
9341  if (pDevice->wasapi.pAudioClientCapture != NULL) {
9342  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9343  pDevice->wasapi.pAudioClientCapture = NULL;
9344  }
9345 
9346  CloseHandle(pDevice->wasapi.hEventCapture);
9347  pDevice->wasapi.hEventCapture = NULL;
9348  }
9349  return result;
9350  }
9351 
9352  pDevice->wasapi.pAudioClientPlayback = data.pAudioClient;
9353  pDevice->wasapi.pRenderClient = data.pRenderClient;
9354  pDevice->wasapi.originalPeriodSizeInMilliseconds = pDescriptorPlayback->periodSizeInMilliseconds;
9355  pDevice->wasapi.originalPeriodSizeInFrames = pDescriptorPlayback->periodSizeInFrames;
9356  pDevice->wasapi.originalPeriods = pDescriptorPlayback->periodCount;
9357  pDevice->wasapi.originalPerformanceProfile = pConfig->performanceProfile;
9358 
9359  /*
9360  The event for playback is needs to be manual reset because we want to explicitly control the fact that it becomes signalled
9361  only after the whole available space has been filled, never before.
9362 
9363  The playback event also needs to be initially set to a signaled state so that the first call to ma_device_write() is able
9364  to get passed WaitForMultipleObjects().
9365  */
9366  pDevice->wasapi.hEventPlayback = CreateEventW(NULL, FALSE, TRUE, NULL); /* Auto reset, signaled by default. */
9367  if (pDevice->wasapi.hEventPlayback == NULL) {
9368  result = ma_result_from_GetLastError(GetLastError());
9369 
9370  if (pConfig->deviceType == ma_device_type_duplex) {
9371  if (pDevice->wasapi.pCaptureClient != NULL) {
9372  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
9373  pDevice->wasapi.pCaptureClient = NULL;
9374  }
9375  if (pDevice->wasapi.pAudioClientCapture != NULL) {
9376  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9377  pDevice->wasapi.pAudioClientCapture = NULL;
9378  }
9379 
9380  CloseHandle(pDevice->wasapi.hEventCapture);
9381  pDevice->wasapi.hEventCapture = NULL;
9382  }
9383 
9384  if (pDevice->wasapi.pRenderClient != NULL) {
9385  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
9386  pDevice->wasapi.pRenderClient = NULL;
9387  }
9388  if (pDevice->wasapi.pAudioClientPlayback != NULL) {
9389  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9390  pDevice->wasapi.pAudioClientPlayback = NULL;
9391  }
9392 
9393  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for playback.", result);
9394  }
9395  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
9396 
9397  pDevice->wasapi.periodSizeInFramesPlayback = data.periodSizeInFramesOut;
9398  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualPeriodSizeInFramesPlayback);
9399 
9400  /* We must always have a valid ID. */
9401  ma_wcscpy_s(pDevice->playback.id.wasapi, sizeof(pDevice->playback.id.wasapi), data.id.wasapi);
9402 
9403  /* The descriptor needs to be updated with actual values. */
9404  pDescriptorPlayback->format = data.formatOut;
9405  pDescriptorPlayback->channels = data.channelsOut;
9406  pDescriptorPlayback->sampleRate = data.sampleRateOut;
9407  MA_COPY_MEMORY(pDescriptorPlayback->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
9408  pDescriptorPlayback->periodSizeInFrames = data.periodSizeInFramesOut;
9409  pDescriptorPlayback->periodCount = data.periodsOut;
9410  }
9411 
9412  /*
9413  We need to register a notification client to detect when the device has been disabled, unplugged or re-routed (when the default device changes). When
9414  we are connecting to the default device we want to do automatic stream routing when the device is disabled or unplugged. Otherwise we want to just
9415  stop the device outright and let the application handle it.
9416  */
9417 #ifdef MA_WIN32_DESKTOP
9418  if (pConfig->wasapi.noAutoStreamRouting == MA_FALSE) {
9419  if ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pConfig->capture.pDeviceID == NULL) {
9420  pDevice->wasapi.allowCaptureAutoStreamRouting = MA_TRUE;
9421  }
9422  if ((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pConfig->playback.pDeviceID == NULL) {
9423  pDevice->wasapi.allowPlaybackAutoStreamRouting = MA_TRUE;
9424  }
9425  }
9426 
9427  hr = ma_CoCreateInstance(pDevice->pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
9428  if (FAILED(hr)) {
9429  ma_device_uninit__wasapi(pDevice);
9430  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
9431  }
9432 
9433  pDevice->wasapi.notificationClient.lpVtbl = (void*)&g_maNotificationCientVtbl;
9434  pDevice->wasapi.notificationClient.counter = 1;
9435  pDevice->wasapi.notificationClient.pDevice = pDevice;
9436 
9437  hr = pDeviceEnumerator->lpVtbl->RegisterEndpointNotificationCallback(pDeviceEnumerator, &pDevice->wasapi.notificationClient);
9438  if (SUCCEEDED(hr)) {
9439  pDevice->wasapi.pDeviceEnumerator = (ma_ptr)pDeviceEnumerator;
9440  } else {
9441  /* Not the end of the world if we fail to register the notification callback. We just won't support automatic stream routing. */
9442  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
9443  }
9444 #endif
9445 
9446  c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_FALSE);
9447  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_FALSE);
9448 
9449  return MA_SUCCESS;
9450 }
9451 
9452 static ma_result ma_device__get_available_frames__wasapi(ma_device* pDevice, ma_IAudioClient* pAudioClient, ma_uint32* pFrameCount)
9453 {
9454  ma_uint32 paddingFramesCount;
9455  HRESULT hr;
9456  ma_share_mode shareMode;
9457 
9458  MA_ASSERT(pDevice != NULL);
9459  MA_ASSERT(pFrameCount != NULL);
9460 
9461  *pFrameCount = 0;
9462 
9463  if ((ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientPlayback && (ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientCapture) {
9464  return MA_INVALID_OPERATION;
9465  }
9466 
9467  /*
9468  I've had a report that GetCurrentPadding() is returning a frame count of 0 which is preventing
9469  higher level function calls from doing anything because it thinks nothing is available. I have
9470  taken a look at the documentation and it looks like this is unnecessary in exclusive mode.
9471 
9472  From Microsoft's documentation:
9473 
9474  For an exclusive-mode rendering or capture stream that was initialized with the
9475  AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag, the client typically has no use for the padding
9476  value reported by GetCurrentPadding. Instead, the client accesses an entire buffer during
9477  each processing pass.
9478 
9479  Considering this, I'm going to skip GetCurrentPadding() for exclusive mode and just report the
9480  entire buffer. This depends on the caller making sure they wait on the event handler.
9481  */
9482  shareMode = ((ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) ? pDevice->playback.shareMode : pDevice->capture.shareMode;
9483  if (shareMode == ma_share_mode_shared) {
9484  /* Shared mode. */
9485  hr = ma_IAudioClient_GetCurrentPadding(pAudioClient, &paddingFramesCount);
9486  if (FAILED(hr)) {
9487  return ma_result_from_HRESULT(hr);
9488  }
9489 
9490  if ((ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) {
9491  *pFrameCount = pDevice->wasapi.actualPeriodSizeInFramesPlayback - paddingFramesCount;
9492  } else {
9493  *pFrameCount = paddingFramesCount;
9494  }
9495  } else {
9496  /* Exclusive mode. */
9497  if ((ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) {
9498  *pFrameCount = pDevice->wasapi.actualPeriodSizeInFramesPlayback;
9499  } else {
9500  *pFrameCount = pDevice->wasapi.actualPeriodSizeInFramesCapture;
9501  }
9502  }
9503 
9504  return MA_SUCCESS;
9505 }
9506 
9507 
9508 static ma_result ma_device_reroute__wasapi(ma_device* pDevice, ma_device_type deviceType)
9509 {
9510  ma_result result;
9511 
9512  if (deviceType == ma_device_type_duplex) {
9513  return MA_INVALID_ARGS;
9514  }
9515 
9516  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "=== CHANGING DEVICE ===\n");
9517 
9518  result = ma_device_reinit__wasapi(pDevice, deviceType);
9519  if (result != MA_SUCCESS) {
9520  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Reinitializing device after route change failed.\n");
9521  return result;
9522  }
9523 
9524  ma_device__post_init_setup(pDevice, deviceType);
9525 
9526  return MA_SUCCESS;
9527 }
9528 
9529 static ma_result ma_device_start__wasapi(ma_device* pDevice)
9530 {
9531  HRESULT hr;
9532 
9533  MA_ASSERT(pDevice != NULL);
9534 
9535  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
9536  hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9537  if (FAILED(hr)) {
9538  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device.", ma_result_from_HRESULT(hr));
9539  }
9540 
9541  c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_TRUE);
9542  }
9543 
9544  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
9545  /* No need to do anything for playback as that'll be started automatically in the data loop. */
9546  }
9547 
9548  return MA_SUCCESS;
9549 }
9550 
9551 static ma_result ma_device_stop__wasapi(ma_device* pDevice)
9552 {
9553  ma_result result;
9554  HRESULT hr;
9555 
9556  MA_ASSERT(pDevice != NULL);
9557 
9558  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
9559  hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9560  if (FAILED(hr)) {
9561  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal capture device.", ma_result_from_HRESULT(hr));
9562  }
9563 
9564  /* The audio client needs to be reset otherwise restarting will fail. */
9565  hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9566  if (FAILED(hr)) {
9567  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to reset internal capture device.", ma_result_from_HRESULT(hr));
9568  }
9569 
9570  c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_FALSE);
9571  }
9572 
9573  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
9574  /*
9575  The buffer needs to be drained before stopping the device. Not doing this will result in the last few frames not getting output to
9576  the speakers. This is a problem for very short sounds because it'll result in a significant portion of it not getting played.
9577  */
9578  if (c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) {
9579  /* We need to make sure we put a timeout here or else we'll risk getting stuck in a deadlock in some cases. */
9580  DWORD waitTime = pDevice->wasapi.actualPeriodSizeInFramesPlayback / pDevice->playback.internalSampleRate;
9581 
9582  if (pDevice->playback.shareMode == ma_share_mode_exclusive) {
9583  WaitForSingleObject(pDevice->wasapi.hEventPlayback, waitTime);
9584  } else {
9585  ma_uint32 prevFramesAvaialablePlayback = (ma_uint32)-1;
9586  ma_uint32 framesAvailablePlayback;
9587  for (;;) {
9588  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
9589  if (result != MA_SUCCESS) {
9590  break;
9591  }
9592 
9593  if (framesAvailablePlayback >= pDevice->wasapi.actualPeriodSizeInFramesPlayback) {
9594  break;
9595  }
9596 
9597  /*
9598  Just a safety check to avoid an infinite loop. If this iteration results in a situation where the number of available frames
9599  has not changed, get out of the loop. I don't think this should ever happen, but I think it's nice to have just in case.
9600  */
9601  if (framesAvailablePlayback == prevFramesAvaialablePlayback) {
9602  break;
9603  }
9604  prevFramesAvaialablePlayback = framesAvailablePlayback;
9605 
9606  WaitForSingleObject(pDevice->wasapi.hEventPlayback, waitTime);
9607  ResetEvent(pDevice->wasapi.hEventPlayback); /* Manual reset. */
9608  }
9609  }
9610  }
9611 
9612  hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9613  if (FAILED(hr)) {
9614  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal playback device.", ma_result_from_HRESULT(hr));
9615  }
9616 
9617  /* The audio client needs to be reset otherwise restarting will fail. */
9618  hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9619  if (FAILED(hr)) {
9620  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to reset internal playback device.", ma_result_from_HRESULT(hr));
9621  }
9622 
9623  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_FALSE);
9624  }
9625 
9626  return MA_SUCCESS;
9627 }
9628 
9629 
9630 #ifndef MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS
9631 #define MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS 5000
9632 #endif
9633 
9634 static ma_result ma_device_data_loop__wasapi(ma_device* pDevice)
9635 {
9636  ma_result result;
9637  HRESULT hr;
9638  ma_bool32 exitLoop = MA_FALSE;
9639  ma_uint32 framesWrittenToPlaybackDevice = 0;
9640  ma_uint32 mappedDeviceBufferSizeInFramesCapture = 0;
9641  ma_uint32 mappedDeviceBufferSizeInFramesPlayback = 0;
9642  ma_uint32 mappedDeviceBufferFramesRemainingCapture = 0;
9643  ma_uint32 mappedDeviceBufferFramesRemainingPlayback = 0;
9644  BYTE* pMappedDeviceBufferCapture = NULL;
9645  BYTE* pMappedDeviceBufferPlayback = NULL;
9646  ma_uint32 bpfCaptureDevice = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
9647  ma_uint32 bpfPlaybackDevice = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
9648  ma_uint32 bpfCaptureClient = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
9649  ma_uint32 bpfPlaybackClient = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
9650  ma_uint8 inputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
9651  ma_uint32 inputDataInClientFormatCap = 0;
9652  ma_uint8 outputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
9653  ma_uint32 outputDataInClientFormatCap = 0;
9654  ma_uint32 outputDataInClientFormatCount = 0;
9655  ma_uint32 outputDataInClientFormatConsumed = 0;
9656  ma_uint32 periodSizeInFramesCapture = 0;
9657 
9658  MA_ASSERT(pDevice != NULL);
9659 
9660  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
9661  periodSizeInFramesCapture = pDevice->capture.internalPeriodSizeInFrames;
9662  inputDataInClientFormatCap = sizeof(inputDataInClientFormat) / bpfCaptureClient;
9663  }
9664 
9665  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
9666  outputDataInClientFormatCap = sizeof(outputDataInClientFormat) / bpfPlaybackClient;
9667  }
9668 
9669  while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
9670  switch (pDevice->type)
9671  {
9672  case ma_device_type_duplex:
9673  {
9674  ma_uint32 framesAvailableCapture;
9675  ma_uint32 framesAvailablePlayback;
9676  DWORD flagsCapture; /* Passed to IAudioCaptureClient_GetBuffer(). */
9677 
9678  /* The process is to map the playback buffer and fill it as quickly as possible from input data. */
9679  if (pMappedDeviceBufferPlayback == NULL) {
9680  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
9681  if (result != MA_SUCCESS) {
9682  return result;
9683  }
9684 
9685  /* In exclusive mode, the frame count needs to exactly match the value returned by GetCurrentPadding(). */
9686  if (pDevice->playback.shareMode != ma_share_mode_exclusive) {
9687  if (framesAvailablePlayback > pDevice->wasapi.periodSizeInFramesPlayback) {
9688  framesAvailablePlayback = pDevice->wasapi.periodSizeInFramesPlayback;
9689  }
9690  }
9691 
9692  /* We're ready to map the playback device's buffer. We don't release this until it's been entirely filled. */
9693  hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedDeviceBufferPlayback);
9694  if (FAILED(hr)) {
9695  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from playback device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
9696  exitLoop = MA_TRUE;
9697  break;
9698  }
9699 
9700  mappedDeviceBufferSizeInFramesPlayback = framesAvailablePlayback;
9701  mappedDeviceBufferFramesRemainingPlayback = framesAvailablePlayback;
9702  }
9703 
9704  if (mappedDeviceBufferFramesRemainingPlayback > 0) {
9705  /* At this point we should have a buffer available for output. We need to keep writing input samples to it. */
9706  for (;;) {
9707  /* Try grabbing some captured data if we haven't already got a mapped buffer. */
9708  if (pMappedDeviceBufferCapture == NULL) {
9709  if (pDevice->capture.shareMode == ma_share_mode_shared) {
9710  if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
9711  return MA_ERROR; /* Wait failed. */
9712  }
9713  }
9714 
9715  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
9716  if (result != MA_SUCCESS) {
9717  exitLoop = MA_TRUE;
9718  break;
9719  }
9720 
9721  /* Wait for more if nothing is available. */
9722  if (framesAvailableCapture == 0) {
9723  /* In exclusive mode we waited at the top. */
9724  if (pDevice->capture.shareMode != ma_share_mode_shared) {
9725  if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
9726  return MA_ERROR; /* Wait failed. */
9727  }
9728  }
9729 
9730  continue;
9731  }
9732 
9733  /* Getting here means there's data available for writing to the output device. */
9734  mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
9735  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
9736  if (FAILED(hr)) {
9737  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
9738  exitLoop = MA_TRUE;
9739  break;
9740  }
9741 
9742 
9743  /* Overrun detection. */
9744  if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) != 0) {
9745  /* Glitched. Probably due to an overrun. */
9746  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Data discontinuity (possible overrun). framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
9747 
9748  /*
9749  Exeriment: If we get an overrun it probably means we're straddling the end of the buffer. In order to prevent a never-ending sequence of glitches let's experiment
9750  by dropping every frame until we're left with only a single period. To do this we just keep retrieving and immediately releasing buffers until we're down to the
9751  last period.
9752  */
9753  if (framesAvailableCapture >= pDevice->wasapi.actualPeriodSizeInFramesCapture) {
9754  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Synchronizing capture stream. ");
9755  do
9756  {
9757  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
9758  if (FAILED(hr)) {
9759  break;
9760  }
9761 
9762  framesAvailableCapture -= mappedDeviceBufferSizeInFramesCapture;
9763 
9764  if (framesAvailableCapture > 0) {
9765  mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
9766  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
9767  if (FAILED(hr)) {
9768  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
9769  exitLoop = MA_TRUE;
9770  break;
9771  }
9772  } else {
9773  pMappedDeviceBufferCapture = NULL;
9774  mappedDeviceBufferSizeInFramesCapture = 0;
9775  }
9776  } while (framesAvailableCapture > periodSizeInFramesCapture);
9777  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
9778  }
9779  } else {
9780  #ifdef MA_DEBUG_OUTPUT
9781  if (flagsCapture != 0) {
9782  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Capture Flags: %ld\n", flagsCapture);
9783  }
9784  #endif
9785  }
9786 
9787  mappedDeviceBufferFramesRemainingCapture = mappedDeviceBufferSizeInFramesCapture;
9788  }
9789 
9790 
9791  /* At this point we should have both input and output data available. We now need to convert the data and post it to the client. */
9792  for (;;) {
9793  BYTE* pRunningDeviceBufferCapture;
9794  BYTE* pRunningDeviceBufferPlayback;
9795  ma_uint32 framesToProcess;
9796  ma_uint32 framesProcessed;
9797 
9798  pRunningDeviceBufferCapture = pMappedDeviceBufferCapture + ((mappedDeviceBufferSizeInFramesCapture - mappedDeviceBufferFramesRemainingCapture ) * bpfCaptureDevice);
9799  pRunningDeviceBufferPlayback = pMappedDeviceBufferPlayback + ((mappedDeviceBufferSizeInFramesPlayback - mappedDeviceBufferFramesRemainingPlayback) * bpfPlaybackDevice);
9800 
9801  /* There may be some data sitting in the converter that needs to be processed first. Once this is exhaused, run the data callback again. */
9802  if (!pDevice->playback.converter.isPassthrough && outputDataInClientFormatConsumed < outputDataInClientFormatCount) {
9803  ma_uint64 convertedFrameCountClient = (outputDataInClientFormatCount - outputDataInClientFormatConsumed);
9804  ma_uint64 convertedFrameCountDevice = mappedDeviceBufferFramesRemainingPlayback;
9805  void* pConvertedFramesClient = outputDataInClientFormat + (outputDataInClientFormatConsumed * bpfPlaybackClient);
9806  void* pConvertedFramesDevice = pRunningDeviceBufferPlayback;
9807  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pConvertedFramesClient, &convertedFrameCountClient, pConvertedFramesDevice, &convertedFrameCountDevice);
9808  if (result != MA_SUCCESS) {
9809  break;
9810  }
9811 
9812  outputDataInClientFormatConsumed += (ma_uint32)convertedFrameCountClient; /* Safe cast. */
9813  mappedDeviceBufferFramesRemainingPlayback -= (ma_uint32)convertedFrameCountDevice; /* Safe cast. */
9814 
9815  if (mappedDeviceBufferFramesRemainingPlayback == 0) {
9816  break;
9817  }
9818  }
9819 
9820  /*
9821  Getting here means we need to fire the callback. If format conversion is unnecessary, we can optimize this by passing the pointers to the internal
9822  buffers directly to the callback.
9823  */
9824  if (pDevice->capture.converter.isPassthrough && pDevice->playback.converter.isPassthrough) {
9825  /* Optimal path. We can pass mapped pointers directly to the callback. */
9826  framesToProcess = ma_min(mappedDeviceBufferFramesRemainingCapture, mappedDeviceBufferFramesRemainingPlayback);
9827  framesProcessed = framesToProcess;
9828 
9829  ma_device__on_data(pDevice, pRunningDeviceBufferPlayback, pRunningDeviceBufferCapture, framesToProcess);
9830 
9831  mappedDeviceBufferFramesRemainingCapture -= framesProcessed;
9832  mappedDeviceBufferFramesRemainingPlayback -= framesProcessed;
9833 
9834  if (mappedDeviceBufferFramesRemainingCapture == 0) {
9835  break; /* Exhausted input data. */
9836  }
9837  if (mappedDeviceBufferFramesRemainingPlayback == 0) {
9838  break; /* Exhausted output data. */
9839  }
9840  } else if (pDevice->capture.converter.isPassthrough) {
9841  /* The input buffer is a passthrough, but the playback buffer requires a conversion. */
9842  framesToProcess = ma_min(mappedDeviceBufferFramesRemainingCapture, outputDataInClientFormatCap);
9843  framesProcessed = framesToProcess;
9844 
9845  ma_device__on_data(pDevice, outputDataInClientFormat, pRunningDeviceBufferCapture, framesToProcess);
9846  outputDataInClientFormatCount = framesProcessed;
9847  outputDataInClientFormatConsumed = 0;
9848 
9849  mappedDeviceBufferFramesRemainingCapture -= framesProcessed;
9850  if (mappedDeviceBufferFramesRemainingCapture == 0) {
9851  break; /* Exhausted input data. */
9852  }
9853  } else if (pDevice->playback.converter.isPassthrough) {
9854  /* The input buffer requires conversion, the playback buffer is passthrough. */
9855  ma_uint64 capturedDeviceFramesToProcess = mappedDeviceBufferFramesRemainingCapture;
9856  ma_uint64 capturedClientFramesToProcess = ma_min(inputDataInClientFormatCap, mappedDeviceBufferFramesRemainingPlayback);
9857 
9858  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningDeviceBufferCapture, &capturedDeviceFramesToProcess, inputDataInClientFormat, &capturedClientFramesToProcess);
9859  if (result != MA_SUCCESS) {
9860  break;
9861  }
9862 
9863  if (capturedClientFramesToProcess == 0) {
9864  break;
9865  }
9866 
9867  ma_device__on_data(pDevice, pRunningDeviceBufferPlayback, inputDataInClientFormat, (ma_uint32)capturedClientFramesToProcess); /* Safe cast. */
9868 
9869  mappedDeviceBufferFramesRemainingCapture -= (ma_uint32)capturedDeviceFramesToProcess;
9870  mappedDeviceBufferFramesRemainingPlayback -= (ma_uint32)capturedClientFramesToProcess;
9871  } else {
9872  ma_uint64 capturedDeviceFramesToProcess = mappedDeviceBufferFramesRemainingCapture;
9873  ma_uint64 capturedClientFramesToProcess = ma_min(inputDataInClientFormatCap, outputDataInClientFormatCap);
9874 
9875  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningDeviceBufferCapture, &capturedDeviceFramesToProcess, inputDataInClientFormat, &capturedClientFramesToProcess);
9876  if (result != MA_SUCCESS) {
9877  break;
9878  }
9879 
9880  if (capturedClientFramesToProcess == 0) {
9881  break;
9882  }
9883 
9884  ma_device__on_data(pDevice, outputDataInClientFormat, inputDataInClientFormat, (ma_uint32)capturedClientFramesToProcess);
9885 
9886  mappedDeviceBufferFramesRemainingCapture -= (ma_uint32)capturedDeviceFramesToProcess;
9887  outputDataInClientFormatCount = (ma_uint32)capturedClientFramesToProcess;
9888  outputDataInClientFormatConsumed = 0;
9889  }
9890  }
9891 
9892 
9893  /* If at this point we've run out of capture data we need to release the buffer. */
9894  if (mappedDeviceBufferFramesRemainingCapture == 0 && pMappedDeviceBufferCapture != NULL) {
9895  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
9896  if (FAILED(hr)) {
9897  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to release internal buffer from capture device after reading from the device.", ma_result_from_HRESULT(hr));
9898  exitLoop = MA_TRUE;
9899  break;
9900  }
9901 
9902  pMappedDeviceBufferCapture = NULL;
9903  mappedDeviceBufferFramesRemainingCapture = 0;
9904  mappedDeviceBufferSizeInFramesCapture = 0;
9905  }
9906 
9907  /* Get out of this loop if we're run out of room in the playback buffer. */
9908  if (mappedDeviceBufferFramesRemainingPlayback == 0) {
9909  break;
9910  }
9911  }
9912  }
9913 
9914 
9915  /* If at this point we've run out of data we need to release the buffer. */
9916  if (mappedDeviceBufferFramesRemainingPlayback == 0 && pMappedDeviceBufferPlayback != NULL) {
9917  hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedDeviceBufferSizeInFramesPlayback, 0);
9918  if (FAILED(hr)) {
9919  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to release internal buffer from playback device after writing to the device.", ma_result_from_HRESULT(hr));
9920  exitLoop = MA_TRUE;
9921  break;
9922  }
9923 
9924  framesWrittenToPlaybackDevice += mappedDeviceBufferSizeInFramesPlayback;
9925 
9926  pMappedDeviceBufferPlayback = NULL;
9927  mappedDeviceBufferFramesRemainingPlayback = 0;
9928  mappedDeviceBufferSizeInFramesPlayback = 0;
9929  }
9930 
9931  if (!c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) {
9932  ma_uint32 startThreshold = pDevice->playback.internalPeriodSizeInFrames * 1;
9933 
9934  /* Prevent a deadlock. If we don't clamp against the actual buffer size we'll never end up starting the playback device which will result in a deadlock. */
9935  if (startThreshold > pDevice->wasapi.actualPeriodSizeInFramesPlayback) {
9936  startThreshold = pDevice->wasapi.actualPeriodSizeInFramesPlayback;
9937  }
9938 
9939  if (pDevice->playback.shareMode == ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= startThreshold) {
9940  hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9941  if (FAILED(hr)) {
9942  ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9943  ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9944  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.", ma_result_from_HRESULT(hr));
9945  }
9946 
9947  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_TRUE);
9948  }
9949  }
9950 
9951  /* Make sure the device has started before waiting. */
9952  if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
9953  return MA_ERROR; /* Wait failed. */
9954  }
9955  } break;
9956 
9957 
9958 
9961  {
9962  ma_uint32 framesAvailableCapture;
9963  DWORD flagsCapture; /* Passed to IAudioCaptureClient_GetBuffer(). */
9964 
9965  /* Wait for data to become available first. */
9966  if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
9967  /*
9968  For capture we can terminate here because it probably means the microphone just isn't delivering data for whatever reason, but
9969  for loopback is most likely means nothing is actually playing. We want to keep trying in this situation.
9970  */
9971  if (pDevice->type == ma_device_type_loopback) {
9972  continue; /* Keep waiting in loopback mode. */
9973  } else {
9974  exitLoop = MA_TRUE;
9975  break; /* Wait failed. */
9976  }
9977  }
9978 
9979  /* See how many frames are available. Since we waited at the top, I don't think this should ever return 0. I'm checking for this anyway. */
9980  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
9981  if (result != MA_SUCCESS) {
9982  exitLoop = MA_TRUE;
9983  break;
9984  }
9985 
9986  if (framesAvailableCapture < pDevice->wasapi.periodSizeInFramesCapture) {
9987  continue; /* Nothing available. Keep waiting. */
9988  }
9989 
9990  /* Map the data buffer in preparation for sending to the client. */
9991  mappedDeviceBufferSizeInFramesCapture = framesAvailableCapture;
9992  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
9993  if (FAILED(hr)) {
9994  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
9995  exitLoop = MA_TRUE;
9996  break;
9997  }
9998 
9999  /* Overrun detection. */
10000  if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) != 0) {
10001  /* Glitched. Probably due to an overrun. */
10002  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Data discontinuity (possible overrun). framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
10003 
10004  /*
10005  Exeriment: If we get an overrun it probably means we're straddling the end of the buffer. In order to prevent a never-ending sequence of glitches let's experiment
10006  by dropping every frame until we're left with only a single period. To do this we just keep retrieving and immediately releasing buffers until we're down to the
10007  last period.
10008  */
10009  if (framesAvailableCapture >= pDevice->wasapi.actualPeriodSizeInFramesCapture) {
10010  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Synchronizing capture stream. ");
10011  do
10012  {
10013  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
10014  if (FAILED(hr)) {
10015  break;
10016  }
10017 
10018  framesAvailableCapture -= mappedDeviceBufferSizeInFramesCapture;
10019 
10020  if (framesAvailableCapture > 0) {
10021  mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
10022  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
10023  if (FAILED(hr)) {
10024  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
10025  exitLoop = MA_TRUE;
10026  break;
10027  }
10028  } else {
10029  pMappedDeviceBufferCapture = NULL;
10030  mappedDeviceBufferSizeInFramesCapture = 0;
10031  }
10032  } while (framesAvailableCapture > periodSizeInFramesCapture);
10033  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
10034  }
10035  } else {
10036  #ifdef MA_DEBUG_OUTPUT
10037  if (flagsCapture != 0) {
10038  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Capture Flags: %ld\n", flagsCapture);
10039  }
10040  #endif
10041  }
10042 
10043  /* We should have a buffer at this point, but let's just do a sanity check anyway. */
10044  if (mappedDeviceBufferSizeInFramesCapture > 0 && pMappedDeviceBufferCapture != NULL) {
10045  ma_device__send_frames_to_client(pDevice, mappedDeviceBufferSizeInFramesCapture, pMappedDeviceBufferCapture);
10046 
10047  /* At this point we're done with the buffer. */
10048  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
10049  pMappedDeviceBufferCapture = NULL; /* <-- Important. Not doing this can result in an error once we leave this loop because it will use this to know whether or not a final ReleaseBuffer() needs to be called. */
10050  mappedDeviceBufferSizeInFramesCapture = 0;
10051  if (FAILED(hr)) {
10052  ma_post_log_message(ma_device_get_context(pDevice), pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to release internal buffer from capture device after reading from the device.");
10053  exitLoop = MA_TRUE;
10054  break;
10055  }
10056  }
10057  } break;
10058 
10059 
10060 
10062  {
10063  ma_uint32 framesAvailablePlayback;
10064 
10065  /* Check how much space is available. If this returns 0 we just keep waiting. */
10066  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
10067  if (result != MA_SUCCESS) {
10068  exitLoop = MA_TRUE;
10069  break;
10070  }
10071 
10072  if (framesAvailablePlayback >= pDevice->wasapi.periodSizeInFramesPlayback) {
10073  /* Map a the data buffer in preparation for the callback. */
10074  hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedDeviceBufferPlayback);
10075  if (FAILED(hr)) {
10076  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from playback device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
10077  exitLoop = MA_TRUE;
10078  break;
10079  }
10080 
10081  /* We should have a buffer at this point. */
10082  ma_device__read_frames_from_client(pDevice, framesAvailablePlayback, pMappedDeviceBufferPlayback);
10083 
10084  /* At this point we're done writing to the device and we just need to release the buffer. */
10085  hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, 0);
10086  pMappedDeviceBufferPlayback = NULL; /* <-- Important. Not doing this can result in an error once we leave this loop because it will use this to know whether or not a final ReleaseBuffer() needs to be called. */
10087  mappedDeviceBufferSizeInFramesPlayback = 0;
10088 
10089  if (FAILED(hr)) {
10090  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to release internal buffer from playback device after writing to the device.", ma_result_from_HRESULT(hr));
10091  exitLoop = MA_TRUE;
10092  break;
10093  }
10094 
10095  framesWrittenToPlaybackDevice += framesAvailablePlayback;
10096  }
10097 
10098  if (!c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) {
10099  hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
10100  if (FAILED(hr)) {
10101  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.", ma_result_from_HRESULT(hr));
10102  exitLoop = MA_TRUE;
10103  break;
10104  }
10105 
10106  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_TRUE);
10107  }
10108 
10109  /* Make sure we don't wait on the event before we've started the device or we may end up deadlocking. */
10110  if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
10111  exitLoop = MA_TRUE;
10112  break; /* Wait failed. Probably timed out. */
10113  }
10114  } break;
10115 
10116  default: return MA_INVALID_ARGS;
10117  }
10118  }
10119 
10120  /* Here is where the device needs to be stopped. */
10121  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
10122  /* Any mapped buffers need to be released. */
10123  if (pMappedDeviceBufferCapture != NULL) {
10124  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
10125  }
10126  }
10127 
10128  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
10129  /* Any mapped buffers need to be released. */
10130  if (pMappedDeviceBufferPlayback != NULL) {
10131  hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedDeviceBufferSizeInFramesPlayback, 0);
10132  }
10133  }
10134 
10135  return MA_SUCCESS;
10136 }
10137 
10138 static ma_result ma_device_data_loop_wakeup__wasapi(ma_device* pDevice)
10139 {
10140  MA_ASSERT(pDevice != NULL);
10141 
10142  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
10143  SetEvent((HANDLE)pDevice->wasapi.hEventCapture);
10144  }
10145 
10146  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
10147  SetEvent((HANDLE)pDevice->wasapi.hEventPlayback);
10148  }
10149 
10150  return MA_SUCCESS;
10151 }
10152 
10153 
10154 static ma_result ma_context_uninit__wasapi(ma_context* pContext)
10155 {
10156  MA_ASSERT(pContext != NULL);
10157  MA_ASSERT(pContext->backend == ma_backend_wasapi);
10158 
10159  if (pContext->wasapi.commandThread != NULL) {
10160  ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_QUIT__WASAPI);
10161  ma_context_post_command__wasapi(pContext, &cmd);
10162  ma_thread_wait(&pContext->wasapi.commandThread);
10163 
10164  /* Only after the thread has been terminated can we uninitialize the sync objects for the command thread. */
10165  ma_semaphore_uninit(&pContext->wasapi.commandSem);
10166  ma_mutex_uninit(&pContext->wasapi.commandLock);
10167  }
10168 
10169  return MA_SUCCESS;
10170 }
10171 
10172 static ma_result ma_context_init__wasapi(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
10173 {
10174  ma_result result = MA_SUCCESS;
10175 
10176  MA_ASSERT(pContext != NULL);
10177 
10178  (void)pConfig;
10179 
10180 #ifdef MA_WIN32_DESKTOP
10181  /*
10182  WASAPI is only supported in Vista SP1 and newer. The reason for SP1 and not the base version of Vista is that event-driven
10183  exclusive mode does not work until SP1.
10184 
10185  Unfortunately older compilers don't define these functions so we need to dynamically load them in order to avoid a link error.
10186  */
10187  {
10188  ma_OSVERSIONINFOEXW osvi;
10189  ma_handle kernel32DLL;
10190  ma_PFNVerifyVersionInfoW _VerifyVersionInfoW;
10191  ma_PFNVerSetConditionMask _VerSetConditionMask;
10192 
10193  kernel32DLL = ma_dlopen(pContext, "kernel32.dll");
10194  if (kernel32DLL == NULL) {
10195  return MA_NO_BACKEND;
10196  }
10197 
10198  _VerifyVersionInfoW = (ma_PFNVerifyVersionInfoW )ma_dlsym(pContext, kernel32DLL, "VerifyVersionInfoW");
10199  _VerSetConditionMask = (ma_PFNVerSetConditionMask)ma_dlsym(pContext, kernel32DLL, "VerSetConditionMask");
10200  if (_VerifyVersionInfoW == NULL || _VerSetConditionMask == NULL) {
10201  ma_dlclose(pContext, kernel32DLL);
10202  return MA_NO_BACKEND;
10203  }
10204 
10205  MA_ZERO_OBJECT(&osvi);
10206  osvi.dwOSVersionInfoSize = sizeof(osvi);
10207  osvi.dwMajorVersion = ((MA_WIN32_WINNT_VISTA >> 8) & 0xFF);
10208  osvi.dwMinorVersion = ((MA_WIN32_WINNT_VISTA >> 0) & 0xFF);
10209  osvi.wServicePackMajor = 1;
10210  if (_VerifyVersionInfoW(&osvi, MA_VER_MAJORVERSION | MA_VER_MINORVERSION | MA_VER_SERVICEPACKMAJOR, _VerSetConditionMask(_VerSetConditionMask(_VerSetConditionMask(0, MA_VER_MAJORVERSION, MA_VER_GREATER_EQUAL), MA_VER_MINORVERSION, MA_VER_GREATER_EQUAL), MA_VER_SERVICEPACKMAJOR, MA_VER_GREATER_EQUAL))) {
10211  result = MA_SUCCESS;
10212  } else {
10213  result = MA_NO_BACKEND;
10214  }
10215 
10216  ma_dlclose(pContext, kernel32DLL);
10217  }
10218 #endif
10219 
10220  if (result != MA_SUCCESS) {
10221  return result;
10222  }
10223 
10224  MA_ZERO_OBJECT(&pContext->wasapi);
10225 
10226  /*
10227  Annoyingly, WASAPI does not allow you to release an IAudioClient object from a different thread
10228  than the one that retrieved it with GetService(). This can result in a deadlock in two
10229  situations:
10230 
10231  1) When calling ma_device_uninit() from a different thread to ma_device_init(); and
10232  2) When uninitializing and reinitializing the internal IAudioClient object in response to
10233  automatic stream routing.
10234 
10235  We could define ma_device_uninit() such that it must be called on the same thread as
10236  ma_device_init(). We could also just not release the IAudioClient when performing automatic
10237  stream routing to avoid the deadlock. Neither of these are acceptable solutions in my view so
10238  we're going to have to work around this with a worker thread. This is not ideal, but I can't
10239  think of a better way to do this.
10240 
10241  More information about this can be found here:
10242 
10243  https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudiorenderclient
10244 
10245  Note this section:
10246 
10247  When releasing an IAudioRenderClient interface instance, the client must call the interface's
10248  Release method from the same thread as the call to IAudioClient::GetService that created the
10249  object.
10250  */
10251  {
10252  result = ma_mutex_init(&pContext->wasapi.commandLock);
10253  if (result != MA_SUCCESS) {
10254  return result;
10255  }
10256 
10257  result = ma_semaphore_init(0, &pContext->wasapi.commandSem);
10258  if (result != MA_SUCCESS) {
10259  ma_mutex_uninit(&pContext->wasapi.commandLock);
10260  return result;
10261  }
10262 
10263  result = ma_thread_create(&pContext->wasapi.commandThread, ma_thread_priority_normal, 0, ma_context_command_thread__wasapi, pContext, &pContext->allocationCallbacks);
10264  if (result != MA_SUCCESS) {
10265  ma_semaphore_uninit(&pContext->wasapi.commandSem);
10266  ma_mutex_uninit(&pContext->wasapi.commandLock);
10267  return result;
10268  }
10269  }
10270 
10271 
10272  pCallbacks->onContextInit = ma_context_init__wasapi;
10273  pCallbacks->onContextUninit = ma_context_uninit__wasapi;
10274  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__wasapi;
10275  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__wasapi;
10276  pCallbacks->onDeviceInit = ma_device_init__wasapi;
10277  pCallbacks->onDeviceUninit = ma_device_uninit__wasapi;
10278  pCallbacks->onDeviceStart = ma_device_start__wasapi;
10279  pCallbacks->onDeviceStop = ma_device_stop__wasapi;
10280  pCallbacks->onDeviceRead = NULL; /* Not used. Reading is done manually in the audio thread. */
10281  pCallbacks->onDeviceWrite = NULL; /* Not used. Writing is done manually in the audio thread. */
10282  pCallbacks->onDeviceDataLoop = ma_device_data_loop__wasapi;
10283  pCallbacks->onDeviceDataLoopWakeup = ma_device_data_loop_wakeup__wasapi;
10284 
10285  return MA_SUCCESS;
10286 }
10287 #endif
10288 
10289 /******************************************************************************
10290 
10291 DirectSound Backend
10292 
10293 ******************************************************************************/
10294 #ifdef MA_HAS_DSOUND
10295 /*#include <dsound.h>*/
10296 
10297 /*static const GUID MA_GUID_IID_DirectSoundNotify = {0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16}};*/
10298 
10299 /* miniaudio only uses priority or exclusive modes. */
10300 #define MA_DSSCL_NORMAL 1
10301 #define MA_DSSCL_PRIORITY 2
10302 #define MA_DSSCL_EXCLUSIVE 3
10303 #define MA_DSSCL_WRITEPRIMARY 4
10304 
10305 #define MA_DSCAPS_PRIMARYMONO 0x00000001
10306 #define MA_DSCAPS_PRIMARYSTEREO 0x00000002
10307 #define MA_DSCAPS_PRIMARY8BIT 0x00000004
10308 #define MA_DSCAPS_PRIMARY16BIT 0x00000008
10309 #define MA_DSCAPS_CONTINUOUSRATE 0x00000010
10310 #define MA_DSCAPS_EMULDRIVER 0x00000020
10311 #define MA_DSCAPS_CERTIFIED 0x00000040
10312 #define MA_DSCAPS_SECONDARYMONO 0x00000100
10313 #define MA_DSCAPS_SECONDARYSTEREO 0x00000200
10314 #define MA_DSCAPS_SECONDARY8BIT 0x00000400
10315 #define MA_DSCAPS_SECONDARY16BIT 0x00000800
10316 
10317 #define MA_DSBCAPS_PRIMARYBUFFER 0x00000001
10318 #define MA_DSBCAPS_STATIC 0x00000002
10319 #define MA_DSBCAPS_LOCHARDWARE 0x00000004
10320 #define MA_DSBCAPS_LOCSOFTWARE 0x00000008
10321 #define MA_DSBCAPS_CTRL3D 0x00000010
10322 #define MA_DSBCAPS_CTRLFREQUENCY 0x00000020
10323 #define MA_DSBCAPS_CTRLPAN 0x00000040
10324 #define MA_DSBCAPS_CTRLVOLUME 0x00000080
10325 #define MA_DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100
10326 #define MA_DSBCAPS_CTRLFX 0x00000200
10327 #define MA_DSBCAPS_STICKYFOCUS 0x00004000
10328 #define MA_DSBCAPS_GLOBALFOCUS 0x00008000
10329 #define MA_DSBCAPS_GETCURRENTPOSITION2 0x00010000
10330 #define MA_DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000
10331 #define MA_DSBCAPS_LOCDEFER 0x00040000
10332 #define MA_DSBCAPS_TRUEPLAYPOSITION 0x00080000
10333 
10334 #define MA_DSBPLAY_LOOPING 0x00000001
10335 #define MA_DSBPLAY_LOCHARDWARE 0x00000002
10336 #define MA_DSBPLAY_LOCSOFTWARE 0x00000004
10337 #define MA_DSBPLAY_TERMINATEBY_TIME 0x00000008
10338 #define MA_DSBPLAY_TERMINATEBY_DISTANCE 0x00000010
10339 #define MA_DSBPLAY_TERMINATEBY_PRIORITY 0x00000020
10340 
10341 #define MA_DSCBSTART_LOOPING 0x00000001
10342 
10343 typedef struct
10344 {
10345  DWORD dwSize;
10346  DWORD dwFlags;
10347  DWORD dwBufferBytes;
10348  DWORD dwReserved;
10349  WAVEFORMATEX* lpwfxFormat;
10350  GUID guid3DAlgorithm;
10351 } MA_DSBUFFERDESC;
10352 
10353 typedef struct
10354 {
10355  DWORD dwSize;
10356  DWORD dwFlags;
10357  DWORD dwBufferBytes;
10358  DWORD dwReserved;
10359  WAVEFORMATEX* lpwfxFormat;
10360  DWORD dwFXCount;
10361  void* lpDSCFXDesc; /* <-- miniaudio doesn't use this, so set to void*. */
10362 } MA_DSCBUFFERDESC;
10363 
10364 typedef struct
10365 {
10366  DWORD dwSize;
10367  DWORD dwFlags;
10368  DWORD dwMinSecondarySampleRate;
10369  DWORD dwMaxSecondarySampleRate;
10370  DWORD dwPrimaryBuffers;
10371  DWORD dwMaxHwMixingAllBuffers;
10372  DWORD dwMaxHwMixingStaticBuffers;
10373  DWORD dwMaxHwMixingStreamingBuffers;
10374  DWORD dwFreeHwMixingAllBuffers;
10375  DWORD dwFreeHwMixingStaticBuffers;
10376  DWORD dwFreeHwMixingStreamingBuffers;
10377  DWORD dwMaxHw3DAllBuffers;
10378  DWORD dwMaxHw3DStaticBuffers;
10379  DWORD dwMaxHw3DStreamingBuffers;
10380  DWORD dwFreeHw3DAllBuffers;
10381  DWORD dwFreeHw3DStaticBuffers;
10382  DWORD dwFreeHw3DStreamingBuffers;
10383  DWORD dwTotalHwMemBytes;
10384  DWORD dwFreeHwMemBytes;
10385  DWORD dwMaxContigFreeHwMemBytes;
10386  DWORD dwUnlockTransferRateHwBuffers;
10387  DWORD dwPlayCpuOverheadSwBuffers;
10388  DWORD dwReserved1;
10389  DWORD dwReserved2;
10390 } MA_DSCAPS;
10391 
10392 typedef struct
10393 {
10394  DWORD dwSize;
10395  DWORD dwFlags;
10396  DWORD dwBufferBytes;
10397  DWORD dwUnlockTransferRate;
10398  DWORD dwPlayCpuOverhead;
10399 } MA_DSBCAPS;
10400 
10401 typedef struct
10402 {
10403  DWORD dwSize;
10404  DWORD dwFlags;
10405  DWORD dwFormats;
10406  DWORD dwChannels;
10407 } MA_DSCCAPS;
10408 
10409 typedef struct
10410 {
10411  DWORD dwSize;
10412  DWORD dwFlags;
10413  DWORD dwBufferBytes;
10414  DWORD dwReserved;
10415 } MA_DSCBCAPS;
10416 
10417 typedef struct
10418 {
10419  DWORD dwOffset;
10420  HANDLE hEventNotify;
10421 } MA_DSBPOSITIONNOTIFY;
10422 
10423 typedef struct ma_IDirectSound ma_IDirectSound;
10424 typedef struct ma_IDirectSoundBuffer ma_IDirectSoundBuffer;
10425 typedef struct ma_IDirectSoundCapture ma_IDirectSoundCapture;
10426 typedef struct ma_IDirectSoundCaptureBuffer ma_IDirectSoundCaptureBuffer;
10427 typedef struct ma_IDirectSoundNotify ma_IDirectSoundNotify;
10428 
10429 
10430 /*
10431 COM objects. The way these work is that you have a vtable (a list of function pointers, kind of
10432 like how C++ works internally), and then you have a structure with a single member, which is a
10433 pointer to the vtable. The vtable is where the methods of the object are defined. Methods need
10434 to be in a specific order, and parent classes need to have their methods declared first.
10435 */
10436 
10437 /* IDirectSound */
10438 typedef struct
10439 {
10440  /* IUnknown */
10441  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSound* pThis, const IID* const riid, void** ppObject);
10442  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSound* pThis);
10443  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSound* pThis);
10444 
10445  /* IDirectSound */
10446  HRESULT (STDMETHODCALLTYPE * CreateSoundBuffer) (ma_IDirectSound* pThis, const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer, void* pUnkOuter);
10447  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps);
10448  HRESULT (STDMETHODCALLTYPE * DuplicateSoundBuffer)(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate);
10449  HRESULT (STDMETHODCALLTYPE * SetCooperativeLevel) (ma_IDirectSound* pThis, HWND hwnd, DWORD dwLevel);
10450  HRESULT (STDMETHODCALLTYPE * Compact) (ma_IDirectSound* pThis);
10451  HRESULT (STDMETHODCALLTYPE * GetSpeakerConfig) (ma_IDirectSound* pThis, DWORD* pSpeakerConfig);
10452  HRESULT (STDMETHODCALLTYPE * SetSpeakerConfig) (ma_IDirectSound* pThis, DWORD dwSpeakerConfig);
10453  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSound* pThis, const GUID* pGuidDevice);
10454 } ma_IDirectSoundVtbl;
10455 struct ma_IDirectSound
10456 {
10457  ma_IDirectSoundVtbl* lpVtbl;
10458 };
10459 static MA_INLINE HRESULT ma_IDirectSound_QueryInterface(ma_IDirectSound* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10460 static MA_INLINE ULONG ma_IDirectSound_AddRef(ma_IDirectSound* pThis) { return pThis->lpVtbl->AddRef(pThis); }
10461 static MA_INLINE ULONG ma_IDirectSound_Release(ma_IDirectSound* pThis) { return pThis->lpVtbl->Release(pThis); }
10462 static MA_INLINE HRESULT ma_IDirectSound_CreateSoundBuffer(ma_IDirectSound* pThis, const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer, void* pUnkOuter) { return pThis->lpVtbl->CreateSoundBuffer(pThis, pDSBufferDesc, ppDSBuffer, pUnkOuter); }
10463 static MA_INLINE HRESULT ma_IDirectSound_GetCaps(ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSCaps); }
10464 static MA_INLINE HRESULT ma_IDirectSound_DuplicateSoundBuffer(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate) { return pThis->lpVtbl->DuplicateSoundBuffer(pThis, pDSBufferOriginal, ppDSBufferDuplicate); }
10465 static MA_INLINE HRESULT ma_IDirectSound_SetCooperativeLevel(ma_IDirectSound* pThis, HWND hwnd, DWORD dwLevel) { return pThis->lpVtbl->SetCooperativeLevel(pThis, hwnd, dwLevel); }
10466 static MA_INLINE HRESULT ma_IDirectSound_Compact(ma_IDirectSound* pThis) { return pThis->lpVtbl->Compact(pThis); }
10467 static MA_INLINE HRESULT ma_IDirectSound_GetSpeakerConfig(ma_IDirectSound* pThis, DWORD* pSpeakerConfig) { return pThis->lpVtbl->GetSpeakerConfig(pThis, pSpeakerConfig); }
10468 static MA_INLINE HRESULT ma_IDirectSound_SetSpeakerConfig(ma_IDirectSound* pThis, DWORD dwSpeakerConfig) { return pThis->lpVtbl->SetSpeakerConfig(pThis, dwSpeakerConfig); }
10469 static MA_INLINE HRESULT ma_IDirectSound_Initialize(ma_IDirectSound* pThis, const GUID* pGuidDevice) { return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
10470 
10471 
10472 /* IDirectSoundBuffer */
10473 typedef struct
10474 {
10475  /* IUnknown */
10476  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundBuffer* pThis, const IID* const riid, void** ppObject);
10477  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundBuffer* pThis);
10478  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundBuffer* pThis);
10479 
10480  /* IDirectSoundBuffer */
10481  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps);
10482  HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundBuffer* pThis, DWORD* pCurrentPlayCursor, DWORD* pCurrentWriteCursor);
10483  HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten);
10484  HRESULT (STDMETHODCALLTYPE * GetVolume) (ma_IDirectSoundBuffer* pThis, LONG* pVolume);
10485  HRESULT (STDMETHODCALLTYPE * GetPan) (ma_IDirectSoundBuffer* pThis, LONG* pPan);
10486  HRESULT (STDMETHODCALLTYPE * GetFrequency) (ma_IDirectSoundBuffer* pThis, DWORD* pFrequency);
10487  HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundBuffer* pThis, DWORD* pStatus);
10488  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound, const MA_DSBUFFERDESC* pDSBufferDesc);
10489  HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundBuffer* pThis, DWORD dwOffset, DWORD dwBytes, void** ppAudioPtr1, DWORD* pAudioBytes1, void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags);
10490  HRESULT (STDMETHODCALLTYPE * Play) (ma_IDirectSoundBuffer* pThis, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags);
10491  HRESULT (STDMETHODCALLTYPE * SetCurrentPosition)(ma_IDirectSoundBuffer* pThis, DWORD dwNewPosition);
10492  HRESULT (STDMETHODCALLTYPE * SetFormat) (ma_IDirectSoundBuffer* pThis, const WAVEFORMATEX* pFormat);
10493  HRESULT (STDMETHODCALLTYPE * SetVolume) (ma_IDirectSoundBuffer* pThis, LONG volume);
10494  HRESULT (STDMETHODCALLTYPE * SetPan) (ma_IDirectSoundBuffer* pThis, LONG pan);
10495  HRESULT (STDMETHODCALLTYPE * SetFrequency) (ma_IDirectSoundBuffer* pThis, DWORD dwFrequency);
10496  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundBuffer* pThis);
10497  HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundBuffer* pThis, void* pAudioPtr1, DWORD dwAudioBytes1, void* pAudioPtr2, DWORD dwAudioBytes2);
10498  HRESULT (STDMETHODCALLTYPE * Restore) (ma_IDirectSoundBuffer* pThis);
10499 } ma_IDirectSoundBufferVtbl;
10500 struct ma_IDirectSoundBuffer
10501 {
10502  ma_IDirectSoundBufferVtbl* lpVtbl;
10503 };
10504 static MA_INLINE HRESULT ma_IDirectSoundBuffer_QueryInterface(ma_IDirectSoundBuffer* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10505 static MA_INLINE ULONG ma_IDirectSoundBuffer_AddRef(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->AddRef(pThis); }
10506 static MA_INLINE ULONG ma_IDirectSoundBuffer_Release(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->Release(pThis); }
10507 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetCaps(ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSBufferCaps); }
10508 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetCurrentPosition(ma_IDirectSoundBuffer* pThis, DWORD* pCurrentPlayCursor, DWORD* pCurrentWriteCursor) { return pThis->lpVtbl->GetCurrentPosition(pThis, pCurrentPlayCursor, pCurrentWriteCursor); }
10509 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetFormat(ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten) { return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
10510 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetVolume(ma_IDirectSoundBuffer* pThis, LONG* pVolume) { return pThis->lpVtbl->GetVolume(pThis, pVolume); }
10511 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetPan(ma_IDirectSoundBuffer* pThis, LONG* pPan) { return pThis->lpVtbl->GetPan(pThis, pPan); }
10512 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetFrequency(ma_IDirectSoundBuffer* pThis, DWORD* pFrequency) { return pThis->lpVtbl->GetFrequency(pThis, pFrequency); }
10513 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetStatus(ma_IDirectSoundBuffer* pThis, DWORD* pStatus) { return pThis->lpVtbl->GetStatus(pThis, pStatus); }
10514 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Initialize(ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound, const MA_DSBUFFERDESC* pDSBufferDesc) { return pThis->lpVtbl->Initialize(pThis, pDirectSound, pDSBufferDesc); }
10515 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Lock(ma_IDirectSoundBuffer* pThis, DWORD dwOffset, DWORD dwBytes, void** ppAudioPtr1, DWORD* pAudioBytes1, void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags) { return pThis->lpVtbl->Lock(pThis, dwOffset, dwBytes, ppAudioPtr1, pAudioBytes1, ppAudioPtr2, pAudioBytes2, dwFlags); }
10516 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Play(ma_IDirectSoundBuffer* pThis, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) { return pThis->lpVtbl->Play(pThis, dwReserved1, dwPriority, dwFlags); }
10517 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetCurrentPosition(ma_IDirectSoundBuffer* pThis, DWORD dwNewPosition) { return pThis->lpVtbl->SetCurrentPosition(pThis, dwNewPosition); }
10518 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetFormat(ma_IDirectSoundBuffer* pThis, const WAVEFORMATEX* pFormat) { return pThis->lpVtbl->SetFormat(pThis, pFormat); }
10519 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetVolume(ma_IDirectSoundBuffer* pThis, LONG volume) { return pThis->lpVtbl->SetVolume(pThis, volume); }
10520 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetPan(ma_IDirectSoundBuffer* pThis, LONG pan) { return pThis->lpVtbl->SetPan(pThis, pan); }
10521 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetFrequency(ma_IDirectSoundBuffer* pThis, DWORD dwFrequency) { return pThis->lpVtbl->SetFrequency(pThis, dwFrequency); }
10522 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Stop(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->Stop(pThis); }
10523 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Unlock(ma_IDirectSoundBuffer* pThis, void* pAudioPtr1, DWORD dwAudioBytes1, void* pAudioPtr2, DWORD dwAudioBytes2) { return pThis->lpVtbl->Unlock(pThis, pAudioPtr1, dwAudioBytes1, pAudioPtr2, dwAudioBytes2); }
10524 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Restore(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->Restore(pThis); }
10525 
10526 
10527 /* IDirectSoundCapture */
10528 typedef struct
10529 {
10530  /* IUnknown */
10531  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCapture* pThis, const IID* const riid, void** ppObject);
10532  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCapture* pThis);
10533  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCapture* pThis);
10534 
10535  /* IDirectSoundCapture */
10536  HRESULT (STDMETHODCALLTYPE * CreateCaptureBuffer)(ma_IDirectSoundCapture* pThis, const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer, void* pUnkOuter);
10537  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps);
10538  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCapture* pThis, const GUID* pGuidDevice);
10539 } ma_IDirectSoundCaptureVtbl;
10540 struct ma_IDirectSoundCapture
10541 {
10542  ma_IDirectSoundCaptureVtbl* lpVtbl;
10543 };
10544 static MA_INLINE HRESULT ma_IDirectSoundCapture_QueryInterface(ma_IDirectSoundCapture* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10545 static MA_INLINE ULONG ma_IDirectSoundCapture_AddRef(ma_IDirectSoundCapture* pThis) { return pThis->lpVtbl->AddRef(pThis); }
10546 static MA_INLINE ULONG ma_IDirectSoundCapture_Release(ma_IDirectSoundCapture* pThis) { return pThis->lpVtbl->Release(pThis); }
10547 static MA_INLINE HRESULT ma_IDirectSoundCapture_CreateCaptureBuffer(ma_IDirectSoundCapture* pThis, const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer, void* pUnkOuter) { return pThis->lpVtbl->CreateCaptureBuffer(pThis, pDSCBufferDesc, ppDSCBuffer, pUnkOuter); }
10548 static MA_INLINE HRESULT ma_IDirectSoundCapture_GetCaps (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSCCaps); }
10549 static MA_INLINE HRESULT ma_IDirectSoundCapture_Initialize (ma_IDirectSoundCapture* pThis, const GUID* pGuidDevice) { return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
10550 
10551 
10552 /* IDirectSoundCaptureBuffer */
10553 typedef struct
10554 {
10555  /* IUnknown */
10556  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCaptureBuffer* pThis, const IID* const riid, void** ppObject);
10557  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCaptureBuffer* pThis);
10558  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCaptureBuffer* pThis);
10559 
10560  /* IDirectSoundCaptureBuffer */
10561  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps);
10562  HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pCapturePosition, DWORD* pReadPosition);
10563  HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten);
10564  HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundCaptureBuffer* pThis, DWORD* pStatus);
10565  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture, const MA_DSCBUFFERDESC* pDSCBufferDesc);
10566  HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundCaptureBuffer* pThis, DWORD dwOffset, DWORD dwBytes, void** ppAudioPtr1, DWORD* pAudioBytes1, void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags);
10567  HRESULT (STDMETHODCALLTYPE * Start) (ma_IDirectSoundCaptureBuffer* pThis, DWORD dwFlags);
10568  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundCaptureBuffer* pThis);
10569  HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundCaptureBuffer* pThis, void* pAudioPtr1, DWORD dwAudioBytes1, void* pAudioPtr2, DWORD dwAudioBytes2);
10570 } ma_IDirectSoundCaptureBufferVtbl;
10571 struct ma_IDirectSoundCaptureBuffer
10572 {
10573  ma_IDirectSoundCaptureBufferVtbl* lpVtbl;
10574 };
10575 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_QueryInterface(ma_IDirectSoundCaptureBuffer* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10576 static MA_INLINE ULONG ma_IDirectSoundCaptureBuffer_AddRef(ma_IDirectSoundCaptureBuffer* pThis) { return pThis->lpVtbl->AddRef(pThis); }
10577 static MA_INLINE ULONG ma_IDirectSoundCaptureBuffer_Release(ma_IDirectSoundCaptureBuffer* pThis) { return pThis->lpVtbl->Release(pThis); }
10578 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetCaps(ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSCBCaps); }
10579 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetCurrentPosition(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pCapturePosition, DWORD* pReadPosition) { return pThis->lpVtbl->GetCurrentPosition(pThis, pCapturePosition, pReadPosition); }
10580 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetFormat(ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten) { return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
10581 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetStatus(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pStatus) { return pThis->lpVtbl->GetStatus(pThis, pStatus); }
10582 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Initialize(ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture, const MA_DSCBUFFERDESC* pDSCBufferDesc) { return pThis->lpVtbl->Initialize(pThis, pDirectSoundCapture, pDSCBufferDesc); }
10583 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Lock(ma_IDirectSoundCaptureBuffer* pThis, DWORD dwOffset, DWORD dwBytes, void** ppAudioPtr1, DWORD* pAudioBytes1, void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags) { return pThis->lpVtbl->Lock(pThis, dwOffset, dwBytes, ppAudioPtr1, pAudioBytes1, ppAudioPtr2, pAudioBytes2, dwFlags); }
10584 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Start(ma_IDirectSoundCaptureBuffer* pThis, DWORD dwFlags) { return pThis->lpVtbl->Start(pThis, dwFlags); }
10585 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Stop(ma_IDirectSoundCaptureBuffer* pThis) { return pThis->lpVtbl->Stop(pThis); }
10586 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Unlock(ma_IDirectSoundCaptureBuffer* pThis, void* pAudioPtr1, DWORD dwAudioBytes1, void* pAudioPtr2, DWORD dwAudioBytes2) { return pThis->lpVtbl->Unlock(pThis, pAudioPtr1, dwAudioBytes1, pAudioPtr2, dwAudioBytes2); }
10587 
10588 
10589 /* IDirectSoundNotify */
10590 typedef struct
10591 {
10592  /* IUnknown */
10593  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundNotify* pThis, const IID* const riid, void** ppObject);
10594  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundNotify* pThis);
10595  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundNotify* pThis);
10596 
10597  /* IDirectSoundNotify */
10598  HRESULT (STDMETHODCALLTYPE * SetNotificationPositions)(ma_IDirectSoundNotify* pThis, DWORD dwPositionNotifies, const MA_DSBPOSITIONNOTIFY* pPositionNotifies);
10599 } ma_IDirectSoundNotifyVtbl;
10600 struct ma_IDirectSoundNotify
10601 {
10602  ma_IDirectSoundNotifyVtbl* lpVtbl;
10603 };
10604 static MA_INLINE HRESULT ma_IDirectSoundNotify_QueryInterface(ma_IDirectSoundNotify* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10605 static MA_INLINE ULONG ma_IDirectSoundNotify_AddRef(ma_IDirectSoundNotify* pThis) { return pThis->lpVtbl->AddRef(pThis); }
10606 static MA_INLINE ULONG ma_IDirectSoundNotify_Release(ma_IDirectSoundNotify* pThis) { return pThis->lpVtbl->Release(pThis); }
10607 static MA_INLINE HRESULT ma_IDirectSoundNotify_SetNotificationPositions(ma_IDirectSoundNotify* pThis, DWORD dwPositionNotifies, const MA_DSBPOSITIONNOTIFY* pPositionNotifies) { return pThis->lpVtbl->SetNotificationPositions(pThis, dwPositionNotifies, pPositionNotifies); }
10608 
10609 
10610 typedef BOOL (CALLBACK * ma_DSEnumCallbackAProc) (LPGUID pDeviceGUID, LPCSTR pDeviceDescription, LPCSTR pModule, LPVOID pContext);
10611 typedef HRESULT (WINAPI * ma_DirectSoundCreateProc) (const GUID* pcGuidDevice, ma_IDirectSound** ppDS8, LPUNKNOWN pUnkOuter);
10612 typedef HRESULT (WINAPI * ma_DirectSoundEnumerateAProc) (ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
10613 typedef HRESULT (WINAPI * ma_DirectSoundCaptureCreateProc) (const GUID* pcGuidDevice, ma_IDirectSoundCapture** ppDSC8, LPUNKNOWN pUnkOuter);
10614 typedef HRESULT (WINAPI * ma_DirectSoundCaptureEnumerateAProc)(ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
10615 
10616 static ma_uint32 ma_get_best_sample_rate_within_range(ma_uint32 sampleRateMin, ma_uint32 sampleRateMax)
10617 {
10618  /* Normalize the range in case we were given something stupid. */
10619  if (sampleRateMin < (ma_uint32)ma_standard_sample_rate_min) {
10620  sampleRateMin = (ma_uint32)ma_standard_sample_rate_min;
10621  }
10622  if (sampleRateMax > (ma_uint32)ma_standard_sample_rate_max) {
10623  sampleRateMax = (ma_uint32)ma_standard_sample_rate_max;
10624  }
10625  if (sampleRateMin > sampleRateMax) {
10626  sampleRateMin = sampleRateMax;
10627  }
10628 
10629  if (sampleRateMin == sampleRateMax) {
10630  return sampleRateMax;
10631  } else {
10632  size_t iStandardRate;
10633  for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
10634  ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
10635  if (standardRate >= sampleRateMin && standardRate <= sampleRateMax) {
10636  return standardRate;
10637  }
10638  }
10639  }
10640 
10641  /* Should never get here. */
10643  return 0;
10644 }
10645 
10646 /*
10647 Retrieves the channel count and channel map for the given speaker configuration. If the speaker configuration is unknown,
10648 the channel count and channel map will be left unmodified.
10649 */
10650 static void ma_get_channels_from_speaker_config__dsound(DWORD speakerConfig, WORD* pChannelsOut, DWORD* pChannelMapOut)
10651 {
10652  WORD channels;
10653  DWORD channelMap;
10654 
10655  channels = 0;
10656  if (pChannelsOut != NULL) {
10657  channels = *pChannelsOut;
10658  }
10659 
10660  channelMap = 0;
10661  if (pChannelMapOut != NULL) {
10662  channelMap = *pChannelMapOut;
10663  }
10664 
10665  /*
10666  The speaker configuration is a combination of speaker config and speaker geometry. The lower 8 bits is what we care about. The upper
10667  16 bits is for the geometry.
10668  */
10669  switch ((BYTE)(speakerConfig)) {
10670  case 1 /*DSSPEAKER_HEADPHONE*/: channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break;
10671  case 2 /*DSSPEAKER_MONO*/: channels = 1; channelMap = SPEAKER_FRONT_CENTER; break;
10672  case 3 /*DSSPEAKER_QUAD*/: channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
10673  case 4 /*DSSPEAKER_STEREO*/: channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break;
10674  case 5 /*DSSPEAKER_SURROUND*/: channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER; break;
10675  case 6 /*DSSPEAKER_5POINT1_BACK*/ /*DSSPEAKER_5POINT1*/: channels = 6; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
10676  case 7 /*DSSPEAKER_7POINT1_WIDE*/ /*DSSPEAKER_7POINT1*/: channels = 8; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER; break;
10677  case 8 /*DSSPEAKER_7POINT1_SURROUND*/: channels = 8; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break;
10678  case 9 /*DSSPEAKER_5POINT1_SURROUND*/: channels = 6; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break;
10679  default: break;
10680  }
10681 
10682  if (pChannelsOut != NULL) {
10683  *pChannelsOut = channels;
10684  }
10685 
10686  if (pChannelMapOut != NULL) {
10687  *pChannelMapOut = channelMap;
10688  }
10689 }
10690 
10691 
10692 static ma_result ma_context_create_IDirectSound__dsound(ma_context* pContext, ma_share_mode shareMode, const ma_device_id* pDeviceID, ma_IDirectSound** ppDirectSound)
10693 {
10694  ma_IDirectSound* pDirectSound;
10695  HWND hWnd;
10696  HRESULT hr;
10697 
10698  MA_ASSERT(pContext != NULL);
10699  MA_ASSERT(ppDirectSound != NULL);
10700 
10701  *ppDirectSound = NULL;
10702  pDirectSound = NULL;
10703 
10704  if (FAILED(((ma_DirectSoundCreateProc)pContext->dsound.DirectSoundCreate)((pDeviceID == NULL) ? NULL : (const GUID*)pDeviceID->dsound, &pDirectSound, NULL))) {
10705  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] DirectSoundCreate() failed for playback device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
10706  }
10707 
10708  /* The cooperative level must be set before doing anything else. */
10709  hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
10710  if (hWnd == NULL) {
10711  hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
10712  }
10713 
10714  hr = ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode == ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY);
10715  if (FAILED(hr)) {
10716  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_SetCooperateiveLevel() failed for playback device.", ma_result_from_HRESULT(hr));
10717  }
10718 
10719  *ppDirectSound = pDirectSound;
10720  return MA_SUCCESS;
10721 }
10722 
10723 static ma_result ma_context_create_IDirectSoundCapture__dsound(ma_context* pContext, ma_share_mode shareMode, const ma_device_id* pDeviceID, ma_IDirectSoundCapture** ppDirectSoundCapture)
10724 {
10725  ma_IDirectSoundCapture* pDirectSoundCapture;
10726  HRESULT hr;
10727 
10728  MA_ASSERT(pContext != NULL);
10729  MA_ASSERT(ppDirectSoundCapture != NULL);
10730 
10731  /* DirectSound does not support exclusive mode for capture. */
10732  if (shareMode == ma_share_mode_exclusive) {
10734  }
10735 
10736  *ppDirectSoundCapture = NULL;
10737  pDirectSoundCapture = NULL;
10738 
10739  hr = ((ma_DirectSoundCaptureCreateProc)pContext->dsound.DirectSoundCaptureCreate)((pDeviceID == NULL) ? NULL : (const GUID*)pDeviceID->dsound, &pDirectSoundCapture, NULL);
10740  if (FAILED(hr)) {
10741  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] DirectSoundCaptureCreate() failed for capture device.", ma_result_from_HRESULT(hr));
10742  }
10743 
10744  *ppDirectSoundCapture = pDirectSoundCapture;
10745  return MA_SUCCESS;
10746 }
10747 
10748 static ma_result ma_context_get_format_info_for_IDirectSoundCapture__dsound(ma_context* pContext, ma_IDirectSoundCapture* pDirectSoundCapture, WORD* pChannels, WORD* pBitsPerSample, DWORD* pSampleRate)
10749 {
10750  HRESULT hr;
10751  MA_DSCCAPS caps;
10752  WORD bitsPerSample;
10753  DWORD sampleRate;
10754 
10755  MA_ASSERT(pContext != NULL);
10756  MA_ASSERT(pDirectSoundCapture != NULL);
10757 
10758  if (pChannels) {
10759  *pChannels = 0;
10760  }
10761  if (pBitsPerSample) {
10762  *pBitsPerSample = 0;
10763  }
10764  if (pSampleRate) {
10765  *pSampleRate = 0;
10766  }
10767 
10768  MA_ZERO_OBJECT(&caps);
10769  caps.dwSize = sizeof(caps);
10770  hr = ma_IDirectSoundCapture_GetCaps(pDirectSoundCapture, &caps);
10771  if (FAILED(hr)) {
10772  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCapture_GetCaps() failed for capture device.", ma_result_from_HRESULT(hr));
10773  }
10774 
10775  if (pChannels) {
10776  *pChannels = (WORD)caps.dwChannels;
10777  }
10778 
10779  /* The device can support multiple formats. We just go through the different formats in order of priority and pick the first one. This the same type of system as the WinMM backend. */
10780  bitsPerSample = 16;
10781  sampleRate = 48000;
10782 
10783  if (caps.dwChannels == 1) {
10784  if ((caps.dwFormats & WAVE_FORMAT_48M16) != 0) {
10785  sampleRate = 48000;
10786  } else if ((caps.dwFormats & WAVE_FORMAT_44M16) != 0) {
10787  sampleRate = 44100;
10788  } else if ((caps.dwFormats & WAVE_FORMAT_2M16) != 0) {
10789  sampleRate = 22050;
10790  } else if ((caps.dwFormats & WAVE_FORMAT_1M16) != 0) {
10791  sampleRate = 11025;
10792  } else if ((caps.dwFormats & WAVE_FORMAT_96M16) != 0) {
10793  sampleRate = 96000;
10794  } else {
10795  bitsPerSample = 8;
10796  if ((caps.dwFormats & WAVE_FORMAT_48M08) != 0) {
10797  sampleRate = 48000;
10798  } else if ((caps.dwFormats & WAVE_FORMAT_44M08) != 0) {
10799  sampleRate = 44100;
10800  } else if ((caps.dwFormats & WAVE_FORMAT_2M08) != 0) {
10801  sampleRate = 22050;
10802  } else if ((caps.dwFormats & WAVE_FORMAT_1M08) != 0) {
10803  sampleRate = 11025;
10804  } else if ((caps.dwFormats & WAVE_FORMAT_96M08) != 0) {
10805  sampleRate = 96000;
10806  } else {
10807  bitsPerSample = 16; /* Didn't find it. Just fall back to 16-bit. */
10808  }
10809  }
10810  } else if (caps.dwChannels == 2) {
10811  if ((caps.dwFormats & WAVE_FORMAT_48S16) != 0) {
10812  sampleRate = 48000;
10813  } else if ((caps.dwFormats & WAVE_FORMAT_44S16) != 0) {
10814  sampleRate = 44100;
10815  } else if ((caps.dwFormats & WAVE_FORMAT_2S16) != 0) {
10816  sampleRate = 22050;
10817  } else if ((caps.dwFormats & WAVE_FORMAT_1S16) != 0) {
10818  sampleRate = 11025;
10819  } else if ((caps.dwFormats & WAVE_FORMAT_96S16) != 0) {
10820  sampleRate = 96000;
10821  } else {
10822  bitsPerSample = 8;
10823  if ((caps.dwFormats & WAVE_FORMAT_48S08) != 0) {
10824  sampleRate = 48000;
10825  } else if ((caps.dwFormats & WAVE_FORMAT_44S08) != 0) {
10826  sampleRate = 44100;
10827  } else if ((caps.dwFormats & WAVE_FORMAT_2S08) != 0) {
10828  sampleRate = 22050;
10829  } else if ((caps.dwFormats & WAVE_FORMAT_1S08) != 0) {
10830  sampleRate = 11025;
10831  } else if ((caps.dwFormats & WAVE_FORMAT_96S08) != 0) {
10832  sampleRate = 96000;
10833  } else {
10834  bitsPerSample = 16; /* Didn't find it. Just fall back to 16-bit. */
10835  }
10836  }
10837  }
10838 
10839  if (pBitsPerSample) {
10840  *pBitsPerSample = bitsPerSample;
10841  }
10842  if (pSampleRate) {
10843  *pSampleRate = sampleRate;
10844  }
10845 
10846  return MA_SUCCESS;
10847 }
10848 
10849 
10850 typedef struct
10851 {
10852  ma_context* pContext;
10853  ma_device_type deviceType;
10855  void* pUserData;
10856  ma_bool32 terminated;
10857 } ma_context_enumerate_devices_callback_data__dsound;
10858 
10859 static BOOL CALLBACK ma_context_enumerate_devices_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
10860 {
10861  ma_context_enumerate_devices_callback_data__dsound* pData = (ma_context_enumerate_devices_callback_data__dsound*)lpContext;
10862  ma_device_info deviceInfo;
10863 
10864  (void)lpcstrModule;
10865 
10866  MA_ZERO_OBJECT(&deviceInfo);
10867 
10868  /* ID. */
10869  if (lpGuid != NULL) {
10870  MA_COPY_MEMORY(deviceInfo.id.dsound, lpGuid, 16);
10871  } else {
10872  MA_ZERO_MEMORY(deviceInfo.id.dsound, 16);
10873  deviceInfo.isDefault = MA_TRUE;
10874  }
10875 
10876  /* Name / Description */
10877  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), lpcstrDescription, (size_t)-1);
10878 
10879 
10880  /* Call the callback function, but make sure we stop enumerating if the callee requested so. */
10881  MA_ASSERT(pData != NULL);
10882  pData->terminated = !pData->callback(pData->pContext, pData->deviceType, &deviceInfo, pData->pUserData);
10883  if (pData->terminated) {
10884  return FALSE; /* Stop enumeration. */
10885  } else {
10886  return TRUE; /* Continue enumeration. */
10887  }
10888 }
10889 
10890 static ma_result ma_context_enumerate_devices__dsound(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
10891 {
10892  ma_context_enumerate_devices_callback_data__dsound data;
10893 
10894  MA_ASSERT(pContext != NULL);
10895  MA_ASSERT(callback != NULL);
10896 
10897  data.pContext = pContext;
10898  data.callback = callback;
10899  data.pUserData = pUserData;
10900  data.terminated = MA_FALSE;
10901 
10902  /* Playback. */
10903  if (!data.terminated) {
10904  data.deviceType = ma_device_type_playback;
10905  ((ma_DirectSoundEnumerateAProc)pContext->dsound.DirectSoundEnumerateA)(ma_context_enumerate_devices_callback__dsound, &data);
10906  }
10907 
10908  /* Capture. */
10909  if (!data.terminated) {
10910  data.deviceType = ma_device_type_capture;
10911  ((ma_DirectSoundCaptureEnumerateAProc)pContext->dsound.DirectSoundCaptureEnumerateA)(ma_context_enumerate_devices_callback__dsound, &data);
10912  }
10913 
10914  return MA_SUCCESS;
10915 }
10916 
10917 
10918 typedef struct
10919 {
10920  const ma_device_id* pDeviceID;
10921  ma_device_info* pDeviceInfo;
10922  ma_bool32 found;
10923 } ma_context_get_device_info_callback_data__dsound;
10924 
10925 static BOOL CALLBACK ma_context_get_device_info_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
10926 {
10927  ma_context_get_device_info_callback_data__dsound* pData = (ma_context_get_device_info_callback_data__dsound*)lpContext;
10928  MA_ASSERT(pData != NULL);
10929 
10930  if ((pData->pDeviceID == NULL || ma_is_guid_null(pData->pDeviceID->dsound)) && (lpGuid == NULL || ma_is_guid_null(lpGuid))) {
10931  /* Default device. */
10932  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), lpcstrDescription, (size_t)-1);
10933  pData->pDeviceInfo->isDefault = MA_TRUE;
10934  pData->found = MA_TRUE;
10935  return FALSE; /* Stop enumeration. */
10936  } else {
10937  /* Not the default device. */
10938  if (lpGuid != NULL && pData->pDeviceID != NULL) {
10939  if (memcmp(pData->pDeviceID->dsound, lpGuid, sizeof(pData->pDeviceID->dsound)) == 0) {
10940  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), lpcstrDescription, (size_t)-1);
10941  pData->found = MA_TRUE;
10942  return FALSE; /* Stop enumeration. */
10943  }
10944  }
10945  }
10946 
10947  (void)lpcstrModule;
10948  return TRUE;
10949 }
10950 
10951 static ma_result ma_context_get_device_info__dsound(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
10952 {
10953  ma_result result;
10954  HRESULT hr;
10955 
10956  if (pDeviceID != NULL) {
10957  ma_context_get_device_info_callback_data__dsound data;
10958 
10959  /* ID. */
10960  MA_COPY_MEMORY(pDeviceInfo->id.dsound, pDeviceID->dsound, 16);
10961 
10962  /* Name / Description. This is retrieved by enumerating over each device until we find that one that matches the input ID. */
10963  data.pDeviceID = pDeviceID;
10964  data.pDeviceInfo = pDeviceInfo;
10965  data.found = MA_FALSE;
10966  if (deviceType == ma_device_type_playback) {
10967  ((ma_DirectSoundEnumerateAProc)pContext->dsound.DirectSoundEnumerateA)(ma_context_get_device_info_callback__dsound, &data);
10968  } else {
10969  ((ma_DirectSoundCaptureEnumerateAProc)pContext->dsound.DirectSoundCaptureEnumerateA)(ma_context_get_device_info_callback__dsound, &data);
10970  }
10971 
10972  if (!data.found) {
10973  return MA_NO_DEVICE;
10974  }
10975  } else {
10976  /* I don't think there's a way to get the name of the default device with DirectSound. In this case we just need to use defaults. */
10977 
10978  /* ID */
10979  MA_ZERO_MEMORY(pDeviceInfo->id.dsound, 16);
10980 
10981  /* Name / Description */
10982  if (deviceType == ma_device_type_playback) {
10983  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
10984  } else {
10985  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
10986  }
10987 
10988  pDeviceInfo->isDefault = MA_TRUE;
10989  }
10990 
10991  /* Retrieving detailed information is slightly different depending on the device type. */
10992  if (deviceType == ma_device_type_playback) {
10993  /* Playback. */
10994  ma_IDirectSound* pDirectSound;
10995  MA_DSCAPS caps;
10996  WORD channels;
10997 
10998  result = ma_context_create_IDirectSound__dsound(pContext, ma_share_mode_shared, pDeviceID, &pDirectSound);
10999  if (result != MA_SUCCESS) {
11000  return result;
11001  }
11002 
11003  MA_ZERO_OBJECT(&caps);
11004  caps.dwSize = sizeof(caps);
11005  hr = ma_IDirectSound_GetCaps(pDirectSound, &caps);
11006  if (FAILED(hr)) {
11007  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_GetCaps() failed for playback device.", ma_result_from_HRESULT(hr));
11008  }
11009 
11010 
11011  /* Channels. Only a single channel count is reported for DirectSound. */
11012  if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
11013  /* It supports at least stereo, but could support more. */
11014  DWORD speakerConfig;
11015 
11016  channels = 2;
11017 
11018  /* Look at the speaker configuration to get a better idea on the channel count. */
11019  hr = ma_IDirectSound_GetSpeakerConfig(pDirectSound, &speakerConfig);
11020  if (SUCCEEDED(hr)) {
11021  ma_get_channels_from_speaker_config__dsound(speakerConfig, &channels, NULL);
11022  }
11023  } else {
11024  /* It does not support stereo, which means we are stuck with mono. */
11025  channels = 1;
11026  }
11027 
11028 
11029  /*
11030  In DirectSound, our native formats are centered around sample rates. All formats are supported, and we're only reporting a single channel
11031  count. However, DirectSound can report a range of supported sample rates. We're only going to include standard rates known by miniaudio
11032  in order to keep the size of this within reason.
11033  */
11034  if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
11035  /* Multiple sample rates are supported. We'll report in order of our preferred sample rates. */
11036  size_t iStandardSampleRate;
11037  for (iStandardSampleRate = 0; iStandardSampleRate < ma_countof(g_maStandardSampleRatePriorities); iStandardSampleRate += 1) {
11038  ma_uint32 sampleRate = g_maStandardSampleRatePriorities[iStandardSampleRate];
11039  if (sampleRate >= caps.dwMinSecondarySampleRate && sampleRate <= caps.dwMaxSecondarySampleRate) {
11040  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = ma_format_unknown;
11041  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
11042  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
11043  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
11044  pDeviceInfo->nativeDataFormatCount += 1;
11045  }
11046  }
11047  } else {
11048  /* Only a single sample rate is supported. */
11049  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = ma_format_unknown;
11050  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
11051  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = caps.dwMaxSecondarySampleRate;
11052  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
11053  pDeviceInfo->nativeDataFormatCount += 1;
11054  }
11055 
11056  ma_IDirectSound_Release(pDirectSound);
11057  } else {
11058  /*
11059  Capture. This is a little different to playback due to the say the supported formats are reported. Technically capture
11060  devices can support a number of different formats, but for simplicity and consistency with ma_device_init() I'm just
11061  reporting the best format.
11062  */
11063  ma_IDirectSoundCapture* pDirectSoundCapture;
11064  WORD channels;
11065  WORD bitsPerSample;
11066  DWORD sampleRate;
11067 
11068  result = ma_context_create_IDirectSoundCapture__dsound(pContext, ma_share_mode_shared, pDeviceID, &pDirectSoundCapture);
11069  if (result != MA_SUCCESS) {
11070  return result;
11071  }
11072 
11073  result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pContext, pDirectSoundCapture, &channels, &bitsPerSample, &sampleRate);
11074  if (result != MA_SUCCESS) {
11075  ma_IDirectSoundCapture_Release(pDirectSoundCapture);
11076  return result;
11077  }
11078 
11079  ma_IDirectSoundCapture_Release(pDirectSoundCapture);
11080 
11081  /* The format is always an integer format and is based on the bits per sample. */
11082  if (bitsPerSample == 8) {
11083  pDeviceInfo->formats[0] = ma_format_u8;
11084  } else if (bitsPerSample == 16) {
11085  pDeviceInfo->formats[0] = ma_format_s16;
11086  } else if (bitsPerSample == 24) {
11087  pDeviceInfo->formats[0] = ma_format_s24;
11088  } else if (bitsPerSample == 32) {
11089  pDeviceInfo->formats[0] = ma_format_s32;
11090  } else {
11091  return MA_FORMAT_NOT_SUPPORTED;
11092  }
11093 
11094  pDeviceInfo->nativeDataFormats[0].channels = channels;
11095  pDeviceInfo->nativeDataFormats[0].sampleRate = sampleRate;
11096  pDeviceInfo->nativeDataFormats[0].flags = 0;
11097  pDeviceInfo->nativeDataFormatCount = 1;
11098  }
11099 
11100  return MA_SUCCESS;
11101 }
11102 
11103 
11104 
11105 static ma_result ma_device_uninit__dsound(ma_device* pDevice)
11106 {
11107  MA_ASSERT(pDevice != NULL);
11108 
11109  if (pDevice->dsound.pCaptureBuffer != NULL) {
11110  ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11111  }
11112  if (pDevice->dsound.pCapture != NULL) {
11113  ma_IDirectSoundCapture_Release((ma_IDirectSoundCapture*)pDevice->dsound.pCapture);
11114  }
11115 
11116  if (pDevice->dsound.pPlaybackBuffer != NULL) {
11117  ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
11118  }
11119  if (pDevice->dsound.pPlaybackPrimaryBuffer != NULL) {
11120  ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer);
11121  }
11122  if (pDevice->dsound.pPlayback != NULL) {
11123  ma_IDirectSound_Release((ma_IDirectSound*)pDevice->dsound.pPlayback);
11124  }
11125 
11126  return MA_SUCCESS;
11127 }
11128 
11129 static ma_result ma_config_to_WAVEFORMATEXTENSIBLE(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, const ma_channel* pChannelMap, WAVEFORMATEXTENSIBLE* pWF)
11130 {
11131  GUID subformat;
11132 
11133  if (format == ma_format_unknown) {
11134  format = MA_DEFAULT_FORMAT;
11135  }
11136 
11137  if (channels == 0) {
11138  channels = MA_DEFAULT_CHANNELS;
11139  }
11140 
11141  if (sampleRate == 0) {
11142  sampleRate = MA_DEFAULT_SAMPLE_RATE;
11143  }
11144 
11145  switch (format)
11146  {
11147  case ma_format_u8:
11148  case ma_format_s16:
11149  case ma_format_s24:
11150  /*case ma_format_s24_32:*/
11151  case ma_format_s32:
11152  {
11153  subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
11154  } break;
11155 
11156  case ma_format_f32:
11157  {
11158  subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
11159  } break;
11160 
11161  default:
11162  return MA_FORMAT_NOT_SUPPORTED;
11163  }
11164 
11165  MA_ZERO_OBJECT(pWF);
11166  pWF->Format.cbSize = sizeof(*pWF);
11167  pWF->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
11168  pWF->Format.nChannels = (WORD)channels;
11169  pWF->Format.nSamplesPerSec = (DWORD)sampleRate;
11170  pWF->Format.wBitsPerSample = (WORD)(ma_get_bytes_per_sample(format)*8);
11171  pWF->Format.nBlockAlign = (WORD)(pWF->Format.nChannels * pWF->Format.wBitsPerSample / 8);
11172  pWF->Format.nAvgBytesPerSec = pWF->Format.nBlockAlign * pWF->Format.nSamplesPerSec;
11173  pWF->Samples.wValidBitsPerSample = pWF->Format.wBitsPerSample;
11174  pWF->dwChannelMask = ma_channel_map_to_channel_mask__win32(pChannelMap, channels);
11175  pWF->SubFormat = subformat;
11176 
11177  return MA_SUCCESS;
11178 }
11179 
11180 static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__dsound(const ma_device_descriptor* pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
11181 {
11182  /* DirectSound has a minimum period size of 20ms. */
11183  ma_uint32 minPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(20, nativeSampleRate);
11184  ma_uint32 periodSizeInFrames;
11185 
11186  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, nativeSampleRate, performanceProfile);
11187  if (periodSizeInFrames < minPeriodSizeInFrames) {
11188  periodSizeInFrames = minPeriodSizeInFrames;
11189  }
11190 
11191  return periodSizeInFrames;
11192 }
11193 
11194 static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
11195 {
11196  ma_result result;
11197  HRESULT hr;
11198 
11199  MA_ASSERT(pDevice != NULL);
11200 
11201  MA_ZERO_OBJECT(&pDevice->dsound);
11202 
11203  if (pConfig->deviceType == ma_device_type_loopback) {
11205  }
11206 
11207  /*
11208  Unfortunately DirectSound uses different APIs and data structures for playback and catpure devices. We need to initialize
11209  the capture device first because we'll want to match it's buffer size and period count on the playback side if we're using
11210  full-duplex mode.
11211  */
11212  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
11213  WAVEFORMATEXTENSIBLE wf;
11214  MA_DSCBUFFERDESC descDS;
11215  ma_uint32 periodSizeInFrames;
11216  ma_uint32 periodCount;
11217  char rawdata[1024]; /* <-- Ugly hack to avoid a malloc() due to a crappy DirectSound API. */
11218  WAVEFORMATEXTENSIBLE* pActualFormat;
11219 
11220  result = ma_config_to_WAVEFORMATEXTENSIBLE(pDescriptorCapture->format, pDescriptorCapture->channels, pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, &wf);
11221  if (result != MA_SUCCESS) {
11222  return result;
11223  }
11224 
11225  result = ma_context_create_IDirectSoundCapture__dsound(pDevice->pContext, pDescriptorCapture->shareMode, pDescriptorCapture->pDeviceID, (ma_IDirectSoundCapture**)&pDevice->dsound.pCapture);
11226  if (result != MA_SUCCESS) {
11227  ma_device_uninit__dsound(pDevice);
11228  return result;
11229  }
11230 
11231  result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pDevice->pContext, (ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &wf.Format.nChannels, &wf.Format.wBitsPerSample, &wf.Format.nSamplesPerSec);
11232  if (result != MA_SUCCESS) {
11233  ma_device_uninit__dsound(pDevice);
11234  return result;
11235  }
11236 
11237  wf.Format.nBlockAlign = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
11238  wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
11239  wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
11240  wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
11241 
11242  /* The size of the buffer must be a clean multiple of the period count. */
11243  periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__dsound(pDescriptorCapture, wf.Format.nSamplesPerSec, pConfig->performanceProfile);
11244  periodCount = (pDescriptorCapture->periodCount > 0) ? pDescriptorCapture->periodCount : MA_DEFAULT_PERIODS;
11245 
11246  MA_ZERO_OBJECT(&descDS);
11247  descDS.dwSize = sizeof(descDS);
11248  descDS.dwFlags = 0;
11249  descDS.dwBufferBytes = periodSizeInFrames * periodCount * wf.Format.nBlockAlign;
11250  descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
11251  hr = ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer, NULL);
11252  if (FAILED(hr)) {
11253  ma_device_uninit__dsound(pDevice);
11254  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCapture_CreateCaptureBuffer() failed for capture device.", ma_result_from_HRESULT(hr));
11255  }
11256 
11257  /* Get the _actual_ properties of the buffer. */
11258  pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
11259  hr = ma_IDirectSoundCaptureBuffer_GetFormat((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, (WAVEFORMATEX*)pActualFormat, sizeof(rawdata), NULL);
11260  if (FAILED(hr)) {
11261  ma_device_uninit__dsound(pDevice);
11262  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to retrieve the actual format of the capture device's buffer.", ma_result_from_HRESULT(hr));
11263  }
11264 
11265  /* We can now start setting the output data formats. */
11266  pDescriptorCapture->format = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
11267  pDescriptorCapture->channels = pActualFormat->Format.nChannels;
11268  pDescriptorCapture->sampleRate = pActualFormat->Format.nSamplesPerSec;
11269 
11270  /* Get the native channel map based on the channel mask. */
11271  if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
11272  ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
11273  } else {
11274  ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
11275  }
11276 
11277  /*
11278  After getting the actual format the size of the buffer in frames may have actually changed. However, we want this to be as close to what the
11279  user has asked for as possible, so let's go ahead and release the old capture buffer and create a new one in this case.
11280  */
11281  if (periodSizeInFrames != (descDS.dwBufferBytes / ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) / periodCount)) {
11282  descDS.dwBufferBytes = periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) * periodCount;
11283  ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11284 
11285  hr = ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer, NULL);
11286  if (FAILED(hr)) {
11287  ma_device_uninit__dsound(pDevice);
11288  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Second attempt at IDirectSoundCapture_CreateCaptureBuffer() failed for capture device.", ma_result_from_HRESULT(hr));
11289  }
11290  }
11291 
11292  /* DirectSound should give us a buffer exactly the size we asked for. */
11293  pDescriptorCapture->periodSizeInFrames = periodSizeInFrames;
11294  pDescriptorCapture->periodCount = periodCount;
11295  }
11296 
11297  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
11298  WAVEFORMATEXTENSIBLE wf;
11299  MA_DSBUFFERDESC descDSPrimary;
11300  MA_DSCAPS caps;
11301  char rawdata[1024]; /* <-- Ugly hack to avoid a malloc() due to a crappy DirectSound API. */
11302  WAVEFORMATEXTENSIBLE* pActualFormat;
11303  ma_uint32 periodSizeInFrames;
11304  ma_uint32 periodCount;
11305  MA_DSBUFFERDESC descDS;
11306 
11307  result = ma_config_to_WAVEFORMATEXTENSIBLE(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &wf);
11308  if (result != MA_SUCCESS) {
11309  return result;
11310  }
11311 
11312  result = ma_context_create_IDirectSound__dsound(pDevice->pContext, pDescriptorPlayback->shareMode, pDescriptorPlayback->pDeviceID, (ma_IDirectSound**)&pDevice->dsound.pPlayback);
11313  if (result != MA_SUCCESS) {
11314  ma_device_uninit__dsound(pDevice);
11315  return result;
11316  }
11317 
11318  MA_ZERO_OBJECT(&descDSPrimary);
11319  descDSPrimary.dwSize = sizeof(MA_DSBUFFERDESC);
11320  descDSPrimary.dwFlags = MA_DSBCAPS_PRIMARYBUFFER | MA_DSBCAPS_CTRLVOLUME;
11321  hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDSPrimary, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackPrimaryBuffer, NULL);
11322  if (FAILED(hr)) {
11323  ma_device_uninit__dsound(pDevice);
11324  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_CreateSoundBuffer() failed for playback device's primary buffer.", ma_result_from_HRESULT(hr));
11325  }
11326 
11327 
11328  /* We may want to make some adjustments to the format if we are using defaults. */
11329  MA_ZERO_OBJECT(&caps);
11330  caps.dwSize = sizeof(caps);
11331  hr = ma_IDirectSound_GetCaps((ma_IDirectSound*)pDevice->dsound.pPlayback, &caps);
11332  if (FAILED(hr)) {
11333  ma_device_uninit__dsound(pDevice);
11334  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_GetCaps() failed for playback device.", ma_result_from_HRESULT(hr));
11335  }
11336 
11337  if (pDescriptorPlayback->channels == 0) {
11338  if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
11339  DWORD speakerConfig;
11340 
11341  /* It supports at least stereo, but could support more. */
11342  wf.Format.nChannels = 2;
11343 
11344  /* Look at the speaker configuration to get a better idea on the channel count. */
11345  if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig((ma_IDirectSound*)pDevice->dsound.pPlayback, &speakerConfig))) {
11346  ma_get_channels_from_speaker_config__dsound(speakerConfig, &wf.Format.nChannels, &wf.dwChannelMask);
11347  }
11348  } else {
11349  /* It does not support stereo, which means we are stuck with mono. */
11350  wf.Format.nChannels = 1;
11351  }
11352  }
11353 
11354  if (pDescriptorPlayback->sampleRate == 0) {
11355  /* We base the sample rate on the values returned by GetCaps(). */
11356  if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
11357  wf.Format.nSamplesPerSec = ma_get_best_sample_rate_within_range(caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate);
11358  } else {
11359  wf.Format.nSamplesPerSec = caps.dwMaxSecondarySampleRate;
11360  }
11361  }
11362 
11363  wf.Format.nBlockAlign = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
11364  wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
11365 
11366  /*
11367  From MSDN:
11368 
11369  The method succeeds even if the hardware does not support the requested format; DirectSound sets the buffer to the closest
11370  supported format. To determine whether this has happened, an application can call the GetFormat method for the primary buffer
11371  and compare the result with the format that was requested with the SetFormat method.
11372  */
11373  hr = ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)&wf);
11374  if (FAILED(hr)) {
11375  ma_device_uninit__dsound(pDevice);
11376  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to set format of playback device's primary buffer.", ma_result_from_HRESULT(hr));
11377  }
11378 
11379  /* Get the _actual_ properties of the buffer. */
11380  pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
11381  hr = ma_IDirectSoundBuffer_GetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)pActualFormat, sizeof(rawdata), NULL);
11382  if (FAILED(hr)) {
11383  ma_device_uninit__dsound(pDevice);
11384  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to retrieve the actual format of the playback device's primary buffer.", ma_result_from_HRESULT(hr));
11385  }
11386 
11387  /* We now have enough information to start setting some output properties. */
11388  pDescriptorPlayback->format = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
11389  pDescriptorPlayback->channels = pActualFormat->Format.nChannels;
11390  pDescriptorPlayback->sampleRate = pActualFormat->Format.nSamplesPerSec;
11391 
11392  /* Get the internal channel map based on the channel mask. */
11393  if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
11394  ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
11395  } else {
11396  ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
11397  }
11398 
11399  /* The size of the buffer must be a clean multiple of the period count. */
11400  periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__dsound(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
11401  periodCount = (pDescriptorPlayback->periodCount > 0) ? pDescriptorPlayback->periodCount : MA_DEFAULT_PERIODS;
11402 
11403  /*
11404  Meaning of dwFlags (from MSDN):
11405 
11406  DSBCAPS_CTRLPOSITIONNOTIFY
11407  The buffer has position notification capability.
11408 
11409  DSBCAPS_GLOBALFOCUS
11410  With this flag set, an application using DirectSound can continue to play its buffers if the user switches focus to
11411  another application, even if the new application uses DirectSound.
11412 
11413  DSBCAPS_GETCURRENTPOSITION2
11414  In the first version of DirectSound, the play cursor was significantly ahead of the actual playing sound on emulated
11415  sound cards; it was directly behind the write cursor. Now, if the DSBCAPS_GETCURRENTPOSITION2 flag is specified, the
11416  application can get a more accurate play cursor.
11417  */
11418  MA_ZERO_OBJECT(&descDS);
11419  descDS.dwSize = sizeof(descDS);
11420  descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2;
11421  descDS.dwBufferBytes = periodSizeInFrames * periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels);
11422  descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
11423  hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer, NULL);
11424  if (FAILED(hr)) {
11425  ma_device_uninit__dsound(pDevice);
11426  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_CreateSoundBuffer() failed for playback device's secondary buffer.", ma_result_from_HRESULT(hr));
11427  }
11428 
11429  /* DirectSound should give us a buffer exactly the size we asked for. */
11430  pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
11431  pDescriptorPlayback->periodCount = periodCount;
11432  }
11433 
11434  return MA_SUCCESS;
11435 }
11436 
11437 
11438 static ma_result ma_device_data_loop__dsound(ma_device* pDevice)
11439 {
11440  ma_result result = MA_SUCCESS;
11441  ma_uint32 bpfDeviceCapture = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
11442  ma_uint32 bpfDevicePlayback = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
11443  HRESULT hr;
11444  DWORD lockOffsetInBytesCapture;
11445  DWORD lockSizeInBytesCapture;
11446  DWORD mappedSizeInBytesCapture;
11447  DWORD mappedDeviceFramesProcessedCapture;
11448  void* pMappedDeviceBufferCapture;
11449  DWORD lockOffsetInBytesPlayback;
11450  DWORD lockSizeInBytesPlayback;
11451  DWORD mappedSizeInBytesPlayback;
11452  void* pMappedDeviceBufferPlayback;
11453  DWORD prevReadCursorInBytesCapture = 0;
11454  DWORD prevPlayCursorInBytesPlayback = 0;
11455  ma_bool32 physicalPlayCursorLoopFlagPlayback = 0;
11456  DWORD virtualWriteCursorInBytesPlayback = 0;
11457  ma_bool32 virtualWriteCursorLoopFlagPlayback = 0;
11458  ma_bool32 isPlaybackDeviceStarted = MA_FALSE;
11459  ma_uint32 framesWrittenToPlaybackDevice = 0; /* For knowing whether or not the playback device needs to be started. */
11460  ma_uint32 waitTimeInMilliseconds = 1;
11461 
11462  MA_ASSERT(pDevice != NULL);
11463 
11464  /* The first thing to do is start the capture device. The playback device is only started after the first period is written. */
11465  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
11466  if (FAILED(ma_IDirectSoundCaptureBuffer_Start((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, MA_DSCBSTART_LOOPING))) {
11467  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCaptureBuffer_Start() failed.", MA_FAILED_TO_START_BACKEND_DEVICE);
11468  }
11469  }
11470 
11471  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
11472  switch (pDevice->type)
11473  {
11474  case ma_device_type_duplex:
11475  {
11476  DWORD physicalCaptureCursorInBytes;
11477  DWORD physicalReadCursorInBytes;
11478  hr = ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes);
11479  if (FAILED(hr)) {
11480  return ma_result_from_HRESULT(hr);
11481  }
11482 
11483  /* If nothing is available we just sleep for a bit and return from this iteration. */
11484  if (physicalReadCursorInBytes == prevReadCursorInBytesCapture) {
11485  ma_sleep(waitTimeInMilliseconds);
11486  continue; /* Nothing is available in the capture buffer. */
11487  }
11488 
11489  /*
11490  The current position has moved. We need to map all of the captured samples and write them to the playback device, making sure
11491  we don't return until every frame has been copied over.
11492  */
11493  if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
11494  /* The capture position has not looped. This is the simple case. */
11495  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
11496  lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
11497  } else {
11498  /*
11499  The capture position has looped. This is the more complex case. Map to the end of the buffer. If this does not return anything,
11500  do it again from the start.
11501  */
11502  if (prevReadCursorInBytesCapture < pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) {
11503  /* Lock up to the end of the buffer. */
11504  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
11505  lockSizeInBytesCapture = (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) - prevReadCursorInBytesCapture;
11506  } else {
11507  /* Lock starting from the start of the buffer. */
11508  lockOffsetInBytesCapture = 0;
11509  lockSizeInBytesCapture = physicalReadCursorInBytes;
11510  }
11511  }
11512 
11513  if (lockSizeInBytesCapture == 0) {
11514  ma_sleep(waitTimeInMilliseconds);
11515  continue; /* Nothing is available in the capture buffer. */
11516  }
11517 
11518  hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedDeviceBufferCapture, &mappedSizeInBytesCapture, NULL, NULL, 0);
11519  if (FAILED(hr)) {
11520  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
11521  }
11522 
11523 
11524  /* At this point we have some input data that we need to output. We do not return until every mapped frame of the input data is written to the playback device. */
11525  mappedDeviceFramesProcessedCapture = 0;
11526 
11527  for (;;) { /* Keep writing to the playback device. */
11528  ma_uint8 inputFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
11529  ma_uint32 inputFramesInClientFormatCap = sizeof(inputFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
11530  ma_uint8 outputFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
11531  ma_uint32 outputFramesInClientFormatCap = sizeof(outputFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
11532  ma_uint32 outputFramesInClientFormatCount;
11533  ma_uint32 outputFramesInClientFormatConsumed = 0;
11534  ma_uint64 clientCapturedFramesToProcess = ma_min(inputFramesInClientFormatCap, outputFramesInClientFormatCap);
11535  ma_uint64 deviceCapturedFramesToProcess = (mappedSizeInBytesCapture / bpfDeviceCapture) - mappedDeviceFramesProcessedCapture;
11536  void* pRunningMappedDeviceBufferCapture = ma_offset_ptr(pMappedDeviceBufferCapture, mappedDeviceFramesProcessedCapture * bpfDeviceCapture);
11537 
11538  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningMappedDeviceBufferCapture, &deviceCapturedFramesToProcess, inputFramesInClientFormat, &clientCapturedFramesToProcess);
11539  if (result != MA_SUCCESS) {
11540  break;
11541  }
11542 
11543  outputFramesInClientFormatCount = (ma_uint32)clientCapturedFramesToProcess;
11544  mappedDeviceFramesProcessedCapture += (ma_uint32)deviceCapturedFramesToProcess;
11545 
11546  ma_device__on_data(pDevice, outputFramesInClientFormat, inputFramesInClientFormat, (ma_uint32)clientCapturedFramesToProcess);
11547 
11548  /* At this point we have input and output data in client format. All we need to do now is convert it to the output device format. This may take a few passes. */
11549  for (;;) {
11550  ma_uint32 framesWrittenThisIteration;
11551  DWORD physicalPlayCursorInBytes;
11552  DWORD physicalWriteCursorInBytes;
11553  DWORD availableBytesPlayback;
11554  DWORD silentPaddingInBytes = 0; /* <-- Must be initialized to 0. */
11555 
11556  /* We need the physical play and write cursors. */
11557  if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
11558  break;
11559  }
11560 
11561  if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
11562  physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
11563  }
11564  prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
11565 
11566  /* If there's any bytes available for writing we can do that now. The space between the virtual cursor position and play cursor. */
11567  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11568  /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
11569  if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
11570  availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
11571  availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
11572  } else {
11573  /* This is an error. */
11574  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Duplex/Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11575  availableBytesPlayback = 0;
11576  }
11577  } else {
11578  /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
11579  if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
11580  availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11581  } else {
11582  /* This is an error. */
11583  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Duplex/Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11584  availableBytesPlayback = 0;
11585  }
11586  }
11587 
11588  /* If there's no room available for writing we need to wait for more. */
11589  if (availableBytesPlayback == 0) {
11590  /* If we haven't started the device yet, this will never get beyond 0. In this case we need to get the device started. */
11591  if (!isPlaybackDeviceStarted) {
11592  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
11593  if (FAILED(hr)) {
11594  ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11595  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
11596  }
11597  isPlaybackDeviceStarted = MA_TRUE;
11598  } else {
11599  ma_sleep(waitTimeInMilliseconds);
11600  continue;
11601  }
11602  }
11603 
11604 
11605  /* Getting here means there room available somewhere. We limit this to either the end of the buffer or the physical play cursor, whichever is closest. */
11606  lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
11607  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11608  /* Same loop iteration. Go up to the end of the buffer. */
11609  lockSizeInBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
11610  } else {
11611  /* Different loop iterations. Go up to the physical play cursor. */
11612  lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11613  }
11614 
11615  hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedDeviceBufferPlayback, &mappedSizeInBytesPlayback, NULL, NULL, 0);
11616  if (FAILED(hr)) {
11617  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from playback device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
11618  break;
11619  }
11620 
11621  /*
11622  Experiment: If the playback buffer is being starved, pad it with some silence to get it back in sync. This will cause a glitch, but it may prevent
11623  endless glitching due to it constantly running out of data.
11624  */
11625  if (isPlaybackDeviceStarted) {
11626  DWORD bytesQueuedForPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - availableBytesPlayback;
11627  if (bytesQueuedForPlayback < (pDevice->playback.internalPeriodSizeInFrames*bpfDevicePlayback)) {
11628  silentPaddingInBytes = (pDevice->playback.internalPeriodSizeInFrames*2*bpfDevicePlayback) - bytesQueuedForPlayback;
11629  if (silentPaddingInBytes > lockSizeInBytesPlayback) {
11630  silentPaddingInBytes = lockSizeInBytesPlayback;
11631  }
11632 
11633  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Duplex/Playback) Playback buffer starved. availableBytesPlayback=%ld, silentPaddingInBytes=%ld\n", availableBytesPlayback, silentPaddingInBytes);
11634  }
11635  }
11636 
11637  /* At this point we have a buffer for output. */
11638  if (silentPaddingInBytes > 0) {
11639  MA_ZERO_MEMORY(pMappedDeviceBufferPlayback, silentPaddingInBytes);
11640  framesWrittenThisIteration = silentPaddingInBytes/bpfDevicePlayback;
11641  } else {
11642  ma_uint64 convertedFrameCountIn = (outputFramesInClientFormatCount - outputFramesInClientFormatConsumed);
11643  ma_uint64 convertedFrameCountOut = mappedSizeInBytesPlayback/bpfDevicePlayback;
11644  void* pConvertedFramesIn = ma_offset_ptr(outputFramesInClientFormat, outputFramesInClientFormatConsumed * bpfDevicePlayback);
11645  void* pConvertedFramesOut = pMappedDeviceBufferPlayback;
11646 
11647  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pConvertedFramesIn, &convertedFrameCountIn, pConvertedFramesOut, &convertedFrameCountOut);
11648  if (result != MA_SUCCESS) {
11649  break;
11650  }
11651 
11652  outputFramesInClientFormatConsumed += (ma_uint32)convertedFrameCountOut;
11653  framesWrittenThisIteration = (ma_uint32)convertedFrameCountOut;
11654  }
11655 
11656 
11657  hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedDeviceBufferPlayback, framesWrittenThisIteration*bpfDevicePlayback, NULL, 0);
11658  if (FAILED(hr)) {
11659  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from playback device after writing to the device.", ma_result_from_HRESULT(hr));
11660  break;
11661  }
11662 
11663  virtualWriteCursorInBytesPlayback += framesWrittenThisIteration*bpfDevicePlayback;
11664  if ((virtualWriteCursorInBytesPlayback/bpfDevicePlayback) == pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods) {
11665  virtualWriteCursorInBytesPlayback = 0;
11666  virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
11667  }
11668 
11669  /*
11670  We may need to start the device. We want two full periods to be written before starting the playback device. Having an extra period adds
11671  a bit of a buffer to prevent the playback buffer from getting starved.
11672  */
11673  framesWrittenToPlaybackDevice += framesWrittenThisIteration;
11674  if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= (pDevice->playback.internalPeriodSizeInFrames*2)) {
11675  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
11676  if (FAILED(hr)) {
11677  ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11678  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
11679  }
11680  isPlaybackDeviceStarted = MA_TRUE;
11681  }
11682 
11683  if (framesWrittenThisIteration < mappedSizeInBytesPlayback/bpfDevicePlayback) {
11684  break; /* We're finished with the output data.*/
11685  }
11686  }
11687 
11688  if (clientCapturedFramesToProcess == 0) {
11689  break; /* We just consumed every input sample. */
11690  }
11691  }
11692 
11693 
11694  /* At this point we're done with the mapped portion of the capture buffer. */
11695  hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedDeviceBufferCapture, mappedSizeInBytesCapture, NULL, 0);
11696  if (FAILED(hr)) {
11697  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from capture device after reading from the device.", ma_result_from_HRESULT(hr));
11698  }
11699  prevReadCursorInBytesCapture = (lockOffsetInBytesCapture + mappedSizeInBytesCapture);
11700  } break;
11701 
11702 
11703 
11705  {
11706  DWORD physicalCaptureCursorInBytes;
11707  DWORD physicalReadCursorInBytes;
11708  hr = ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes);
11709  if (FAILED(hr)) {
11710  return MA_ERROR;
11711  }
11712 
11713  /* If the previous capture position is the same as the current position we need to wait a bit longer. */
11714  if (prevReadCursorInBytesCapture == physicalReadCursorInBytes) {
11715  ma_sleep(waitTimeInMilliseconds);
11716  continue;
11717  }
11718 
11719  /* Getting here means we have capture data available. */
11720  if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
11721  /* The capture position has not looped. This is the simple case. */
11722  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
11723  lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
11724  } else {
11725  /*
11726  The capture position has looped. This is the more complex case. Map to the end of the buffer. If this does not return anything,
11727  do it again from the start.
11728  */
11729  if (prevReadCursorInBytesCapture < pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) {
11730  /* Lock up to the end of the buffer. */
11731  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
11732  lockSizeInBytesCapture = (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) - prevReadCursorInBytesCapture;
11733  } else {
11734  /* Lock starting from the start of the buffer. */
11735  lockOffsetInBytesCapture = 0;
11736  lockSizeInBytesCapture = physicalReadCursorInBytes;
11737  }
11738  }
11739 
11740  if (lockSizeInBytesCapture < pDevice->capture.internalPeriodSizeInFrames) {
11741  ma_sleep(waitTimeInMilliseconds);
11742  continue; /* Nothing is available in the capture buffer. */
11743  }
11744 
11745  hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedDeviceBufferCapture, &mappedSizeInBytesCapture, NULL, NULL, 0);
11746  if (FAILED(hr)) {
11747  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from capture device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
11748  }
11749 
11750  #ifdef MA_DEBUG_OUTPUT
11751  if (lockSizeInBytesCapture != mappedSizeInBytesCapture) {
11752  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Capture) lockSizeInBytesCapture=%ld != mappedSizeInBytesCapture=%ld\n", lockSizeInBytesCapture, mappedSizeInBytesCapture);
11753  }
11754  #endif
11755 
11756  ma_device__send_frames_to_client(pDevice, mappedSizeInBytesCapture/bpfDeviceCapture, pMappedDeviceBufferCapture);
11757 
11758  hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedDeviceBufferCapture, mappedSizeInBytesCapture, NULL, 0);
11759  if (FAILED(hr)) {
11760  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from capture device after reading from the device.", ma_result_from_HRESULT(hr));
11761  }
11762  prevReadCursorInBytesCapture = lockOffsetInBytesCapture + mappedSizeInBytesCapture;
11763 
11764  if (prevReadCursorInBytesCapture == (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture)) {
11765  prevReadCursorInBytesCapture = 0;
11766  }
11767  } break;
11768 
11769 
11770 
11772  {
11773  DWORD availableBytesPlayback;
11774  DWORD physicalPlayCursorInBytes;
11775  DWORD physicalWriteCursorInBytes;
11776  hr = ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes);
11777  if (FAILED(hr)) {
11778  break;
11779  }
11780 
11781  if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
11782  physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
11783  }
11784  prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
11785 
11786  /* If there's any bytes available for writing we can do that now. The space between the virtual cursor position and play cursor. */
11787  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11788  /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
11789  if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
11790  availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
11791  availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
11792  } else {
11793  /* This is an error. */
11794  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11795  availableBytesPlayback = 0;
11796  }
11797  } else {
11798  /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
11799  if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
11800  availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11801  } else {
11802  /* This is an error. */
11803  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11804  availableBytesPlayback = 0;
11805  }
11806  }
11807 
11808  /* If there's no room available for writing we need to wait for more. */
11809  if (availableBytesPlayback < pDevice->playback.internalPeriodSizeInFrames) {
11810  /* If we haven't started the device yet, this will never get beyond 0. In this case we need to get the device started. */
11811  if (availableBytesPlayback == 0 && !isPlaybackDeviceStarted) {
11812  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
11813  if (FAILED(hr)) {
11814  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
11815  }
11816  isPlaybackDeviceStarted = MA_TRUE;
11817  } else {
11818  ma_sleep(waitTimeInMilliseconds);
11819  continue;
11820  }
11821  }
11822 
11823  /* Getting here means there room available somewhere. We limit this to either the end of the buffer or the physical play cursor, whichever is closest. */
11824  lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
11825  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11826  /* Same loop iteration. Go up to the end of the buffer. */
11827  lockSizeInBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
11828  } else {
11829  /* Different loop iterations. Go up to the physical play cursor. */
11830  lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11831  }
11832 
11833  hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedDeviceBufferPlayback, &mappedSizeInBytesPlayback, NULL, NULL, 0);
11834  if (FAILED(hr)) {
11835  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from playback device in preparation for writing to the device.", ma_result_from_HRESULT(hr));
11836  break;
11837  }
11838 
11839  /* At this point we have a buffer for output. */
11840  ma_device__read_frames_from_client(pDevice, (mappedSizeInBytesPlayback/bpfDevicePlayback), pMappedDeviceBufferPlayback);
11841 
11842  hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedDeviceBufferPlayback, mappedSizeInBytesPlayback, NULL, 0);
11843  if (FAILED(hr)) {
11844  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from playback device after writing to the device.", ma_result_from_HRESULT(hr));
11845  break;
11846  }
11847 
11848  virtualWriteCursorInBytesPlayback += mappedSizeInBytesPlayback;
11849  if (virtualWriteCursorInBytesPlayback == pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) {
11850  virtualWriteCursorInBytesPlayback = 0;
11851  virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
11852  }
11853 
11854  /*
11855  We may need to start the device. We want two full periods to be written before starting the playback device. Having an extra period adds
11856  a bit of a buffer to prevent the playback buffer from getting starved.
11857  */
11858  framesWrittenToPlaybackDevice += mappedSizeInBytesPlayback/bpfDevicePlayback;
11859  if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= pDevice->playback.internalPeriodSizeInFrames) {
11860  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
11861  if (FAILED(hr)) {
11862  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
11863  }
11864  isPlaybackDeviceStarted = MA_TRUE;
11865  }
11866  } break;
11867 
11868 
11869  default: return MA_INVALID_ARGS; /* Invalid device type. */
11870  }
11871 
11872  if (result != MA_SUCCESS) {
11873  return result;
11874  }
11875  }
11876 
11877  /* Getting here means the device is being stopped. */
11878  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
11879  hr = ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11880  if (FAILED(hr)) {
11881  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCaptureBuffer_Stop() failed.", ma_result_from_HRESULT(hr));
11882  }
11883  }
11884 
11885  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
11886  /* The playback device should be drained before stopping. All we do is wait until the available bytes is equal to the size of the buffer. */
11887  if (isPlaybackDeviceStarted) {
11888  for (;;) {
11889  DWORD availableBytesPlayback = 0;
11890  DWORD physicalPlayCursorInBytes;
11891  DWORD physicalWriteCursorInBytes;
11892  hr = ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes);
11893  if (FAILED(hr)) {
11894  break;
11895  }
11896 
11897  if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
11898  physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
11899  }
11900  prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
11901 
11902  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11903  /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
11904  if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
11905  availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
11906  availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
11907  } else {
11908  break;
11909  }
11910  } else {
11911  /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
11912  if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
11913  availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11914  } else {
11915  break;
11916  }
11917  }
11918 
11919  if (availableBytesPlayback >= (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback)) {
11920  break;
11921  }
11922 
11923  ma_sleep(waitTimeInMilliseconds);
11924  }
11925  }
11926 
11927  hr = ma_IDirectSoundBuffer_Stop((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
11928  if (FAILED(hr)) {
11929  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Stop() failed.", ma_result_from_HRESULT(hr));
11930  }
11931 
11932  ma_IDirectSoundBuffer_SetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0);
11933  }
11934 
11935  return MA_SUCCESS;
11936 }
11937 
11938 static ma_result ma_context_uninit__dsound(ma_context* pContext)
11939 {
11940  MA_ASSERT(pContext != NULL);
11941  MA_ASSERT(pContext->backend == ma_backend_dsound);
11942 
11943  ma_dlclose(pContext, pContext->dsound.hDSoundDLL);
11944 
11945  return MA_SUCCESS;
11946 }
11947 
11948 static ma_result ma_context_init__dsound(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
11949 {
11950  MA_ASSERT(pContext != NULL);
11951 
11952  (void)pConfig;
11953 
11954  pContext->dsound.hDSoundDLL = ma_dlopen(pContext, "dsound.dll");
11955  if (pContext->dsound.hDSoundDLL == NULL) {
11956  return MA_API_NOT_FOUND;
11957  }
11958 
11959  pContext->dsound.DirectSoundCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCreate");
11960  pContext->dsound.DirectSoundEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundEnumerateA");
11961  pContext->dsound.DirectSoundCaptureCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCaptureCreate");
11962  pContext->dsound.DirectSoundCaptureEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCaptureEnumerateA");
11963 
11964  pCallbacks->onContextInit = ma_context_init__dsound;
11965  pCallbacks->onContextUninit = ma_context_uninit__dsound;
11966  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__dsound;
11967  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__dsound;
11968  pCallbacks->onDeviceInit = ma_device_init__dsound;
11969  pCallbacks->onDeviceUninit = ma_device_uninit__dsound;
11970  pCallbacks->onDeviceStart = NULL; /* Not used. Started in onDeviceDataLoop. */
11971  pCallbacks->onDeviceStop = NULL; /* Not used. Stopped in onDeviceDataLoop. */
11972  pCallbacks->onDeviceRead = NULL; /* Not used. Data is read directly in onDeviceDataLoop. */
11973  pCallbacks->onDeviceWrite = NULL; /* Not used. Data is written directly in onDeviceDataLoop. */
11974  pCallbacks->onDeviceDataLoop = ma_device_data_loop__dsound;
11975 
11976  return MA_SUCCESS;
11977 }
11978 #endif
11979 
11980 
11981 
11982 /******************************************************************************
11983 
11984 WinMM Backend
11985 
11986 ******************************************************************************/
11987 #ifdef MA_HAS_WINMM
11988 
11989 /*
11990 Some older compilers don't have WAVEOUTCAPS2A and WAVEINCAPS2A, so we'll need to write this ourselves. These structures
11991 are exactly the same as the older ones but they have a few GUIDs for manufacturer/product/name identification. I'm keeping
11992 the names the same as the Win32 library for consistency, but namespaced to avoid naming conflicts with the Win32 version.
11993 */
11994 typedef struct
11995 {
11996  WORD wMid;
11997  WORD wPid;
11998  MMVERSION vDriverVersion;
11999  CHAR szPname[MAXPNAMELEN];
12000  DWORD dwFormats;
12001  WORD wChannels;
12002  WORD wReserved1;
12003  DWORD dwSupport;
12004  GUID ManufacturerGuid;
12005  GUID ProductGuid;
12006  GUID NameGuid;
12007 } MA_WAVEOUTCAPS2A;
12008 typedef struct
12009 {
12010  WORD wMid;
12011  WORD wPid;
12012  MMVERSION vDriverVersion;
12013  CHAR szPname[MAXPNAMELEN];
12014  DWORD dwFormats;
12015  WORD wChannels;
12016  WORD wReserved1;
12017  GUID ManufacturerGuid;
12018  GUID ProductGuid;
12019  GUID NameGuid;
12020 } MA_WAVEINCAPS2A;
12021 
12022 typedef UINT (WINAPI * MA_PFN_waveOutGetNumDevs)(void);
12023 typedef MMRESULT (WINAPI * MA_PFN_waveOutGetDevCapsA)(ma_uintptr uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc);
12024 typedef MMRESULT (WINAPI * MA_PFN_waveOutOpen)(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
12025 typedef MMRESULT (WINAPI * MA_PFN_waveOutClose)(HWAVEOUT hwo);
12026 typedef MMRESULT (WINAPI * MA_PFN_waveOutPrepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
12027 typedef MMRESULT (WINAPI * MA_PFN_waveOutUnprepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
12028 typedef MMRESULT (WINAPI * MA_PFN_waveOutWrite)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
12029 typedef MMRESULT (WINAPI * MA_PFN_waveOutReset)(HWAVEOUT hwo);
12030 typedef UINT (WINAPI * MA_PFN_waveInGetNumDevs)(void);
12031 typedef MMRESULT (WINAPI * MA_PFN_waveInGetDevCapsA)(ma_uintptr uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic);
12032 typedef MMRESULT (WINAPI * MA_PFN_waveInOpen)(LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
12033 typedef MMRESULT (WINAPI * MA_PFN_waveInClose)(HWAVEIN hwi);
12034 typedef MMRESULT (WINAPI * MA_PFN_waveInPrepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
12035 typedef MMRESULT (WINAPI * MA_PFN_waveInUnprepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
12036 typedef MMRESULT (WINAPI * MA_PFN_waveInAddBuffer)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
12037 typedef MMRESULT (WINAPI * MA_PFN_waveInStart)(HWAVEIN hwi);
12038 typedef MMRESULT (WINAPI * MA_PFN_waveInReset)(HWAVEIN hwi);
12039 
12040 static ma_result ma_result_from_MMRESULT(MMRESULT resultMM)
12041 {
12042  switch (resultMM) {
12043  case MMSYSERR_NOERROR: return MA_SUCCESS;
12044  case MMSYSERR_BADDEVICEID: return MA_INVALID_ARGS;
12045  case MMSYSERR_INVALHANDLE: return MA_INVALID_ARGS;
12046  case MMSYSERR_NOMEM: return MA_OUT_OF_MEMORY;
12047  case MMSYSERR_INVALFLAG: return MA_INVALID_ARGS;
12048  case MMSYSERR_INVALPARAM: return MA_INVALID_ARGS;
12049  case MMSYSERR_HANDLEBUSY: return MA_BUSY;
12050  case MMSYSERR_ERROR: return MA_ERROR;
12051  default: return MA_ERROR;
12052  }
12053 }
12054 
12055 static char* ma_find_last_character(char* str, char ch)
12056 {
12057  char* last;
12058 
12059  if (str == NULL) {
12060  return NULL;
12061  }
12062 
12063  last = NULL;
12064  while (*str != '\0') {
12065  if (*str == ch) {
12066  last = str;
12067  }
12068 
12069  str += 1;
12070  }
12071 
12072  return last;
12073 }
12074 
12075 static ma_uint32 ma_get_period_size_in_bytes(ma_uint32 periodSizeInFrames, ma_format format, ma_uint32 channels)
12076 {
12077  return periodSizeInFrames * ma_get_bytes_per_frame(format, channels);
12078 }
12079 
12080 
12081 /*
12082 Our own "WAVECAPS" structure that contains generic information shared between WAVEOUTCAPS2 and WAVEINCAPS2 so
12083 we can do things generically and typesafely. Names are being kept the same for consistency.
12084 */
12085 typedef struct
12086 {
12087  CHAR szPname[MAXPNAMELEN];
12088  DWORD dwFormats;
12089  WORD wChannels;
12090  GUID NameGuid;
12091 } MA_WAVECAPSA;
12092 
12093 static ma_result ma_get_best_info_from_formats_flags__winmm(DWORD dwFormats, WORD channels, WORD* pBitsPerSample, DWORD* pSampleRate)
12094 {
12095  WORD bitsPerSample = 0;
12096  DWORD sampleRate = 0;
12097 
12098  if (pBitsPerSample) {
12099  *pBitsPerSample = 0;
12100  }
12101  if (pSampleRate) {
12102  *pSampleRate = 0;
12103  }
12104 
12105  if (channels == 1) {
12106  bitsPerSample = 16;
12107  if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
12108  sampleRate = 48000;
12109  } else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
12110  sampleRate = 44100;
12111  } else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
12112  sampleRate = 22050;
12113  } else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
12114  sampleRate = 11025;
12115  } else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
12116  sampleRate = 96000;
12117  } else {
12118  bitsPerSample = 8;
12119  if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
12120  sampleRate = 48000;
12121  } else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
12122  sampleRate = 44100;
12123  } else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
12124  sampleRate = 22050;
12125  } else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
12126  sampleRate = 11025;
12127  } else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
12128  sampleRate = 96000;
12129  } else {
12130  return MA_FORMAT_NOT_SUPPORTED;
12131  }
12132  }
12133  } else {
12134  bitsPerSample = 16;
12135  if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
12136  sampleRate = 48000;
12137  } else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
12138  sampleRate = 44100;
12139  } else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
12140  sampleRate = 22050;
12141  } else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
12142  sampleRate = 11025;
12143  } else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
12144  sampleRate = 96000;
12145  } else {
12146  bitsPerSample = 8;
12147  if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
12148  sampleRate = 48000;
12149  } else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
12150  sampleRate = 44100;
12151  } else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
12152  sampleRate = 22050;
12153  } else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
12154  sampleRate = 11025;
12155  } else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
12156  sampleRate = 96000;
12157  } else {
12158  return MA_FORMAT_NOT_SUPPORTED;
12159  }
12160  }
12161  }
12162 
12163  if (pBitsPerSample) {
12164  *pBitsPerSample = bitsPerSample;
12165  }
12166  if (pSampleRate) {
12167  *pSampleRate = sampleRate;
12168  }
12169 
12170  return MA_SUCCESS;
12171 }
12172 
12173 static ma_result ma_formats_flags_to_WAVEFORMATEX__winmm(DWORD dwFormats, WORD channels, WAVEFORMATEX* pWF)
12174 {
12175  ma_result result;
12176 
12177  MA_ASSERT(pWF != NULL);
12178 
12179  MA_ZERO_OBJECT(pWF);
12180  pWF->cbSize = sizeof(*pWF);
12181  pWF->wFormatTag = WAVE_FORMAT_PCM;
12182  pWF->nChannels = (WORD)channels;
12183  if (pWF->nChannels > 2) {
12184  pWF->nChannels = 2;
12185  }
12186 
12187  result = ma_get_best_info_from_formats_flags__winmm(dwFormats, channels, &pWF->wBitsPerSample, &pWF->nSamplesPerSec);
12188  if (result != MA_SUCCESS) {
12189  return result;
12190  }
12191 
12192  pWF->nBlockAlign = (WORD)(pWF->nChannels * pWF->wBitsPerSample / 8);
12193  pWF->nAvgBytesPerSec = pWF->nBlockAlign * pWF->nSamplesPerSec;
12194 
12195  return MA_SUCCESS;
12196 }
12197 
12198 static ma_result ma_context_get_device_info_from_WAVECAPS(ma_context* pContext, MA_WAVECAPSA* pCaps, ma_device_info* pDeviceInfo)
12199 {
12200  WORD bitsPerSample;
12201  DWORD sampleRate;
12202  ma_result result;
12203 
12204  MA_ASSERT(pContext != NULL);
12205  MA_ASSERT(pCaps != NULL);
12206  MA_ASSERT(pDeviceInfo != NULL);
12207 
12208  /*
12209  Name / Description
12210 
12211  Unfortunately the name specified in WAVE(OUT/IN)CAPS2 is limited to 31 characters. This results in an unprofessional looking
12212  situation where the names of the devices are truncated. To help work around this, we need to look at the name GUID and try
12213  looking in the registry for the full name. If we can't find it there, we need to just fall back to the default name.
12214  */
12215 
12216  /* Set the default to begin with. */
12217  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), pCaps->szPname, (size_t)-1);
12218 
12219  /*
12220  Now try the registry. There's a few things to consider here:
12221  - The name GUID can be null, in which we case we just need to stick to the original 31 characters.
12222  - If the name GUID is not present in the registry we'll also need to stick to the original 31 characters.
12223  - I like consistency, so I want the returned device names to be consistent with those returned by WASAPI and DirectSound. The
12224  problem, however is that WASAPI and DirectSound use "<component> (<name>)" format (such as "Speakers (High Definition Audio)"),
12225  but WinMM does not specificy the component name. From my admittedly limited testing, I've notice the component name seems to
12226  usually fit within the 31 characters of the fixed sized buffer, so what I'm going to do is parse that string for the component
12227  name, and then concatenate the name from the registry.
12228  */
12229  if (!ma_is_guid_null(&pCaps->NameGuid)) {
12230  wchar_t guidStrW[256];
12231  if (((MA_PFN_StringFromGUID2)pContext->win32.StringFromGUID2)(&pCaps->NameGuid, guidStrW, ma_countof(guidStrW)) > 0) {
12232  char guidStr[256];
12233  char keyStr[1024];
12234  HKEY hKey;
12235 
12236  WideCharToMultiByte(CP_UTF8, 0, guidStrW, -1, guidStr, sizeof(guidStr), 0, FALSE);
12237 
12238  ma_strcpy_s(keyStr, sizeof(keyStr), "SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
12239  ma_strcat_s(keyStr, sizeof(keyStr), guidStr);
12240 
12241  if (((MA_PFN_RegOpenKeyExA)pContext->win32.RegOpenKeyExA)(HKEY_LOCAL_MACHINE, keyStr, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
12242  BYTE nameFromReg[512];
12243  DWORD nameFromRegSize = sizeof(nameFromReg);
12244  result = ((MA_PFN_RegQueryValueExA)pContext->win32.RegQueryValueExA)(hKey, "Name", 0, NULL, (LPBYTE)nameFromReg, (LPDWORD)&nameFromRegSize);
12245  ((MA_PFN_RegCloseKey)pContext->win32.RegCloseKey)(hKey);
12246 
12247  if (result == ERROR_SUCCESS) {
12248  /* We have the value from the registry, so now we need to construct the name string. */
12249  char name[1024];
12250  if (ma_strcpy_s(name, sizeof(name), pDeviceInfo->name) == 0) {
12251  char* nameBeg = ma_find_last_character(name, '(');
12252  if (nameBeg != NULL) {
12253  size_t leadingLen = (nameBeg - name);
12254  ma_strncpy_s(nameBeg + 1, sizeof(name) - leadingLen, (const char*)nameFromReg, (size_t)-1);
12255 
12256  /* The closing ")", if it can fit. */
12257  if (leadingLen + nameFromRegSize < sizeof(name)-1) {
12258  ma_strcat_s(name, sizeof(name), ")");
12259  }
12260 
12261  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), name, (size_t)-1);
12262  }
12263  }
12264  }
12265  }
12266  }
12267  }
12268 
12269 
12270  result = ma_get_best_info_from_formats_flags__winmm(pCaps->dwFormats, pCaps->wChannels, &bitsPerSample, &sampleRate);
12271  if (result != MA_SUCCESS) {
12272  return result;
12273  }
12274 
12275  if (bitsPerSample == 8) {
12276  pDeviceInfo->nativeDataFormats[0].format = ma_format_u8;
12277  } else if (bitsPerSample == 16) {
12278  pDeviceInfo->nativeDataFormats[0].format = ma_format_s16;
12279  } else if (bitsPerSample == 24) {
12280  pDeviceInfo->nativeDataFormats[0].format = ma_format_s24;
12281  } else if (bitsPerSample == 32) {
12282  pDeviceInfo->nativeDataFormats[0].format = ma_format_s32;
12283  } else {
12284  return MA_FORMAT_NOT_SUPPORTED;
12285  }
12286  pDeviceInfo->nativeDataFormats[0].channels = pCaps->wChannels;
12287  pDeviceInfo->nativeDataFormats[0].sampleRate = sampleRate;
12288  pDeviceInfo->nativeDataFormats[0].flags = 0;
12289  pDeviceInfo->nativeDataFormatCount = 1;
12290 
12291  return MA_SUCCESS;
12292 }
12293 
12294 static ma_result ma_context_get_device_info_from_WAVEOUTCAPS2(ma_context* pContext, MA_WAVEOUTCAPS2A* pCaps, ma_device_info* pDeviceInfo)
12295 {
12296  MA_WAVECAPSA caps;
12297 
12298  MA_ASSERT(pContext != NULL);
12299  MA_ASSERT(pCaps != NULL);
12300  MA_ASSERT(pDeviceInfo != NULL);
12301 
12302  MA_COPY_MEMORY(caps.szPname, pCaps->szPname, sizeof(caps.szPname));
12303  caps.dwFormats = pCaps->dwFormats;
12304  caps.wChannels = pCaps->wChannels;
12305  caps.NameGuid = pCaps->NameGuid;
12306  return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
12307 }
12308 
12309 static ma_result ma_context_get_device_info_from_WAVEINCAPS2(ma_context* pContext, MA_WAVEINCAPS2A* pCaps, ma_device_info* pDeviceInfo)
12310 {
12311  MA_WAVECAPSA caps;
12312 
12313  MA_ASSERT(pContext != NULL);
12314  MA_ASSERT(pCaps != NULL);
12315  MA_ASSERT(pDeviceInfo != NULL);
12316 
12317  MA_COPY_MEMORY(caps.szPname, pCaps->szPname, sizeof(caps.szPname));
12318  caps.dwFormats = pCaps->dwFormats;
12319  caps.wChannels = pCaps->wChannels;
12320  caps.NameGuid = pCaps->NameGuid;
12321  return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
12322 }
12323 
12324 
12325 static ma_result ma_context_enumerate_devices__winmm(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
12326 {
12327  UINT playbackDeviceCount;
12328  UINT captureDeviceCount;
12329  UINT iPlaybackDevice;
12330  UINT iCaptureDevice;
12331 
12332  MA_ASSERT(pContext != NULL);
12333  MA_ASSERT(callback != NULL);
12334 
12335  /* Playback. */
12336  playbackDeviceCount = ((MA_PFN_waveOutGetNumDevs)pContext->winmm.waveOutGetNumDevs)();
12337  for (iPlaybackDevice = 0; iPlaybackDevice < playbackDeviceCount; ++iPlaybackDevice) {
12338  MMRESULT result;
12339  MA_WAVEOUTCAPS2A caps;
12340 
12341  MA_ZERO_OBJECT(&caps);
12342 
12343  result = ((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(iPlaybackDevice, (WAVEOUTCAPSA*)&caps, sizeof(caps));
12344  if (result == MMSYSERR_NOERROR) {
12345  ma_device_info deviceInfo;
12346 
12347  MA_ZERO_OBJECT(&deviceInfo);
12348  deviceInfo.id.winmm = iPlaybackDevice;
12349 
12350  /* The first enumerated device is the default device. */
12351  if (iPlaybackDevice == 0) {
12352  deviceInfo.isDefault = MA_TRUE;
12353  }
12354 
12355  if (ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, &deviceInfo) == MA_SUCCESS) {
12356  ma_bool32 cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
12357  if (cbResult == MA_FALSE) {
12358  return MA_SUCCESS; /* Enumeration was stopped. */
12359  }
12360  }
12361  }
12362  }
12363 
12364  /* Capture. */
12365  captureDeviceCount = ((MA_PFN_waveInGetNumDevs)pContext->winmm.waveInGetNumDevs)();
12366  for (iCaptureDevice = 0; iCaptureDevice < captureDeviceCount; ++iCaptureDevice) {
12367  MMRESULT result;
12368  MA_WAVEINCAPS2A caps;
12369 
12370  MA_ZERO_OBJECT(&caps);
12371 
12372  result = ((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(iCaptureDevice, (WAVEINCAPSA*)&caps, sizeof(caps));
12373  if (result == MMSYSERR_NOERROR) {
12374  ma_device_info deviceInfo;
12375 
12376  MA_ZERO_OBJECT(&deviceInfo);
12377  deviceInfo.id.winmm = iCaptureDevice;
12378 
12379  /* The first enumerated device is the default device. */
12380  if (iCaptureDevice == 0) {
12381  deviceInfo.isDefault = MA_TRUE;
12382  }
12383 
12384  if (ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, &deviceInfo) == MA_SUCCESS) {
12385  ma_bool32 cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
12386  if (cbResult == MA_FALSE) {
12387  return MA_SUCCESS; /* Enumeration was stopped. */
12388  }
12389  }
12390  }
12391  }
12392 
12393  return MA_SUCCESS;
12394 }
12395 
12396 static ma_result ma_context_get_device_info__winmm(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
12397 {
12398  UINT winMMDeviceID;
12399 
12400  MA_ASSERT(pContext != NULL);
12401 
12402  winMMDeviceID = 0;
12403  if (pDeviceID != NULL) {
12404  winMMDeviceID = (UINT)pDeviceID->winmm;
12405  }
12406 
12407  pDeviceInfo->id.winmm = winMMDeviceID;
12408 
12409  /* The first ID is the default device. */
12410  if (winMMDeviceID == 0) {
12411  pDeviceInfo->isDefault = MA_TRUE;
12412  }
12413 
12414  if (deviceType == ma_device_type_playback) {
12415  MMRESULT result;
12416  MA_WAVEOUTCAPS2A caps;
12417 
12418  MA_ZERO_OBJECT(&caps);
12419 
12420  result = ((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(winMMDeviceID, (WAVEOUTCAPSA*)&caps, sizeof(caps));
12421  if (result == MMSYSERR_NOERROR) {
12422  return ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, pDeviceInfo);
12423  }
12424  } else {
12425  MMRESULT result;
12426  MA_WAVEINCAPS2A caps;
12427 
12428  MA_ZERO_OBJECT(&caps);
12429 
12430  result = ((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(winMMDeviceID, (WAVEINCAPSA*)&caps, sizeof(caps));
12431  if (result == MMSYSERR_NOERROR) {
12432  return ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, pDeviceInfo);
12433  }
12434  }
12435 
12436  return MA_NO_DEVICE;
12437 }
12438 
12439 
12440 static ma_result ma_device_uninit__winmm(ma_device* pDevice)
12441 {
12442  MA_ASSERT(pDevice != NULL);
12443 
12444  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
12445  ((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12446  CloseHandle((HANDLE)pDevice->winmm.hEventCapture);
12447  }
12448 
12449  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
12450  ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
12451  ((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
12452  CloseHandle((HANDLE)pDevice->winmm.hEventPlayback);
12453  }
12454 
12455  ma__free_from_callbacks(pDevice->winmm._pHeapData, &pDevice->pContext->allocationCallbacks);
12456 
12457  MA_ZERO_OBJECT(&pDevice->winmm); /* Safety. */
12458 
12459  return MA_SUCCESS;
12460 }
12461 
12462 static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__winmm(const ma_device_descriptor* pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
12463 {
12464  /* WinMM has a minimum period size of 40ms. */
12465  ma_uint32 minPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(40, nativeSampleRate);
12466  ma_uint32 periodSizeInFrames;
12467 
12468  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, nativeSampleRate, performanceProfile);
12469  if (periodSizeInFrames < minPeriodSizeInFrames) {
12470  periodSizeInFrames = minPeriodSizeInFrames;
12471  }
12472 
12473  return periodSizeInFrames;
12474 }
12475 
12476 static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
12477 {
12478  const char* errorMsg = "";
12479  ma_result errorCode = MA_ERROR;
12480  ma_result result = MA_SUCCESS;
12481  ma_uint32 heapSize;
12482  UINT winMMDeviceIDPlayback = 0;
12483  UINT winMMDeviceIDCapture = 0;
12484 
12485  MA_ASSERT(pDevice != NULL);
12486 
12487  MA_ZERO_OBJECT(&pDevice->winmm);
12488 
12489  if (pConfig->deviceType == ma_device_type_loopback) {
12491  }
12492 
12493  /* No exlusive mode with WinMM. */
12494  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
12495  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
12497  }
12498 
12499  if (pDescriptorPlayback->pDeviceID != NULL) {
12500  winMMDeviceIDPlayback = (UINT)pDescriptorPlayback->pDeviceID->winmm;
12501  }
12502  if (pDescriptorCapture->pDeviceID != NULL) {
12503  winMMDeviceIDCapture = (UINT)pDescriptorCapture->pDeviceID->winmm;
12504  }
12505 
12506  /* The capture device needs to be initialized first. */
12507  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
12508  WAVEINCAPSA caps;
12509  WAVEFORMATEX wf;
12510  MMRESULT resultMM;
12511 
12512  /* We use an event to know when a new fragment needs to be enqueued. */
12513  pDevice->winmm.hEventCapture = (ma_handle)CreateEventW(NULL, TRUE, TRUE, NULL);
12514  if (pDevice->winmm.hEventCapture == NULL) {
12515  errorMsg = "[WinMM] Failed to create event for fragment enqueing for the capture device.", errorCode = ma_result_from_GetLastError(GetLastError());
12516  goto on_error;
12517  }
12518 
12519  /* The format should be based on the device's actual format. */
12520  if (((MA_PFN_waveInGetDevCapsA)pDevice->pContext->winmm.waveInGetDevCapsA)(winMMDeviceIDCapture, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
12521  errorMsg = "[WinMM] Failed to retrieve internal device caps.", errorCode = MA_FORMAT_NOT_SUPPORTED;
12522  goto on_error;
12523  }
12524 
12525  result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
12526  if (result != MA_SUCCESS) {
12527  errorMsg = "[WinMM] Could not find appropriate format for internal device.", errorCode = result;
12528  goto on_error;
12529  }
12530 
12531  resultMM = ((MA_PFN_waveInOpen)pDevice->pContext->winmm.waveInOpen)((LPHWAVEIN)&pDevice->winmm.hDeviceCapture, winMMDeviceIDCapture, &wf, (DWORD_PTR)pDevice->winmm.hEventCapture, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
12532  if (resultMM != MMSYSERR_NOERROR) {
12533  errorMsg = "[WinMM] Failed to open capture device.", errorCode = MA_FAILED_TO_OPEN_BACKEND_DEVICE;
12534  goto on_error;
12535  }
12536 
12537  pDescriptorCapture->format = ma_format_from_WAVEFORMATEX(&wf);
12538  pDescriptorCapture->channels = wf.nChannels;
12539  pDescriptorCapture->sampleRate = wf.nSamplesPerSec;
12540  ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
12541  pDescriptorCapture->periodCount = pDescriptorCapture->periodCount;
12542  pDescriptorCapture->periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__winmm(pDescriptorCapture, pDescriptorCapture->sampleRate, pConfig->performanceProfile);
12543  }
12544 
12545  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
12546  WAVEOUTCAPSA caps;
12547  WAVEFORMATEX wf;
12548  MMRESULT resultMM;
12549 
12550  /* We use an event to know when a new fragment needs to be enqueued. */
12551  pDevice->winmm.hEventPlayback = (ma_handle)CreateEvent(NULL, TRUE, TRUE, NULL);
12552  if (pDevice->winmm.hEventPlayback == NULL) {
12553  errorMsg = "[WinMM] Failed to create event for fragment enqueing for the playback device.", errorCode = ma_result_from_GetLastError(GetLastError());
12554  goto on_error;
12555  }
12556 
12557  /* The format should be based on the device's actual format. */
12558  if (((MA_PFN_waveOutGetDevCapsA)pDevice->pContext->winmm.waveOutGetDevCapsA)(winMMDeviceIDPlayback, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
12559  errorMsg = "[WinMM] Failed to retrieve internal device caps.", errorCode = MA_FORMAT_NOT_SUPPORTED;
12560  goto on_error;
12561  }
12562 
12563  result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
12564  if (result != MA_SUCCESS) {
12565  errorMsg = "[WinMM] Could not find appropriate format for internal device.", errorCode = result;
12566  goto on_error;
12567  }
12568 
12569  resultMM = ((MA_PFN_waveOutOpen)pDevice->pContext->winmm.waveOutOpen)((LPHWAVEOUT)&pDevice->winmm.hDevicePlayback, winMMDeviceIDPlayback, &wf, (DWORD_PTR)pDevice->winmm.hEventPlayback, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
12570  if (resultMM != MMSYSERR_NOERROR) {
12571  errorMsg = "[WinMM] Failed to open playback device.", errorCode = MA_FAILED_TO_OPEN_BACKEND_DEVICE;
12572  goto on_error;
12573  }
12574 
12575  pDescriptorPlayback->format = ma_format_from_WAVEFORMATEX(&wf);
12576  pDescriptorPlayback->channels = wf.nChannels;
12577  pDescriptorPlayback->sampleRate = wf.nSamplesPerSec;
12578  ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
12579  pDescriptorPlayback->periodCount = pDescriptorPlayback->periodCount;
12580  pDescriptorPlayback->periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__winmm(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
12581  }
12582 
12583  /*
12584  The heap allocated data is allocated like so:
12585 
12586  [Capture WAVEHDRs][Playback WAVEHDRs][Capture Intermediary Buffer][Playback Intermediary Buffer]
12587  */
12588  heapSize = 0;
12589  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
12590  heapSize += sizeof(WAVEHDR)*pDescriptorCapture->periodCount + (pDescriptorCapture->periodSizeInFrames * pDescriptorCapture->periodCount * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
12591  }
12592  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
12593  heapSize += sizeof(WAVEHDR)*pDescriptorPlayback->periodCount + (pDescriptorPlayback->periodSizeInFrames * pDescriptorPlayback->periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels));
12594  }
12595 
12596  pDevice->winmm._pHeapData = (ma_uint8*)ma__calloc_from_callbacks(heapSize, &pDevice->pContext->allocationCallbacks);
12597  if (pDevice->winmm._pHeapData == NULL) {
12598  errorMsg = "[WinMM] Failed to allocate memory for the intermediary buffer.", errorCode = MA_OUT_OF_MEMORY;
12599  goto on_error;
12600  }
12601 
12602  MA_ZERO_MEMORY(pDevice->winmm._pHeapData, heapSize);
12603 
12604  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
12605  ma_uint32 iPeriod;
12606 
12607  if (pConfig->deviceType == ma_device_type_capture) {
12608  pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
12609  pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount));
12610  } else {
12611  pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
12612  pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount));
12613  }
12614 
12615  /* Prepare headers. */
12616  for (iPeriod = 0; iPeriod < pDescriptorCapture->periodCount; ++iPeriod) {
12617  ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDescriptorCapture->periodSizeInFrames, pDescriptorCapture->format, pDescriptorCapture->channels);
12618 
12619  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferCapture + (periodSizeInBytes*iPeriod));
12620  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwBufferLength = periodSizeInBytes;
12621  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwFlags = 0L;
12622  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwLoops = 0L;
12623  ((MA_PFN_waveInPrepareHeader)pDevice->pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
12624 
12625  /*
12626  The user data of the WAVEHDR structure is a single flag the controls whether or not it is ready for writing. Consider it to be named "isLocked". A value of 0 means
12627  it's unlocked and available for writing. A value of 1 means it's locked.
12628  */
12629  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwUser = 0;
12630  }
12631  }
12632 
12633  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
12634  ma_uint32 iPeriod;
12635 
12636  if (pConfig->deviceType == ma_device_type_playback) {
12637  pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData;
12638  pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*pDescriptorPlayback->periodCount);
12639  } else {
12640  pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount));
12641  pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount)) + (pDescriptorCapture->periodSizeInFrames*pDescriptorCapture->periodCount*ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
12642  }
12643 
12644  /* Prepare headers. */
12645  for (iPeriod = 0; iPeriod < pDescriptorPlayback->periodCount; ++iPeriod) {
12646  ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDescriptorPlayback->periodSizeInFrames, pDescriptorPlayback->format, pDescriptorPlayback->channels);
12647 
12648  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferPlayback + (periodSizeInBytes*iPeriod));
12649  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwBufferLength = periodSizeInBytes;
12650  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwFlags = 0L;
12651  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwLoops = 0L;
12652  ((MA_PFN_waveOutPrepareHeader)pDevice->pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
12653 
12654  /*
12655  The user data of the WAVEHDR structure is a single flag the controls whether or not it is ready for writing. Consider it to be named "isLocked". A value of 0 means
12656  it's unlocked and available for writing. A value of 1 means it's locked.
12657  */
12658  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwUser = 0;
12659  }
12660  }
12661 
12662  return MA_SUCCESS;
12663 
12664 on_error:
12665  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
12666  if (pDevice->winmm.pWAVEHDRCapture != NULL) {
12667  ma_uint32 iPeriod;
12668  for (iPeriod = 0; iPeriod < pDescriptorCapture->periodCount; ++iPeriod) {
12669  ((MA_PFN_waveInUnprepareHeader)pDevice->pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
12670  }
12671  }
12672 
12673  ((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12674  }
12675 
12676  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
12677  if (pDevice->winmm.pWAVEHDRCapture != NULL) {
12678  ma_uint32 iPeriod;
12679  for (iPeriod = 0; iPeriod < pDescriptorPlayback->periodCount; ++iPeriod) {
12680  ((MA_PFN_waveOutUnprepareHeader)pDevice->pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
12681  }
12682  }
12683 
12684  ((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
12685  }
12686 
12687  ma__free_from_callbacks(pDevice->winmm._pHeapData, &pDevice->pContext->allocationCallbacks);
12688  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, errorMsg, errorCode);
12689 }
12690 
12691 static ma_result ma_device_start__winmm(ma_device* pDevice)
12692 {
12693  MA_ASSERT(pDevice != NULL);
12694 
12695  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
12696  MMRESULT resultMM;
12697  WAVEHDR* pWAVEHDR;
12698  ma_uint32 iPeriod;
12699 
12700  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
12701 
12702  /* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
12703  ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
12704 
12705  /* To start the device we attach all of the buffers and then start it. As the buffers are filled with data we will get notifications. */
12706  for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
12707  resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
12708  if (resultMM != MMSYSERR_NOERROR) {
12709  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to attach input buffers to capture device in preparation for capture.", ma_result_from_MMRESULT(resultMM));
12710  }
12711 
12712  /* Make sure all of the buffers start out locked. We don't want to access them until the backend tells us we can. */
12713  pWAVEHDR[iPeriod].dwUser = 1; /* 1 = locked. */
12714  }
12715 
12716  /* Capture devices need to be explicitly started, unlike playback devices. */
12717  resultMM = ((MA_PFN_waveInStart)pDevice->pContext->winmm.waveInStart)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12718  if (resultMM != MMSYSERR_NOERROR) {
12719  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to start backend device.", ma_result_from_MMRESULT(resultMM));
12720  }
12721  }
12722 
12723  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
12724  /* Don't need to do anything for playback. It'll be started automatically in ma_device_start__winmm(). */
12725  }
12726 
12727  return MA_SUCCESS;
12728 }
12729 
12730 static ma_result ma_device_stop__winmm(ma_device* pDevice)
12731 {
12732  MMRESULT resultMM;
12733 
12734  MA_ASSERT(pDevice != NULL);
12735 
12736  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
12737  if (pDevice->winmm.hDeviceCapture == NULL) {
12738  return MA_INVALID_ARGS;
12739  }
12740 
12741  resultMM = ((MA_PFN_waveInReset)pDevice->pContext->winmm.waveInReset)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12742  if (resultMM != MMSYSERR_NOERROR) {
12743  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] WARNING: Failed to reset capture device.", ma_result_from_MMRESULT(resultMM));
12744  }
12745  }
12746 
12747  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
12748  ma_uint32 iPeriod;
12749  WAVEHDR* pWAVEHDR;
12750 
12751  if (pDevice->winmm.hDevicePlayback == NULL) {
12752  return MA_INVALID_ARGS;
12753  }
12754 
12755  /* We need to drain the device. To do this we just loop over each header and if it's locked just wait for the event. */
12756  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback;
12757  for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; iPeriod += 1) {
12758  if (pWAVEHDR[iPeriod].dwUser == 1) { /* 1 = locked. */
12759  if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
12760  break; /* An error occurred so just abandon ship and stop the device without draining. */
12761  }
12762 
12763  pWAVEHDR[iPeriod].dwUser = 0;
12764  }
12765  }
12766 
12767  resultMM = ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
12768  if (resultMM != MMSYSERR_NOERROR) {
12769  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] WARNING: Failed to reset playback device.", ma_result_from_MMRESULT(resultMM));
12770  }
12771  }
12772 
12773  return MA_SUCCESS;
12774 }
12775 
12776 static ma_result ma_device_write__winmm(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
12777 {
12778  ma_result result = MA_SUCCESS;
12779  MMRESULT resultMM;
12780  ma_uint32 totalFramesWritten;
12781  WAVEHDR* pWAVEHDR;
12782 
12783  MA_ASSERT(pDevice != NULL);
12784  MA_ASSERT(pPCMFrames != NULL);
12785 
12786  if (pFramesWritten != NULL) {
12787  *pFramesWritten = 0;
12788  }
12789 
12790  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback;
12791 
12792  /* Keep processing as much data as possible. */
12793  totalFramesWritten = 0;
12794  while (totalFramesWritten < frameCount) {
12795  /* If the current header has some space available we need to write part of it. */
12796  if (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser == 0) { /* 0 = unlocked. */
12797  /*
12798  This header has room in it. We copy as much of it as we can. If we end up fully consuming the buffer we need to
12799  write it out and move on to the next iteration.
12800  */
12802  ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedPlayback;
12803 
12804  ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesWritten));
12805  const void* pSrc = ma_offset_ptr(pPCMFrames, totalFramesWritten*bpf);
12806  void* pDst = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].lpData, pDevice->winmm.headerFramesConsumedPlayback*bpf);
12807  MA_COPY_MEMORY(pDst, pSrc, framesToCopy*bpf);
12808 
12809  pDevice->winmm.headerFramesConsumedPlayback += framesToCopy;
12810  totalFramesWritten += framesToCopy;
12811 
12812  /* If we've consumed the buffer entirely we need to write it out to the device. */
12813  if (pDevice->winmm.headerFramesConsumedPlayback == (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf)) {
12814  pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 1; /* 1 = locked. */
12815  pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags &= ~WHDR_DONE; /* <-- Need to make sure the WHDR_DONE flag is unset. */
12816 
12817  /* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
12818  ResetEvent((HANDLE)pDevice->winmm.hEventPlayback);
12819 
12820  /* The device will be started here. */
12821  resultMM = ((MA_PFN_waveOutWrite)pDevice->pContext->winmm.waveOutWrite)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &pWAVEHDR[pDevice->winmm.iNextHeaderPlayback], sizeof(WAVEHDR));
12822  if (resultMM != MMSYSERR_NOERROR) {
12823  result = ma_result_from_MMRESULT(resultMM);
12824  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] waveOutWrite() failed.", result);
12825  break;
12826  }
12827 
12828  /* Make sure we move to the next header. */
12829  pDevice->winmm.iNextHeaderPlayback = (pDevice->winmm.iNextHeaderPlayback + 1) % pDevice->playback.internalPeriods;
12830  pDevice->winmm.headerFramesConsumedPlayback = 0;
12831  }
12832 
12833  /* If at this point we have consumed the entire input buffer we can return. */
12834  MA_ASSERT(totalFramesWritten <= frameCount);
12835  if (totalFramesWritten == frameCount) {
12836  break;
12837  }
12838 
12839  /* Getting here means there's more to process. */
12840  continue;
12841  }
12842 
12843  /* Getting here means there isn't enough room in the buffer and we need to wait for one to become available. */
12844  if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
12845  result = MA_ERROR;
12846  break;
12847  }
12848 
12849  /* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
12850  if ((pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags & WHDR_DONE) != 0) {
12851  pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 0; /* 0 = unlocked (make it available for writing). */
12852  pDevice->winmm.headerFramesConsumedPlayback = 0;
12853  }
12854 
12855  /* If the device has been stopped we need to break. */
12856  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
12857  break;
12858  }
12859  }
12860 
12861  if (pFramesWritten != NULL) {
12862  *pFramesWritten = totalFramesWritten;
12863  }
12864 
12865  return result;
12866 }
12867 
12868 static ma_result ma_device_read__winmm(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
12869 {
12870  ma_result result = MA_SUCCESS;
12871  MMRESULT resultMM;
12872  ma_uint32 totalFramesRead;
12873  WAVEHDR* pWAVEHDR;
12874 
12875  MA_ASSERT(pDevice != NULL);
12876  MA_ASSERT(pPCMFrames != NULL);
12877 
12878  if (pFramesRead != NULL) {
12879  *pFramesRead = 0;
12880  }
12881 
12882  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
12883 
12884  /* Keep processing as much data as possible. */
12885  totalFramesRead = 0;
12886  while (totalFramesRead < frameCount) {
12887  /* If the current header has some space available we need to write part of it. */
12888  if (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser == 0) { /* 0 = unlocked. */
12889  /* The buffer is available for reading. If we fully consume it we need to add it back to the buffer. */
12891  ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedCapture;
12892 
12893  ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesRead));
12894  const void* pSrc = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderCapture].lpData, pDevice->winmm.headerFramesConsumedCapture*bpf);
12895  void* pDst = ma_offset_ptr(pPCMFrames, totalFramesRead*bpf);
12896  MA_COPY_MEMORY(pDst, pSrc, framesToCopy*bpf);
12897 
12898  pDevice->winmm.headerFramesConsumedCapture += framesToCopy;
12899  totalFramesRead += framesToCopy;
12900 
12901  /* If we've consumed the buffer entirely we need to add it back to the device. */
12902  if (pDevice->winmm.headerFramesConsumedCapture == (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf)) {
12903  pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 1; /* 1 = locked. */
12904  pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags &= ~WHDR_DONE; /* <-- Need to make sure the WHDR_DONE flag is unset. */
12905 
12906  /* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
12907  ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
12908 
12909  /* The device will be started here. */
12910  resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[pDevice->winmm.iNextHeaderCapture], sizeof(WAVEHDR));
12911  if (resultMM != MMSYSERR_NOERROR) {
12912  result = ma_result_from_MMRESULT(resultMM);
12913  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] waveInAddBuffer() failed.", result);
12914  break;
12915  }
12916 
12917  /* Make sure we move to the next header. */
12918  pDevice->winmm.iNextHeaderCapture = (pDevice->winmm.iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
12919  pDevice->winmm.headerFramesConsumedCapture = 0;
12920  }
12921 
12922  /* If at this point we have filled the entire input buffer we can return. */
12923  MA_ASSERT(totalFramesRead <= frameCount);
12924  if (totalFramesRead == frameCount) {
12925  break;
12926  }
12927 
12928  /* Getting here means there's more to process. */
12929  continue;
12930  }
12931 
12932  /* Getting here means there isn't enough any data left to send to the client which means we need to wait for more. */
12933  if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
12934  result = MA_ERROR;
12935  break;
12936  }
12937 
12938  /* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
12939  if ((pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags & WHDR_DONE) != 0) {
12940  pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 0; /* 0 = unlocked (make it available for reading). */
12941  pDevice->winmm.headerFramesConsumedCapture = 0;
12942  }
12943 
12944  /* If the device has been stopped we need to break. */
12945  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
12946  break;
12947  }
12948  }
12949 
12950  if (pFramesRead != NULL) {
12951  *pFramesRead = totalFramesRead;
12952  }
12953 
12954  return result;
12955 }
12956 
12957 static ma_result ma_context_uninit__winmm(ma_context* pContext)
12958 {
12959  MA_ASSERT(pContext != NULL);
12960  MA_ASSERT(pContext->backend == ma_backend_winmm);
12961 
12962  ma_dlclose(pContext, pContext->winmm.hWinMM);
12963  return MA_SUCCESS;
12964 }
12965 
12966 static ma_result ma_context_init__winmm(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
12967 {
12968  MA_ASSERT(pContext != NULL);
12969 
12970  (void)pConfig;
12971 
12972  pContext->winmm.hWinMM = ma_dlopen(pContext, "winmm.dll");
12973  if (pContext->winmm.hWinMM == NULL) {
12974  return MA_NO_BACKEND;
12975  }
12976 
12977  pContext->winmm.waveOutGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutGetNumDevs");
12978  pContext->winmm.waveOutGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutGetDevCapsA");
12979  pContext->winmm.waveOutOpen = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutOpen");
12980  pContext->winmm.waveOutClose = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutClose");
12981  pContext->winmm.waveOutPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutPrepareHeader");
12982  pContext->winmm.waveOutUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutUnprepareHeader");
12983  pContext->winmm.waveOutWrite = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutWrite");
12984  pContext->winmm.waveOutReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutReset");
12985  pContext->winmm.waveInGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInGetNumDevs");
12986  pContext->winmm.waveInGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInGetDevCapsA");
12987  pContext->winmm.waveInOpen = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInOpen");
12988  pContext->winmm.waveInClose = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInClose");
12989  pContext->winmm.waveInPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInPrepareHeader");
12990  pContext->winmm.waveInUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInUnprepareHeader");
12991  pContext->winmm.waveInAddBuffer = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInAddBuffer");
12992  pContext->winmm.waveInStart = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInStart");
12993  pContext->winmm.waveInReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInReset");
12994 
12995  pCallbacks->onContextInit = ma_context_init__winmm;
12996  pCallbacks->onContextUninit = ma_context_uninit__winmm;
12997  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__winmm;
12998  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__winmm;
12999  pCallbacks->onDeviceInit = ma_device_init__winmm;
13000  pCallbacks->onDeviceUninit = ma_device_uninit__winmm;
13001  pCallbacks->onDeviceStart = ma_device_start__winmm;
13002  pCallbacks->onDeviceStop = ma_device_stop__winmm;
13003  pCallbacks->onDeviceRead = ma_device_read__winmm;
13004  pCallbacks->onDeviceWrite = ma_device_write__winmm;
13005  pCallbacks->onDeviceDataLoop = NULL; /* This is a blocking read-write API, so this can be NULL since miniaudio will manage the audio thread for us. */
13006 
13007  return MA_SUCCESS;
13008 }
13009 #endif
13010 
13011 
13012 
13013 
13014 /******************************************************************************
13015 
13016 ALSA Backend
13017 
13018 ******************************************************************************/
13019 #ifdef MA_HAS_ALSA
13020 
13021 #include <poll.h> /* poll(), struct pollfd */
13022 #include <sys/eventfd.h> /* eventfd() */
13023 
13024 #ifdef MA_NO_RUNTIME_LINKING
13025 
13026 /* asoundlib.h marks some functions with "inline" which isn't always supported. Need to emulate it. */
13027 #if !defined(__cplusplus)
13028  #if defined(__STRICT_ANSI__)
13029  #if !defined(inline)
13030  #define inline __inline__ __attribute__((always_inline))
13031  #define MA_INLINE_DEFINED
13032  #endif
13033  #endif
13034 #endif
13035 #include <alsa/asoundlib.h>
13036 #if defined(MA_INLINE_DEFINED)
13037  #undef inline
13038  #undef MA_INLINE_DEFINED
13039 #endif
13040 
13041 typedef snd_pcm_uframes_t ma_snd_pcm_uframes_t;
13042 typedef snd_pcm_sframes_t ma_snd_pcm_sframes_t;
13043 typedef snd_pcm_stream_t ma_snd_pcm_stream_t;
13044 typedef snd_pcm_format_t ma_snd_pcm_format_t;
13045 typedef snd_pcm_access_t ma_snd_pcm_access_t;
13046 typedef snd_pcm_t ma_snd_pcm_t;
13047 typedef snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
13048 typedef snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
13049 typedef snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
13050 typedef snd_pcm_info_t ma_snd_pcm_info_t;
13051 typedef snd_pcm_channel_area_t ma_snd_pcm_channel_area_t;
13052 typedef snd_pcm_chmap_t ma_snd_pcm_chmap_t;
13053 typedef snd_pcm_state_t ma_snd_pcm_state_t;
13054 
13055 /* snd_pcm_stream_t */
13056 #define MA_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK
13057 #define MA_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE
13058 
13059 /* snd_pcm_format_t */
13060 #define MA_SND_PCM_FORMAT_UNKNOWN SND_PCM_FORMAT_UNKNOWN
13061 #define MA_SND_PCM_FORMAT_U8 SND_PCM_FORMAT_U8
13062 #define MA_SND_PCM_FORMAT_S16_LE SND_PCM_FORMAT_S16_LE
13063 #define MA_SND_PCM_FORMAT_S16_BE SND_PCM_FORMAT_S16_BE
13064 #define MA_SND_PCM_FORMAT_S24_LE SND_PCM_FORMAT_S24_LE
13065 #define MA_SND_PCM_FORMAT_S24_BE SND_PCM_FORMAT_S24_BE
13066 #define MA_SND_PCM_FORMAT_S32_LE SND_PCM_FORMAT_S32_LE
13067 #define MA_SND_PCM_FORMAT_S32_BE SND_PCM_FORMAT_S32_BE
13068 #define MA_SND_PCM_FORMAT_FLOAT_LE SND_PCM_FORMAT_FLOAT_LE
13069 #define MA_SND_PCM_FORMAT_FLOAT_BE SND_PCM_FORMAT_FLOAT_BE
13070 #define MA_SND_PCM_FORMAT_FLOAT64_LE SND_PCM_FORMAT_FLOAT64_LE
13071 #define MA_SND_PCM_FORMAT_FLOAT64_BE SND_PCM_FORMAT_FLOAT64_BE
13072 #define MA_SND_PCM_FORMAT_MU_LAW SND_PCM_FORMAT_MU_LAW
13073 #define MA_SND_PCM_FORMAT_A_LAW SND_PCM_FORMAT_A_LAW
13074 #define MA_SND_PCM_FORMAT_S24_3LE SND_PCM_FORMAT_S24_3LE
13075 #define MA_SND_PCM_FORMAT_S24_3BE SND_PCM_FORMAT_S24_3BE
13076 
13077 /* ma_snd_pcm_access_t */
13078 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED SND_PCM_ACCESS_MMAP_INTERLEAVED
13079 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED SND_PCM_ACCESS_MMAP_NONINTERLEAVED
13080 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX SND_PCM_ACCESS_MMAP_COMPLEX
13081 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED SND_PCM_ACCESS_RW_INTERLEAVED
13082 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED SND_PCM_ACCESS_RW_NONINTERLEAVED
13083 
13084 /* Channel positions. */
13085 #define MA_SND_CHMAP_UNKNOWN SND_CHMAP_UNKNOWN
13086 #define MA_SND_CHMAP_NA SND_CHMAP_NA
13087 #define MA_SND_CHMAP_MONO SND_CHMAP_MONO
13088 #define MA_SND_CHMAP_FL SND_CHMAP_FL
13089 #define MA_SND_CHMAP_FR SND_CHMAP_FR
13090 #define MA_SND_CHMAP_RL SND_CHMAP_RL
13091 #define MA_SND_CHMAP_RR SND_CHMAP_RR
13092 #define MA_SND_CHMAP_FC SND_CHMAP_FC
13093 #define MA_SND_CHMAP_LFE SND_CHMAP_LFE
13094 #define MA_SND_CHMAP_SL SND_CHMAP_SL
13095 #define MA_SND_CHMAP_SR SND_CHMAP_SR
13096 #define MA_SND_CHMAP_RC SND_CHMAP_RC
13097 #define MA_SND_CHMAP_FLC SND_CHMAP_FLC
13098 #define MA_SND_CHMAP_FRC SND_CHMAP_FRC
13099 #define MA_SND_CHMAP_RLC SND_CHMAP_RLC
13100 #define MA_SND_CHMAP_RRC SND_CHMAP_RRC
13101 #define MA_SND_CHMAP_FLW SND_CHMAP_FLW
13102 #define MA_SND_CHMAP_FRW SND_CHMAP_FRW
13103 #define MA_SND_CHMAP_FLH SND_CHMAP_FLH
13104 #define MA_SND_CHMAP_FCH SND_CHMAP_FCH
13105 #define MA_SND_CHMAP_FRH SND_CHMAP_FRH
13106 #define MA_SND_CHMAP_TC SND_CHMAP_TC
13107 #define MA_SND_CHMAP_TFL SND_CHMAP_TFL
13108 #define MA_SND_CHMAP_TFR SND_CHMAP_TFR
13109 #define MA_SND_CHMAP_TFC SND_CHMAP_TFC
13110 #define MA_SND_CHMAP_TRL SND_CHMAP_TRL
13111 #define MA_SND_CHMAP_TRR SND_CHMAP_TRR
13112 #define MA_SND_CHMAP_TRC SND_CHMAP_TRC
13113 #define MA_SND_CHMAP_TFLC SND_CHMAP_TFLC
13114 #define MA_SND_CHMAP_TFRC SND_CHMAP_TFRC
13115 #define MA_SND_CHMAP_TSL SND_CHMAP_TSL
13116 #define MA_SND_CHMAP_TSR SND_CHMAP_TSR
13117 #define MA_SND_CHMAP_LLFE SND_CHMAP_LLFE
13118 #define MA_SND_CHMAP_RLFE SND_CHMAP_RLFE
13119 #define MA_SND_CHMAP_BC SND_CHMAP_BC
13120 #define MA_SND_CHMAP_BLC SND_CHMAP_BLC
13121 #define MA_SND_CHMAP_BRC SND_CHMAP_BRC
13122 
13123 /* Open mode flags. */
13124 #define MA_SND_PCM_NO_AUTO_RESAMPLE SND_PCM_NO_AUTO_RESAMPLE
13125 #define MA_SND_PCM_NO_AUTO_CHANNELS SND_PCM_NO_AUTO_CHANNELS
13126 #define MA_SND_PCM_NO_AUTO_FORMAT SND_PCM_NO_AUTO_FORMAT
13127 #else
13128 #include <errno.h> /* For EPIPE, etc. */
13129 typedef unsigned long ma_snd_pcm_uframes_t;
13130 typedef long ma_snd_pcm_sframes_t;
13131 typedef int ma_snd_pcm_stream_t;
13132 typedef int ma_snd_pcm_format_t;
13133 typedef int ma_snd_pcm_access_t;
13134 typedef int ma_snd_pcm_state_t;
13135 typedef struct ma_snd_pcm_t ma_snd_pcm_t;
13136 typedef struct ma_snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
13137 typedef struct ma_snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
13138 typedef struct ma_snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
13139 typedef struct ma_snd_pcm_info_t ma_snd_pcm_info_t;
13140 typedef struct
13141 {
13142  void* addr;
13143  unsigned int first;
13144  unsigned int step;
13145 } ma_snd_pcm_channel_area_t;
13146 typedef struct
13147 {
13148  unsigned int channels;
13149  unsigned int pos[1];
13150 } ma_snd_pcm_chmap_t;
13151 
13152 /* snd_pcm_state_t */
13153 #define MA_SND_PCM_STATE_OPEN 0
13154 #define MA_SND_PCM_STATE_SETUP 1
13155 #define MA_SND_PCM_STATE_PREPARED 2
13156 #define MA_SND_PCM_STATE_RUNNING 3
13157 #define MA_SND_PCM_STATE_XRUN 4
13158 #define MA_SND_PCM_STATE_DRAINING 5
13159 #define MA_SND_PCM_STATE_PAUSED 6
13160 #define MA_SND_PCM_STATE_SUSPENDED 7
13161 #define MA_SND_PCM_STATE_DISCONNECTED 8
13162 
13163 /* snd_pcm_stream_t */
13164 #define MA_SND_PCM_STREAM_PLAYBACK 0
13165 #define MA_SND_PCM_STREAM_CAPTURE 1
13166 
13167 /* snd_pcm_format_t */
13168 #define MA_SND_PCM_FORMAT_UNKNOWN -1
13169 #define MA_SND_PCM_FORMAT_U8 1
13170 #define MA_SND_PCM_FORMAT_S16_LE 2
13171 #define MA_SND_PCM_FORMAT_S16_BE 3
13172 #define MA_SND_PCM_FORMAT_S24_LE 6
13173 #define MA_SND_PCM_FORMAT_S24_BE 7
13174 #define MA_SND_PCM_FORMAT_S32_LE 10
13175 #define MA_SND_PCM_FORMAT_S32_BE 11
13176 #define MA_SND_PCM_FORMAT_FLOAT_LE 14
13177 #define MA_SND_PCM_FORMAT_FLOAT_BE 15
13178 #define MA_SND_PCM_FORMAT_FLOAT64_LE 16
13179 #define MA_SND_PCM_FORMAT_FLOAT64_BE 17
13180 #define MA_SND_PCM_FORMAT_MU_LAW 20
13181 #define MA_SND_PCM_FORMAT_A_LAW 21
13182 #define MA_SND_PCM_FORMAT_S24_3LE 32
13183 #define MA_SND_PCM_FORMAT_S24_3BE 33
13184 
13185 /* snd_pcm_access_t */
13186 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED 0
13187 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED 1
13188 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX 2
13189 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED 3
13190 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED 4
13191 
13192 /* Channel positions. */
13193 #define MA_SND_CHMAP_UNKNOWN 0
13194 #define MA_SND_CHMAP_NA 1
13195 #define MA_SND_CHMAP_MONO 2
13196 #define MA_SND_CHMAP_FL 3
13197 #define MA_SND_CHMAP_FR 4
13198 #define MA_SND_CHMAP_RL 5
13199 #define MA_SND_CHMAP_RR 6
13200 #define MA_SND_CHMAP_FC 7
13201 #define MA_SND_CHMAP_LFE 8
13202 #define MA_SND_CHMAP_SL 9
13203 #define MA_SND_CHMAP_SR 10
13204 #define MA_SND_CHMAP_RC 11
13205 #define MA_SND_CHMAP_FLC 12
13206 #define MA_SND_CHMAP_FRC 13
13207 #define MA_SND_CHMAP_RLC 14
13208 #define MA_SND_CHMAP_RRC 15
13209 #define MA_SND_CHMAP_FLW 16
13210 #define MA_SND_CHMAP_FRW 17
13211 #define MA_SND_CHMAP_FLH 18
13212 #define MA_SND_CHMAP_FCH 19
13213 #define MA_SND_CHMAP_FRH 20
13214 #define MA_SND_CHMAP_TC 21
13215 #define MA_SND_CHMAP_TFL 22
13216 #define MA_SND_CHMAP_TFR 23
13217 #define MA_SND_CHMAP_TFC 24
13218 #define MA_SND_CHMAP_TRL 25
13219 #define MA_SND_CHMAP_TRR 26
13220 #define MA_SND_CHMAP_TRC 27
13221 #define MA_SND_CHMAP_TFLC 28
13222 #define MA_SND_CHMAP_TFRC 29
13223 #define MA_SND_CHMAP_TSL 30
13224 #define MA_SND_CHMAP_TSR 31
13225 #define MA_SND_CHMAP_LLFE 32
13226 #define MA_SND_CHMAP_RLFE 33
13227 #define MA_SND_CHMAP_BC 34
13228 #define MA_SND_CHMAP_BLC 35
13229 #define MA_SND_CHMAP_BRC 36
13230 
13231 /* Open mode flags. */
13232 #define MA_SND_PCM_NO_AUTO_RESAMPLE 0x00010000
13233 #define MA_SND_PCM_NO_AUTO_CHANNELS 0x00020000
13234 #define MA_SND_PCM_NO_AUTO_FORMAT 0x00040000
13235 #endif
13236 
13237 typedef int (* ma_snd_pcm_open_proc) (ma_snd_pcm_t **pcm, const char *name, ma_snd_pcm_stream_t stream, int mode);
13238 typedef int (* ma_snd_pcm_close_proc) (ma_snd_pcm_t *pcm);
13239 typedef size_t (* ma_snd_pcm_hw_params_sizeof_proc) (void);
13240 typedef int (* ma_snd_pcm_hw_params_any_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params);
13241 typedef int (* ma_snd_pcm_hw_params_set_format_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_format_t val);
13242 typedef int (* ma_snd_pcm_hw_params_set_format_first_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_format_t *format);
13243 typedef void (* ma_snd_pcm_hw_params_get_format_mask_proc) (ma_snd_pcm_hw_params_t *params, ma_snd_pcm_format_mask_t *mask);
13244 typedef int (* ma_snd_pcm_hw_params_set_channels_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val);
13245 typedef int (* ma_snd_pcm_hw_params_set_channels_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val);
13246 typedef int (* ma_snd_pcm_hw_params_set_channels_minmax_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *minimum, unsigned int *maximum);
13247 typedef int (* ma_snd_pcm_hw_params_set_rate_resample_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val);
13248 typedef int (* ma_snd_pcm_hw_params_set_rate_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val, int dir);
13249 typedef int (* ma_snd_pcm_hw_params_set_rate_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
13250 typedef int (* ma_snd_pcm_hw_params_set_buffer_size_near_proc)(ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_uframes_t *val);
13251 typedef int (* ma_snd_pcm_hw_params_set_periods_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
13252 typedef int (* ma_snd_pcm_hw_params_set_access_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_access_t _access);
13253 typedef int (* ma_snd_pcm_hw_params_get_format_proc) (const ma_snd_pcm_hw_params_t *params, ma_snd_pcm_format_t *format);
13254 typedef int (* ma_snd_pcm_hw_params_get_channels_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val);
13255 typedef int (* ma_snd_pcm_hw_params_get_channels_min_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val);
13256 typedef int (* ma_snd_pcm_hw_params_get_channels_max_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val);
13257 typedef int (* ma_snd_pcm_hw_params_get_rate_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *rate, int *dir);
13258 typedef int (* ma_snd_pcm_hw_params_get_rate_min_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *rate, int *dir);
13259 typedef int (* ma_snd_pcm_hw_params_get_rate_max_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *rate, int *dir);
13260 typedef int (* ma_snd_pcm_hw_params_get_buffer_size_proc) (const ma_snd_pcm_hw_params_t *params, ma_snd_pcm_uframes_t *val);
13261 typedef int (* ma_snd_pcm_hw_params_get_periods_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
13262 typedef int (* ma_snd_pcm_hw_params_get_access_proc) (const ma_snd_pcm_hw_params_t *params, ma_snd_pcm_access_t *_access);
13263 typedef int (* ma_snd_pcm_hw_params_test_format_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_format_t val);
13264 typedef int (* ma_snd_pcm_hw_params_test_channels_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val);
13265 typedef int (* ma_snd_pcm_hw_params_test_rate_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val, int dir);
13266 typedef int (* ma_snd_pcm_hw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params);
13267 typedef size_t (* ma_snd_pcm_sw_params_sizeof_proc) (void);
13268 typedef int (* ma_snd_pcm_sw_params_current_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params);
13269 typedef int (* ma_snd_pcm_sw_params_get_boundary_proc) (const ma_snd_pcm_sw_params_t *params, ma_snd_pcm_uframes_t* val);
13270 typedef int (* ma_snd_pcm_sw_params_set_avail_min_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params, ma_snd_pcm_uframes_t val);
13271 typedef int (* ma_snd_pcm_sw_params_set_start_threshold_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params, ma_snd_pcm_uframes_t val);
13272 typedef int (* ma_snd_pcm_sw_params_set_stop_threshold_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params, ma_snd_pcm_uframes_t val);
13273 typedef int (* ma_snd_pcm_sw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params);
13274 typedef size_t (* ma_snd_pcm_format_mask_sizeof_proc) (void);
13275 typedef int (* ma_snd_pcm_format_mask_test_proc) (const ma_snd_pcm_format_mask_t *mask, ma_snd_pcm_format_t val);
13276 typedef ma_snd_pcm_chmap_t * (* ma_snd_pcm_get_chmap_proc) (ma_snd_pcm_t *pcm);
13277 typedef ma_snd_pcm_state_t (* ma_snd_pcm_state_proc) (ma_snd_pcm_t *pcm);
13278 typedef int (* ma_snd_pcm_prepare_proc) (ma_snd_pcm_t *pcm);
13279 typedef int (* ma_snd_pcm_start_proc) (ma_snd_pcm_t *pcm);
13280 typedef int (* ma_snd_pcm_drop_proc) (ma_snd_pcm_t *pcm);
13281 typedef int (* ma_snd_pcm_drain_proc) (ma_snd_pcm_t *pcm);
13282 typedef int (* ma_snd_pcm_reset_proc) (ma_snd_pcm_t *pcm);
13283 typedef int (* ma_snd_device_name_hint_proc) (int card, const char *iface, void ***hints);
13284 typedef char * (* ma_snd_device_name_get_hint_proc) (const void *hint, const char *id);
13285 typedef int (* ma_snd_card_get_index_proc) (const char *name);
13286 typedef int (* ma_snd_device_name_free_hint_proc) (void **hints);
13287 typedef int (* ma_snd_pcm_mmap_begin_proc) (ma_snd_pcm_t *pcm, const ma_snd_pcm_channel_area_t **areas, ma_snd_pcm_uframes_t *offset, ma_snd_pcm_uframes_t *frames);
13288 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_mmap_commit_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_uframes_t offset, ma_snd_pcm_uframes_t frames);
13289 typedef int (* ma_snd_pcm_recover_proc) (ma_snd_pcm_t *pcm, int err, int silent);
13290 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_readi_proc) (ma_snd_pcm_t *pcm, void *buffer, ma_snd_pcm_uframes_t size);
13291 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_writei_proc) (ma_snd_pcm_t *pcm, const void *buffer, ma_snd_pcm_uframes_t size);
13292 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_proc) (ma_snd_pcm_t *pcm);
13293 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_update_proc) (ma_snd_pcm_t *pcm);
13294 typedef int (* ma_snd_pcm_wait_proc) (ma_snd_pcm_t *pcm, int timeout);
13295 typedef int (* ma_snd_pcm_nonblock_proc) (ma_snd_pcm_t *pcm, int nonblock);
13296 typedef int (* ma_snd_pcm_info_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_info_t* info);
13297 typedef size_t (* ma_snd_pcm_info_sizeof_proc) (void);
13298 typedef const char* (* ma_snd_pcm_info_get_name_proc) (const ma_snd_pcm_info_t* info);
13299 typedef int (* ma_snd_pcm_poll_descriptors_proc) (ma_snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
13300 typedef int (* ma_snd_pcm_poll_descriptors_count_proc) (ma_snd_pcm_t *pcm);
13301 typedef int (* ma_snd_pcm_poll_descriptors_revents_proc) (ma_snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
13302 typedef int (* ma_snd_config_update_free_global_proc) (void);
13303 
13304 /* This array specifies each of the common devices that can be used for both playback and capture. */
13305 static const char* g_maCommonDeviceNamesALSA[] = {
13306  "default",
13307  "null",
13308  "pulse",
13309  "jack"
13310 };
13311 
13312 /* This array allows us to blacklist specific playback devices. */
13313 static const char* g_maBlacklistedPlaybackDeviceNamesALSA[] = {
13314  ""
13315 };
13316 
13317 /* This array allows us to blacklist specific capture devices. */
13318 static const char* g_maBlacklistedCaptureDeviceNamesALSA[] = {
13319  ""
13320 };
13321 
13322 
13323 static ma_snd_pcm_format_t ma_convert_ma_format_to_alsa_format(ma_format format)
13324 {
13325  ma_snd_pcm_format_t ALSAFormats[] = {
13326  MA_SND_PCM_FORMAT_UNKNOWN, /* ma_format_unknown */
13327  MA_SND_PCM_FORMAT_U8, /* ma_format_u8 */
13328  MA_SND_PCM_FORMAT_S16_LE, /* ma_format_s16 */
13329  MA_SND_PCM_FORMAT_S24_3LE, /* ma_format_s24 */
13330  MA_SND_PCM_FORMAT_S32_LE, /* ma_format_s32 */
13331  MA_SND_PCM_FORMAT_FLOAT_LE /* ma_format_f32 */
13332  };
13333 
13334  if (ma_is_big_endian()) {
13335  ALSAFormats[0] = MA_SND_PCM_FORMAT_UNKNOWN;
13336  ALSAFormats[1] = MA_SND_PCM_FORMAT_U8;
13337  ALSAFormats[2] = MA_SND_PCM_FORMAT_S16_BE;
13338  ALSAFormats[3] = MA_SND_PCM_FORMAT_S24_3BE;
13339  ALSAFormats[4] = MA_SND_PCM_FORMAT_S32_BE;
13340  ALSAFormats[5] = MA_SND_PCM_FORMAT_FLOAT_BE;
13341  }
13342 
13343  return ALSAFormats[format];
13344 }
13345 
13346 static ma_format ma_format_from_alsa(ma_snd_pcm_format_t formatALSA)
13347 {
13348  if (ma_is_little_endian()) {
13349  switch (formatALSA) {
13350  case MA_SND_PCM_FORMAT_S16_LE: return ma_format_s16;
13351  case MA_SND_PCM_FORMAT_S24_3LE: return ma_format_s24;
13352  case MA_SND_PCM_FORMAT_S32_LE: return ma_format_s32;
13353  case MA_SND_PCM_FORMAT_FLOAT_LE: return ma_format_f32;
13354  default: break;
13355  }
13356  } else {
13357  switch (formatALSA) {
13358  case MA_SND_PCM_FORMAT_S16_BE: return ma_format_s16;
13359  case MA_SND_PCM_FORMAT_S24_3BE: return ma_format_s24;
13360  case MA_SND_PCM_FORMAT_S32_BE: return ma_format_s32;
13361  case MA_SND_PCM_FORMAT_FLOAT_BE: return ma_format_f32;
13362  default: break;
13363  }
13364  }
13365 
13366  /* Endian agnostic. */
13367  switch (formatALSA) {
13368  case MA_SND_PCM_FORMAT_U8: return ma_format_u8;
13369  default: return ma_format_unknown;
13370  }
13371 }
13372 
13373 static ma_channel ma_convert_alsa_channel_position_to_ma_channel(unsigned int alsaChannelPos)
13374 {
13375  switch (alsaChannelPos)
13376  {
13377  case MA_SND_CHMAP_MONO: return MA_CHANNEL_MONO;
13378  case MA_SND_CHMAP_FL: return MA_CHANNEL_FRONT_LEFT;
13379  case MA_SND_CHMAP_FR: return MA_CHANNEL_FRONT_RIGHT;
13380  case MA_SND_CHMAP_RL: return MA_CHANNEL_BACK_LEFT;
13381  case MA_SND_CHMAP_RR: return MA_CHANNEL_BACK_RIGHT;
13382  case MA_SND_CHMAP_FC: return MA_CHANNEL_FRONT_CENTER;
13383  case MA_SND_CHMAP_LFE: return MA_CHANNEL_LFE;
13384  case MA_SND_CHMAP_SL: return MA_CHANNEL_SIDE_LEFT;
13385  case MA_SND_CHMAP_SR: return MA_CHANNEL_SIDE_RIGHT;
13386  case MA_SND_CHMAP_RC: return MA_CHANNEL_BACK_CENTER;
13387  case MA_SND_CHMAP_FLC: return MA_CHANNEL_FRONT_LEFT_CENTER;
13388  case MA_SND_CHMAP_FRC: return MA_CHANNEL_FRONT_RIGHT_CENTER;
13389  case MA_SND_CHMAP_RLC: return 0;
13390  case MA_SND_CHMAP_RRC: return 0;
13391  case MA_SND_CHMAP_FLW: return 0;
13392  case MA_SND_CHMAP_FRW: return 0;
13393  case MA_SND_CHMAP_FLH: return 0;
13394  case MA_SND_CHMAP_FCH: return 0;
13395  case MA_SND_CHMAP_FRH: return 0;
13396  case MA_SND_CHMAP_TC: return MA_CHANNEL_TOP_CENTER;
13397  case MA_SND_CHMAP_TFL: return MA_CHANNEL_TOP_FRONT_LEFT;
13398  case MA_SND_CHMAP_TFR: return MA_CHANNEL_TOP_FRONT_RIGHT;
13399  case MA_SND_CHMAP_TFC: return MA_CHANNEL_TOP_FRONT_CENTER;
13400  case MA_SND_CHMAP_TRL: return MA_CHANNEL_TOP_BACK_LEFT;
13401  case MA_SND_CHMAP_TRR: return MA_CHANNEL_TOP_BACK_RIGHT;
13402  case MA_SND_CHMAP_TRC: return MA_CHANNEL_TOP_BACK_CENTER;
13403  default: break;
13404  }
13405 
13406  return 0;
13407 }
13408 
13409 static ma_bool32 ma_is_common_device_name__alsa(const char* name)
13410 {
13411  size_t iName;
13412  for (iName = 0; iName < ma_countof(g_maCommonDeviceNamesALSA); ++iName) {
13413  if (ma_strcmp(name, g_maCommonDeviceNamesALSA[iName]) == 0) {
13414  return MA_TRUE;
13415  }
13416  }
13417 
13418  return MA_FALSE;
13419 }
13420 
13421 
13422 static ma_bool32 ma_is_playback_device_blacklisted__alsa(const char* name)
13423 {
13424  size_t iName;
13425  for (iName = 0; iName < ma_countof(g_maBlacklistedPlaybackDeviceNamesALSA); ++iName) {
13426  if (ma_strcmp(name, g_maBlacklistedPlaybackDeviceNamesALSA[iName]) == 0) {
13427  return MA_TRUE;
13428  }
13429  }
13430 
13431  return MA_FALSE;
13432 }
13433 
13434 static ma_bool32 ma_is_capture_device_blacklisted__alsa(const char* name)
13435 {
13436  size_t iName;
13437  for (iName = 0; iName < ma_countof(g_maBlacklistedCaptureDeviceNamesALSA); ++iName) {
13438  if (ma_strcmp(name, g_maBlacklistedCaptureDeviceNamesALSA[iName]) == 0) {
13439  return MA_TRUE;
13440  }
13441  }
13442 
13443  return MA_FALSE;
13444 }
13445 
13446 static ma_bool32 ma_is_device_blacklisted__alsa(ma_device_type deviceType, const char* name)
13447 {
13448  if (deviceType == ma_device_type_playback) {
13449  return ma_is_playback_device_blacklisted__alsa(name);
13450  } else {
13451  return ma_is_capture_device_blacklisted__alsa(name);
13452  }
13453 }
13454 
13455 
13456 static const char* ma_find_char(const char* str, char c, int* index)
13457 {
13458  int i = 0;
13459  for (;;) {
13460  if (str[i] == '\0') {
13461  if (index) *index = -1;
13462  return NULL;
13463  }
13464 
13465  if (str[i] == c) {
13466  if (index) *index = i;
13467  return str + i;
13468  }
13469 
13470  i += 1;
13471  }
13472 
13473  /* Should never get here, but treat it as though the character was not found to make me feel better inside. */
13474  if (index) *index = -1;
13475  return NULL;
13476 }
13477 
13478 static ma_bool32 ma_is_device_name_in_hw_format__alsa(const char* hwid)
13479 {
13480  /* This function is just checking whether or not hwid is in "hw:%d,%d" format. */
13481 
13482  int commaPos;
13483  const char* dev;
13484  int i;
13485 
13486  if (hwid == NULL) {
13487  return MA_FALSE;
13488  }
13489 
13490  if (hwid[0] != 'h' || hwid[1] != 'w' || hwid[2] != ':') {
13491  return MA_FALSE;
13492  }
13493 
13494  hwid += 3;
13495 
13496  dev = ma_find_char(hwid, ',', &commaPos);
13497  if (dev == NULL) {
13498  return MA_FALSE;
13499  } else {
13500  dev += 1; /* Skip past the ",". */
13501  }
13502 
13503  /* Check if the part between the ":" and the "," contains only numbers. If not, return false. */
13504  for (i = 0; i < commaPos; ++i) {
13505  if (hwid[i] < '0' || hwid[i] > '9') {
13506  return MA_FALSE;
13507  }
13508  }
13509 
13510  /* Check if everything after the "," is numeric. If not, return false. */
13511  i = 0;
13512  while (dev[i] != '\0') {
13513  if (dev[i] < '0' || dev[i] > '9') {
13514  return MA_FALSE;
13515  }
13516  i += 1;
13517  }
13518 
13519  return MA_TRUE;
13520 }
13521 
13522 static int ma_convert_device_name_to_hw_format__alsa(ma_context* pContext, char* dst, size_t dstSize, const char* src) /* Returns 0 on success, non-0 on error. */
13523 {
13524  /* src should look something like this: "hw:CARD=I82801AAICH,DEV=0" */
13525 
13526  int colonPos;
13527  int commaPos;
13528  char card[256];
13529  const char* dev;
13530  int cardIndex;
13531 
13532  if (dst == NULL) {
13533  return -1;
13534  }
13535  if (dstSize < 7) {
13536  return -1; /* Absolute minimum size of the output buffer is 7 bytes. */
13537  }
13538 
13539  *dst = '\0'; /* Safety. */
13540  if (src == NULL) {
13541  return -1;
13542  }
13543 
13544  /* If the input name is already in "hw:%d,%d" format, just return that verbatim. */
13545  if (ma_is_device_name_in_hw_format__alsa(src)) {
13546  return ma_strcpy_s(dst, dstSize, src);
13547  }
13548 
13549  src = ma_find_char(src, ':', &colonPos);
13550  if (src == NULL) {
13551  return -1; /* Couldn't find a colon */
13552  }
13553 
13554  dev = ma_find_char(src, ',', &commaPos);
13555  if (dev == NULL) {
13556  dev = "0";
13557  ma_strncpy_s(card, sizeof(card), src+6, (size_t)-1); /* +6 = ":CARD=" */
13558  } else {
13559  dev = dev + 5; /* +5 = ",DEV=" */
13560  ma_strncpy_s(card, sizeof(card), src+6, commaPos-6); /* +6 = ":CARD=" */
13561  }
13562 
13563  cardIndex = ((ma_snd_card_get_index_proc)pContext->alsa.snd_card_get_index)(card);
13564  if (cardIndex < 0) {
13565  return -2; /* Failed to retrieve the card index. */
13566  }
13567 
13568 
13569  /* Construction. */
13570  dst[0] = 'h'; dst[1] = 'w'; dst[2] = ':';
13571  if (ma_itoa_s(cardIndex, dst+3, dstSize-3, 10) != 0) {
13572  return -3;
13573  }
13574  if (ma_strcat_s(dst, dstSize, ",") != 0) {
13575  return -3;
13576  }
13577  if (ma_strcat_s(dst, dstSize, dev) != 0) {
13578  return -3;
13579  }
13580 
13581  return 0;
13582 }
13583 
13584 static ma_bool32 ma_does_id_exist_in_list__alsa(ma_device_id* pUniqueIDs, ma_uint32 count, const char* pHWID)
13585 {
13586  ma_uint32 i;
13587 
13588  MA_ASSERT(pHWID != NULL);
13589 
13590  for (i = 0; i < count; ++i) {
13591  if (ma_strcmp(pUniqueIDs[i].alsa, pHWID) == 0) {
13592  return MA_TRUE;
13593  }
13594  }
13595 
13596  return MA_FALSE;
13597 }
13598 
13599 
13600 static ma_result ma_context_open_pcm__alsa(ma_context* pContext, ma_share_mode shareMode, ma_device_type deviceType, const ma_device_id* pDeviceID, int openMode, ma_snd_pcm_t** ppPCM)
13601 {
13602  ma_snd_pcm_t* pPCM;
13603  ma_snd_pcm_stream_t stream;
13604 
13605  MA_ASSERT(pContext != NULL);
13606  MA_ASSERT(ppPCM != NULL);
13607 
13608  *ppPCM = NULL;
13609  pPCM = NULL;
13610 
13611  stream = (deviceType == ma_device_type_playback) ? MA_SND_PCM_STREAM_PLAYBACK : MA_SND_PCM_STREAM_CAPTURE;
13612 
13613  if (pDeviceID == NULL) {
13614  ma_bool32 isDeviceOpen;
13615  size_t i;
13616 
13617  /*
13618  We're opening the default device. I don't know if trying anything other than "default" is necessary, but it makes
13619  me feel better to try as hard as we can get to get _something_ working.
13620  */
13621  const char* defaultDeviceNames[] = {
13622  "default",
13623  NULL,
13624  NULL,
13625  NULL,
13626  NULL,
13627  NULL,
13628  NULL
13629  };
13630 
13631  if (shareMode == ma_share_mode_exclusive) {
13632  defaultDeviceNames[1] = "hw";
13633  defaultDeviceNames[2] = "hw:0";
13634  defaultDeviceNames[3] = "hw:0,0";
13635  } else {
13636  if (deviceType == ma_device_type_playback) {
13637  defaultDeviceNames[1] = "dmix";
13638  defaultDeviceNames[2] = "dmix:0";
13639  defaultDeviceNames[3] = "dmix:0,0";
13640  } else {
13641  defaultDeviceNames[1] = "dsnoop";
13642  defaultDeviceNames[2] = "dsnoop:0";
13643  defaultDeviceNames[3] = "dsnoop:0,0";
13644  }
13645  defaultDeviceNames[4] = "hw";
13646  defaultDeviceNames[5] = "hw:0";
13647  defaultDeviceNames[6] = "hw:0,0";
13648  }
13649 
13650  isDeviceOpen = MA_FALSE;
13651  for (i = 0; i < ma_countof(defaultDeviceNames); ++i) {
13652  if (defaultDeviceNames[i] != NULL && defaultDeviceNames[i][0] != '\0') {
13653  if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, defaultDeviceNames[i], stream, openMode) == 0) {
13654  isDeviceOpen = MA_TRUE;
13655  break;
13656  }
13657  }
13658  }
13659 
13660  if (!isDeviceOpen) {
13661  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_open() failed when trying to open an appropriate default device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
13662  }
13663  } else {
13664  /*
13665  We're trying to open a specific device. There's a few things to consider here:
13666 
13667  miniaudio recongnizes a special format of device id that excludes the "hw", "dmix", etc. prefix. It looks like this: ":0,0", ":0,1", etc. When
13668  an ID of this format is specified, it indicates to miniaudio that it can try different combinations of plugins ("hw", "dmix", etc.) until it
13669  finds an appropriate one that works. This comes in very handy when trying to open a device in shared mode ("dmix"), vs exclusive mode ("hw").
13670  */
13671 
13672  /* May end up needing to make small adjustments to the ID, so make a copy. */
13673  ma_device_id deviceID = *pDeviceID;
13674  int resultALSA = -ENODEV;
13675 
13676  if (deviceID.alsa[0] != ':') {
13677  /* The ID is not in ":0,0" format. Use the ID exactly as-is. */
13678  resultALSA = ((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, deviceID.alsa, stream, openMode);
13679  } else {
13680  char hwid[256];
13681 
13682  /* The ID is in ":0,0" format. Try different plugins depending on the shared mode. */
13683  if (deviceID.alsa[1] == '\0') {
13684  deviceID.alsa[0] = '\0'; /* An ID of ":" should be converted to "". */
13685  }
13686 
13687  if (shareMode == ma_share_mode_shared) {
13688  if (deviceType == ma_device_type_playback) {
13689  ma_strcpy_s(hwid, sizeof(hwid), "dmix");
13690  } else {
13691  ma_strcpy_s(hwid, sizeof(hwid), "dsnoop");
13692  }
13693 
13694  if (ma_strcat_s(hwid, sizeof(hwid), deviceID.alsa) == 0) {
13695  resultALSA = ((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid, stream, openMode);
13696  }
13697  }
13698 
13699  /* If at this point we still don't have an open device it means we're either preferencing exclusive mode or opening with "dmix"/"dsnoop" failed. */
13700  if (resultALSA != 0) {
13701  ma_strcpy_s(hwid, sizeof(hwid), "hw");
13702  if (ma_strcat_s(hwid, sizeof(hwid), deviceID.alsa) == 0) {
13703  resultALSA = ((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid, stream, openMode);
13704  }
13705  }
13706  }
13707 
13708  if (resultALSA < 0) {
13709  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_open() failed.", ma_result_from_errno(-resultALSA));
13710  }
13711  }
13712 
13713  *ppPCM = pPCM;
13714  return MA_SUCCESS;
13715 }
13716 
13717 
13718 static ma_result ma_context_enumerate_devices__alsa(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
13719 {
13720  int resultALSA;
13721  ma_bool32 cbResult = MA_TRUE;
13722  char** ppDeviceHints;
13723  ma_device_id* pUniqueIDs = NULL;
13724  ma_uint32 uniqueIDCount = 0;
13725  char** ppNextDeviceHint;
13726 
13727  MA_ASSERT(pContext != NULL);
13728  MA_ASSERT(callback != NULL);
13729 
13730  ma_mutex_lock(&pContext->alsa.internalDeviceEnumLock);
13731 
13732  resultALSA = ((ma_snd_device_name_hint_proc)pContext->alsa.snd_device_name_hint)(-1, "pcm", (void***)&ppDeviceHints);
13733  if (resultALSA < 0) {
13734  ma_mutex_unlock(&pContext->alsa.internalDeviceEnumLock);
13735  return ma_result_from_errno(-resultALSA);
13736  }
13737 
13738  ppNextDeviceHint = ppDeviceHints;
13739  while (*ppNextDeviceHint != NULL) {
13740  char* NAME = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint, "NAME");
13741  char* DESC = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint, "DESC");
13742  char* IOID = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint, "IOID");
13744  ma_bool32 stopEnumeration = MA_FALSE;
13745  char hwid[sizeof(pUniqueIDs->alsa)];
13746  ma_device_info deviceInfo;
13747 
13748  if ((IOID == NULL || ma_strcmp(IOID, "Output") == 0)) {
13749  deviceType = ma_device_type_playback;
13750  }
13751  if ((IOID != NULL && ma_strcmp(IOID, "Input" ) == 0)) {
13752  deviceType = ma_device_type_capture;
13753  }
13754 
13755  if (NAME != NULL) {
13756  if (pContext->alsa.useVerboseDeviceEnumeration) {
13757  /* Verbose mode. Use the name exactly as-is. */
13758  ma_strncpy_s(hwid, sizeof(hwid), NAME, (size_t)-1);
13759  } else {
13760  /* Simplified mode. Use ":%d,%d" format. */
13761  if (ma_convert_device_name_to_hw_format__alsa(pContext, hwid, sizeof(hwid), NAME) == 0) {
13762  /*
13763  At this point, hwid looks like "hw:0,0". In simplified enumeration mode, we actually want to strip off the
13764  plugin name so it looks like ":0,0". The reason for this is that this special format is detected at device
13765  initialization time and is used as an indicator to try and use the most appropriate plugin depending on the
13766  device type and sharing mode.
13767  */
13768  char* dst = hwid;
13769  char* src = hwid+2;
13770  while ((*dst++ = *src++));
13771  } else {
13772  /* Conversion to "hw:%d,%d" failed. Just use the name as-is. */
13773  ma_strncpy_s(hwid, sizeof(hwid), NAME, (size_t)-1);
13774  }
13775 
13776  if (ma_does_id_exist_in_list__alsa(pUniqueIDs, uniqueIDCount, hwid)) {
13777  goto next_device; /* The device has already been enumerated. Move on to the next one. */
13778  } else {
13779  /* The device has not yet been enumerated. Make sure it's added to our list so that it's not enumerated again. */
13780  size_t oldCapacity = sizeof(*pUniqueIDs) * uniqueIDCount;
13781  size_t newCapacity = sizeof(*pUniqueIDs) * (uniqueIDCount + 1);
13782  ma_device_id* pNewUniqueIDs = (ma_device_id*)ma__realloc_from_callbacks(pUniqueIDs, newCapacity, oldCapacity, &pContext->allocationCallbacks);
13783  if (pNewUniqueIDs == NULL) {
13784  goto next_device; /* Failed to allocate memory. */
13785  }
13786 
13787  pUniqueIDs = pNewUniqueIDs;
13788  MA_COPY_MEMORY(pUniqueIDs[uniqueIDCount].alsa, hwid, sizeof(hwid));
13789  uniqueIDCount += 1;
13790  }
13791  }
13792  } else {
13793  MA_ZERO_MEMORY(hwid, sizeof(hwid));
13794  }
13795 
13796  MA_ZERO_OBJECT(&deviceInfo);
13797  ma_strncpy_s(deviceInfo.id.alsa, sizeof(deviceInfo.id.alsa), hwid, (size_t)-1);
13798 
13799  /*
13800  There's no good way to determine whether or not a device is the default on Linux. We're just going to do something simple and
13801  just use the name of "default" as the indicator.
13802  */
13803  if (ma_strcmp(deviceInfo.id.alsa, "default") == 0) {
13804  deviceInfo.isDefault = MA_TRUE;
13805  }
13806 
13807 
13808  /*
13809  DESC is the friendly name. We treat this slightly differently depending on whether or not we are using verbose
13810  device enumeration. In verbose mode we want to take the entire description so that the end-user can distinguish
13811  between the subdevices of each card/dev pair. In simplified mode, however, we only want the first part of the
13812  description.
13813 
13814  The value in DESC seems to be split into two lines, with the first line being the name of the device and the
13815  second line being a description of the device. I don't like having the description be across two lines because
13816  it makes formatting ugly and annoying. I'm therefore deciding to put it all on a single line with the second line
13817  being put into parentheses. In simplified mode I'm just stripping the second line entirely.
13818  */
13819  if (DESC != NULL) {
13820  int lfPos;
13821  const char* line2 = ma_find_char(DESC, '\n', &lfPos);
13822  if (line2 != NULL) {
13823  line2 += 1; /* Skip past the new-line character. */
13824 
13825  if (pContext->alsa.useVerboseDeviceEnumeration) {
13826  /* Verbose mode. Put the second line in brackets. */
13827  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), DESC, lfPos);
13828  ma_strcat_s (deviceInfo.name, sizeof(deviceInfo.name), " (");
13829  ma_strcat_s (deviceInfo.name, sizeof(deviceInfo.name), line2);
13830  ma_strcat_s (deviceInfo.name, sizeof(deviceInfo.name), ")");
13831  } else {
13832  /* Simplified mode. Strip the second line entirely. */
13833  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), DESC, lfPos);
13834  }
13835  } else {
13836  /* There's no second line. Just copy the whole description. */
13837  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), DESC, (size_t)-1);
13838  }
13839  }
13840 
13841  if (!ma_is_device_blacklisted__alsa(deviceType, NAME)) {
13842  cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
13843  }
13844 
13845  /*
13846  Some devices are both playback and capture, but they are only enumerated by ALSA once. We need to fire the callback
13847  again for the other device type in this case. We do this for known devices.
13848  */
13849  if (cbResult) {
13850  if (ma_is_common_device_name__alsa(NAME)) {
13851  if (deviceType == ma_device_type_playback) {
13852  if (!ma_is_capture_device_blacklisted__alsa(NAME)) {
13853  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
13854  }
13855  } else {
13856  if (!ma_is_playback_device_blacklisted__alsa(NAME)) {
13857  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
13858  }
13859  }
13860  }
13861  }
13862 
13863  if (cbResult == MA_FALSE) {
13864  stopEnumeration = MA_TRUE;
13865  }
13866 
13867  next_device:
13868  free(NAME);
13869  free(DESC);
13870  free(IOID);
13871  ppNextDeviceHint += 1;
13872 
13873  /* We need to stop enumeration if the callback returned false. */
13874  if (stopEnumeration) {
13875  break;
13876  }
13877  }
13878 
13879  ma__free_from_callbacks(pUniqueIDs, &pContext->allocationCallbacks);
13880  ((ma_snd_device_name_free_hint_proc)pContext->alsa.snd_device_name_free_hint)((void**)ppDeviceHints);
13881 
13882  ma_mutex_unlock(&pContext->alsa.internalDeviceEnumLock);
13883 
13884  return MA_SUCCESS;
13885 }
13886 
13887 
13888 typedef struct
13889 {
13890  ma_device_type deviceType;
13891  const ma_device_id* pDeviceID;
13892  ma_share_mode shareMode;
13893  ma_device_info* pDeviceInfo;
13894  ma_bool32 foundDevice;
13895 } ma_context_get_device_info_enum_callback_data__alsa;
13896 
13897 static ma_bool32 ma_context_get_device_info_enum_callback__alsa(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pDeviceInfo, void* pUserData)
13898 {
13899  ma_context_get_device_info_enum_callback_data__alsa* pData = (ma_context_get_device_info_enum_callback_data__alsa*)pUserData;
13900  MA_ASSERT(pData != NULL);
13901 
13902  (void)pContext;
13903 
13904  if (pData->pDeviceID == NULL && ma_strcmp(pDeviceInfo->id.alsa, "default") == 0) {
13905  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pDeviceInfo->name, (size_t)-1);
13906  pData->foundDevice = MA_TRUE;
13907  } else {
13908  if (pData->deviceType == deviceType && (pData->pDeviceID != NULL && ma_strcmp(pData->pDeviceID->alsa, pDeviceInfo->id.alsa) == 0)) {
13909  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pDeviceInfo->name, (size_t)-1);
13910  pData->foundDevice = MA_TRUE;
13911  }
13912  }
13913 
13914  /* Keep enumerating until we have found the device. */
13915  return !pData->foundDevice;
13916 }
13917 
13918 static void ma_context_test_rate_and_add_native_data_format__alsa(ma_context* pContext, ma_snd_pcm_t* pPCM, ma_snd_pcm_hw_params_t* pHWParams, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 flags, ma_device_info* pDeviceInfo)
13919 {
13920  MA_ASSERT(pPCM != NULL);
13921  MA_ASSERT(pHWParams != NULL);
13922  MA_ASSERT(pDeviceInfo != NULL);
13923 
13924  if (pDeviceInfo->nativeDataFormatCount < ma_countof(pDeviceInfo->nativeDataFormats) && ((ma_snd_pcm_hw_params_test_rate_proc)pContext->alsa.snd_pcm_hw_params_test_rate)(pPCM, pHWParams, sampleRate, 0) == 0) {
13925  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
13926  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
13927  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
13928  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = flags;
13929  pDeviceInfo->nativeDataFormatCount += 1;
13930  }
13931 }
13932 
13933 static void ma_context_iterate_rates_and_add_native_data_format__alsa(ma_context* pContext, ma_snd_pcm_t* pPCM, ma_snd_pcm_hw_params_t* pHWParams, ma_format format, ma_uint32 channels, ma_uint32 flags, ma_device_info* pDeviceInfo)
13934 {
13935  ma_uint32 iSampleRate;
13936  unsigned int minSampleRate;
13937  unsigned int maxSampleRate;
13938  int sampleRateDir; /* Not used. Just passed into snd_pcm_hw_params_get_rate_min/max(). */
13939 
13940  /* There could be a range. */
13941  ((ma_snd_pcm_hw_params_get_rate_min_proc)pContext->alsa.snd_pcm_hw_params_get_rate_min)(pHWParams, &minSampleRate, &sampleRateDir);
13942  ((ma_snd_pcm_hw_params_get_rate_max_proc)pContext->alsa.snd_pcm_hw_params_get_rate_max)(pHWParams, &maxSampleRate, &sampleRateDir);
13943 
13944  /* Make sure our sample rates are clamped to sane values. Stupid devices like "pulse" will reports rates like "1" which is ridiculus. */
13945  minSampleRate = ma_clamp(minSampleRate, (unsigned int)ma_standard_sample_rate_min, (unsigned int)ma_standard_sample_rate_max);
13946  maxSampleRate = ma_clamp(maxSampleRate, (unsigned int)ma_standard_sample_rate_min, (unsigned int)ma_standard_sample_rate_max);
13947 
13948  for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); iSampleRate += 1) {
13949  ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iSampleRate];
13950 
13951  if (standardSampleRate >= minSampleRate && standardSampleRate <= maxSampleRate) {
13952  ma_context_test_rate_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, standardSampleRate, flags, pDeviceInfo);
13953  }
13954  }
13955 
13956  /* Now make sure our min and max rates are included just in case they aren't in the range of our standard rates. */
13957  if (!ma_is_standard_sample_rate(minSampleRate)) {
13958  ma_context_test_rate_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, minSampleRate, flags, pDeviceInfo);
13959  }
13960 
13961  if (!ma_is_standard_sample_rate(maxSampleRate) && maxSampleRate != minSampleRate) {
13962  ma_context_test_rate_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, maxSampleRate, flags, pDeviceInfo);
13963  }
13964 }
13965 
13966 static ma_result ma_context_get_device_info__alsa(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
13967 {
13968  ma_context_get_device_info_enum_callback_data__alsa data;
13969  ma_result result;
13970  int resultALSA;
13971  ma_snd_pcm_t* pPCM;
13972  ma_snd_pcm_hw_params_t* pHWParams;
13973  ma_uint32 iFormat;
13974  ma_uint32 iChannel;
13975 
13976  MA_ASSERT(pContext != NULL);
13977 
13978  /* We just enumerate to find basic information about the device. */
13979  data.deviceType = deviceType;
13980  data.pDeviceID = pDeviceID;
13981  data.pDeviceInfo = pDeviceInfo;
13982  data.foundDevice = MA_FALSE;
13983  result = ma_context_enumerate_devices__alsa(pContext, ma_context_get_device_info_enum_callback__alsa, &data);
13984  if (result != MA_SUCCESS) {
13985  return result;
13986  }
13987 
13988  if (!data.foundDevice) {
13989  return MA_NO_DEVICE;
13990  }
13991 
13992  if (ma_strcmp(pDeviceInfo->id.alsa, "default") == 0) {
13993  pDeviceInfo->isDefault = MA_TRUE;
13994  }
13995 
13996  /* For detailed info we need to open the device. */
13997  result = ma_context_open_pcm__alsa(pContext, ma_share_mode_shared, deviceType, pDeviceID, 0, &pPCM);
13998  if (result != MA_SUCCESS) {
13999  return result;
14000  }
14001 
14002  /* We need to initialize a HW parameters object in order to know what formats are supported. */
14003  pHWParams = (ma_snd_pcm_hw_params_t*)ma__calloc_from_callbacks(((ma_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)(), &pContext->allocationCallbacks);
14004  if (pHWParams == NULL) {
14005  ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
14006  return MA_OUT_OF_MEMORY;
14007  }
14008 
14009  resultALSA = ((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
14010  if (resultALSA < 0) {
14011  ma__free_from_callbacks(pHWParams, &pContext->allocationCallbacks);
14012  ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
14013  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to initialize hardware parameters. snd_pcm_hw_params_any() failed.", ma_result_from_errno(-resultALSA));
14014  }
14015 
14016  /*
14017  Some ALSA devices can support many permutations of formats, channels and rates. We only support
14018  a fixed number of permutations which means we need to employ some strategies to ensure the best
14019  combinations are returned. An example is the "pulse" device which can do it's own data conversion
14020  in software and as a result can support any combination of format, channels and rate.
14021 
14022  We want to ensure the the first data formats are the best. We have a list of favored sample
14023  formats and sample rates, so these will be the basis of our iteration.
14024  */
14025 
14026  /* Formats. We just iterate over our standard formats and test them, making sure we reset the configuration space each iteration. */
14027  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); iFormat += 1) {
14028  ma_format format = g_maFormatPriorities[iFormat];
14029 
14030  /*
14031  For each format we need to make sure we reset the configuration space so we don't return
14032  channel counts and rates that aren't compatible with a format.
14033  */
14034  ((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
14035 
14036  /* Test the format first. If this fails it means the format is not supported and we can skip it. */
14037  if (((ma_snd_pcm_hw_params_test_format_proc)pContext->alsa.snd_pcm_hw_params_test_format)(pPCM, pHWParams, ma_convert_ma_format_to_alsa_format(format)) == 0) {
14038  /* The format is supported. */
14039  unsigned int minChannels;
14040  unsigned int maxChannels;
14041 
14042  /*
14043  The configuration space needs to be restricted to this format so we can get an accurate
14044  picture of which sample rates and channel counts are support with this format.
14045  */
14046  ((ma_snd_pcm_hw_params_set_format_proc)pContext->alsa.snd_pcm_hw_params_set_format)(pPCM, pHWParams, ma_convert_ma_format_to_alsa_format(format));
14047 
14048  /* Now we need to check for supported channels. */
14049  ((ma_snd_pcm_hw_params_get_channels_min_proc)pContext->alsa.snd_pcm_hw_params_get_channels_min)(pHWParams, &minChannels);
14050  ((ma_snd_pcm_hw_params_get_channels_max_proc)pContext->alsa.snd_pcm_hw_params_get_channels_max)(pHWParams, &maxChannels);
14051 
14052  if (minChannels > MA_MAX_CHANNELS) {
14053  continue; /* Too many channels. */
14054  }
14055  if (maxChannels < MA_MIN_CHANNELS) {
14056  continue; /* Not enough channels. */
14057  }
14058 
14059  /*
14060  Make sure the channel count is clamped. This is mainly intended for the max channels
14061  because some devices can report an unbound maximum.
14062  */
14063  minChannels = ma_clamp(minChannels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
14064  maxChannels = ma_clamp(maxChannels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
14065 
14066  if (minChannels == MA_MIN_CHANNELS && maxChannels == MA_MAX_CHANNELS) {
14067  /* The device supports all channels. Don't iterate over every single one. Instead just set the channels to 0 which means all channels are supported. */
14068  ma_context_iterate_rates_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, 0, 0, pDeviceInfo); /* Intentionally setting the channel count to 0 as that means all channels are supported. */
14069  } else {
14070  /* The device only supports a specific set of channels. We need to iterate over all of them. */
14071  for (iChannel = minChannels; iChannel <= maxChannels; iChannel += 1) {
14072  /* Test the channel before applying it to the configuration space. */
14073  unsigned int channels = iChannel;
14074 
14075  /* Make sure our channel range is reset before testing again or else we'll always fail the test. */
14076  ((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
14077  ((ma_snd_pcm_hw_params_set_format_proc)pContext->alsa.snd_pcm_hw_params_set_format)(pPCM, pHWParams, ma_convert_ma_format_to_alsa_format(format));
14078 
14079  if (((ma_snd_pcm_hw_params_test_channels_proc)pContext->alsa.snd_pcm_hw_params_test_channels)(pPCM, pHWParams, channels) == 0) {
14080  /* The channel count is supported. */
14081 
14082  /* The configuration space now needs to be restricted to the channel count before extracting the sample rate. */
14083  ((ma_snd_pcm_hw_params_set_channels_proc)pContext->alsa.snd_pcm_hw_params_set_channels)(pPCM, pHWParams, channels);
14084 
14085  /* Only after the configuration space has been restricted to the specific channel count should we iterate over our sample rates. */
14086  ma_context_iterate_rates_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, 0, pDeviceInfo);
14087  } else {
14088  /* The channel count is not supported. Skip. */
14089  }
14090  }
14091  }
14092  } else {
14093  /* The format is not supported. Skip. */
14094  }
14095  }
14096 
14097  ma__free_from_callbacks(pHWParams, &pContext->allocationCallbacks);
14098 
14099  ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
14100  return MA_SUCCESS;
14101 }
14102 
14103 static ma_result ma_device_uninit__alsa(ma_device* pDevice)
14104 {
14105  MA_ASSERT(pDevice != NULL);
14106 
14107  if ((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) {
14108  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
14109  close(pDevice->alsa.wakeupfdCapture);
14110  ma_free(pDevice->alsa.pPollDescriptorsCapture, &pDevice->pContext->allocationCallbacks);
14111  }
14112 
14113  if ((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) {
14114  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
14115  close(pDevice->alsa.wakeupfdPlayback);
14116  ma_free(pDevice->alsa.pPollDescriptorsPlayback, &pDevice->pContext->allocationCallbacks);
14117  }
14118 
14119  return MA_SUCCESS;
14120 }
14121 
14122 static ma_result ma_device_init_by_type__alsa(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
14123 {
14124  ma_result result;
14125  int resultALSA;
14126  ma_snd_pcm_t* pPCM;
14127  ma_bool32 isUsingMMap;
14128  ma_snd_pcm_format_t formatALSA;
14129  ma_format internalFormat;
14130  ma_uint32 internalChannels;
14131  ma_uint32 internalSampleRate;
14132  ma_channel internalChannelMap[MA_MAX_CHANNELS];
14133  ma_uint32 internalPeriodSizeInFrames;
14134  ma_uint32 internalPeriods;
14135  int openMode;
14136  ma_snd_pcm_hw_params_t* pHWParams;
14137  ma_snd_pcm_sw_params_t* pSWParams;
14138  ma_snd_pcm_uframes_t bufferBoundary;
14139  int pollDescriptorCount;
14140  struct pollfd* pPollDescriptors;
14141  int wakeupfd;
14142 
14143  MA_ASSERT(pConfig != NULL);
14144  MA_ASSERT(deviceType != ma_device_type_duplex); /* This function should only be called for playback _or_ capture, never duplex. */
14145  MA_ASSERT(pDevice != NULL);
14146 
14147  formatALSA = ma_convert_ma_format_to_alsa_format(pDescriptor->format);
14148 
14149  openMode = 0;
14150  if (pConfig->alsa.noAutoResample) {
14151  openMode |= MA_SND_PCM_NO_AUTO_RESAMPLE;
14152  }
14153  if (pConfig->alsa.noAutoChannels) {
14154  openMode |= MA_SND_PCM_NO_AUTO_CHANNELS;
14155  }
14156  if (pConfig->alsa.noAutoFormat) {
14157  openMode |= MA_SND_PCM_NO_AUTO_FORMAT;
14158  }
14159 
14160  result = ma_context_open_pcm__alsa(pDevice->pContext, pDescriptor->shareMode, deviceType, pDescriptor->pDeviceID, openMode, &pPCM);
14161  if (result != MA_SUCCESS) {
14162  return result;
14163  }
14164 
14165 
14166  /* Hardware parameters. */
14167  pHWParams = (ma_snd_pcm_hw_params_t*)ma__calloc_from_callbacks(((ma_snd_pcm_hw_params_sizeof_proc)pDevice->pContext->alsa.snd_pcm_hw_params_sizeof)(), &pDevice->pContext->allocationCallbacks);
14168  if (pHWParams == NULL) {
14169  return MA_OUT_OF_MEMORY;
14170  }
14171 
14172  resultALSA = ((ma_snd_pcm_hw_params_any_proc)pDevice->pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
14173  if (resultALSA < 0) {
14174  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14175  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14176  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to initialize hardware parameters. snd_pcm_hw_params_any() failed.", ma_result_from_errno(-resultALSA));
14177  }
14178 
14179  /* MMAP Mode. Try using interleaved MMAP access. If this fails, fall back to standard readi/writei. */
14180  isUsingMMap = MA_FALSE;
14181 #if 0 /* NOTE: MMAP mode temporarily disabled. */
14182  if (deviceType != ma_device_type_capture) { /* <-- Disabling MMAP mode for capture devices because I apparently do not have a device that supports it which means I can't test it... Contributions welcome. */
14183  if (!pConfig->alsa.noMMap && ma_device__is_async(pDevice)) {
14184  if (((ma_snd_pcm_hw_params_set_access_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_access)(pPCM, pHWParams, MA_SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0) {
14185  pDevice->alsa.isUsingMMap = MA_TRUE;
14186  }
14187  }
14188  }
14189 #endif
14190 
14191  if (!isUsingMMap) {
14192  resultALSA = ((ma_snd_pcm_hw_params_set_access_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_access)(pPCM, pHWParams, MA_SND_PCM_ACCESS_RW_INTERLEAVED);
14193  if (resultALSA < 0) {
14194  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14195  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14196  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set access mode to neither SND_PCM_ACCESS_MMAP_INTERLEAVED nor SND_PCM_ACCESS_RW_INTERLEAVED. snd_pcm_hw_params_set_access() failed.", ma_result_from_errno(-resultALSA));
14197  }
14198  }
14199 
14200  /*
14201  Most important properties first. The documentation for OSS (yes, I know this is ALSA!) recommends format, channels, then sample rate. I can't
14202  find any documentation for ALSA specifically, so I'm going to copy the recommendation for OSS.
14203  */
14204 
14205  /* Format. */
14206  {
14207  /*
14208  At this point we should have a list of supported formats, so now we need to find the best one. We first check if the requested format is
14209  supported, and if so, use that one. If it's not supported, we just run though a list of formats and try to find the best one.
14210  */
14211  if (formatALSA == MA_SND_PCM_FORMAT_UNKNOWN || ((ma_snd_pcm_hw_params_test_format_proc)pDevice->pContext->alsa.snd_pcm_hw_params_test_format)(pPCM, pHWParams, formatALSA) != 0) {
14212  /* We're either requesting the native format or the specified format is not supported. */
14213  size_t iFormat;
14214 
14215  formatALSA = MA_SND_PCM_FORMAT_UNKNOWN;
14216  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); ++iFormat) {
14217  if (((ma_snd_pcm_hw_params_test_format_proc)pDevice->pContext->alsa.snd_pcm_hw_params_test_format)(pPCM, pHWParams, ma_convert_ma_format_to_alsa_format(g_maFormatPriorities[iFormat])) == 0) {
14218  formatALSA = ma_convert_ma_format_to_alsa_format(g_maFormatPriorities[iFormat]);
14219  break;
14220  }
14221  }
14222 
14223  if (formatALSA == MA_SND_PCM_FORMAT_UNKNOWN) {
14224  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14225  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14226  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Format not supported. The device does not support any miniaudio formats.", MA_FORMAT_NOT_SUPPORTED);
14227  }
14228  }
14229 
14230  resultALSA = ((ma_snd_pcm_hw_params_set_format_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_format)(pPCM, pHWParams, formatALSA);
14231  if (resultALSA < 0) {
14232  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14233  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14234  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Format not supported. snd_pcm_hw_params_set_format() failed.", ma_result_from_errno(-resultALSA));
14235  }
14236 
14237  internalFormat = ma_format_from_alsa(formatALSA);
14238  if (internalFormat == ma_format_unknown) {
14239  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14240  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14241  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] The chosen format is not supported by miniaudio.", MA_FORMAT_NOT_SUPPORTED);
14242  }
14243  }
14244 
14245  /* Channels. */
14246  {
14247  unsigned int channels = pDescriptor->channels;
14248  if (channels == 0) {
14249  channels = MA_DEFAULT_CHANNELS;
14250  }
14251 
14252  resultALSA = ((ma_snd_pcm_hw_params_set_channels_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_channels_near)(pPCM, pHWParams, &channels);
14253  if (resultALSA < 0) {
14254  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14255  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14256  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set channel count. snd_pcm_hw_params_set_channels_near() failed.", ma_result_from_errno(-resultALSA));
14257  }
14258 
14259  internalChannels = (ma_uint32)channels;
14260  }
14261 
14262  /* Sample Rate */
14263  {
14264  unsigned int sampleRate;
14265 
14266  /*
14267  It appears there's either a bug in ALSA, a bug in some drivers, or I'm doing something silly; but having resampling enabled causes
14268  problems with some device configurations when used in conjunction with MMAP access mode. To fix this problem we need to disable
14269  resampling.
14270 
14271  To reproduce this problem, open the "plug:dmix" device, and set the sample rate to 44100. Internally, it looks like dmix uses a
14272  sample rate of 48000. The hardware parameters will get set correctly with no errors, but it looks like the 44100 -> 48000 resampling
14273  doesn't work properly - but only with MMAP access mode. You will notice skipping/crackling in the audio, and it'll run at a slightly
14274  faster rate.
14275 
14276  miniaudio has built-in support for sample rate conversion (albeit low quality at the moment), so disabling resampling should be fine
14277  for us. The only problem is that it won't be taking advantage of any kind of hardware-accelerated resampling and it won't be very
14278  good quality until I get a chance to improve the quality of miniaudio's software sample rate conversion.
14279 
14280  I don't currently know if the dmix plugin is the only one with this error. Indeed, this is the only one I've been able to reproduce
14281  this error with. In the future, we may want to restrict the disabling of resampling to only known bad plugins.
14282  */
14283  ((ma_snd_pcm_hw_params_set_rate_resample_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_rate_resample)(pPCM, pHWParams, 0);
14284 
14285  sampleRate = pDescriptor->sampleRate;
14286  if (sampleRate == 0) {
14287  sampleRate = MA_DEFAULT_SAMPLE_RATE;
14288  }
14289 
14290  resultALSA = ((ma_snd_pcm_hw_params_set_rate_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_rate_near)(pPCM, pHWParams, &sampleRate, 0);
14291  if (resultALSA < 0) {
14292  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14293  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14294  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Sample rate not supported. snd_pcm_hw_params_set_rate_near() failed.", ma_result_from_errno(-resultALSA));
14295  }
14296 
14297  internalSampleRate = (ma_uint32)sampleRate;
14298  }
14299 
14300  /* Periods. */
14301  {
14302  ma_uint32 periods = pDescriptor->periodCount;
14303 
14304  resultALSA = ((ma_snd_pcm_hw_params_set_periods_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_periods_near)(pPCM, pHWParams, &periods, NULL);
14305  if (resultALSA < 0) {
14306  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14307  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14308  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set period count. snd_pcm_hw_params_set_periods_near() failed.", ma_result_from_errno(-resultALSA));
14309  }
14310 
14311  internalPeriods = periods;
14312  }
14313 
14314  /* Buffer Size */
14315  {
14316  ma_snd_pcm_uframes_t actualBufferSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, internalSampleRate, pConfig->performanceProfile) * internalPeriods;
14317 
14318  resultALSA = ((ma_snd_pcm_hw_params_set_buffer_size_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_buffer_size_near)(pPCM, pHWParams, &actualBufferSizeInFrames);
14319  if (resultALSA < 0) {
14320  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14321  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14322  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set buffer size for device. snd_pcm_hw_params_set_buffer_size() failed.", ma_result_from_errno(-resultALSA));
14323  }
14324 
14325  internalPeriodSizeInFrames = actualBufferSizeInFrames / internalPeriods;
14326  }
14327 
14328  /* Apply hardware parameters. */
14329  resultALSA = ((ma_snd_pcm_hw_params_proc)pDevice->pContext->alsa.snd_pcm_hw_params)(pPCM, pHWParams);
14330  if (resultALSA < 0) {
14331  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14332  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14333  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set hardware parameters. snd_pcm_hw_params() failed.", ma_result_from_errno(-resultALSA));
14334  }
14335 
14336  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
14337  pHWParams = NULL;
14338 
14339 
14340  /* Software parameters. */
14341  pSWParams = (ma_snd_pcm_sw_params_t*)ma__calloc_from_callbacks(((ma_snd_pcm_sw_params_sizeof_proc)pDevice->pContext->alsa.snd_pcm_sw_params_sizeof)(), &pDevice->pContext->allocationCallbacks);
14342  if (pSWParams == NULL) {
14343  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14344  return MA_OUT_OF_MEMORY;
14345  }
14346 
14347  resultALSA = ((ma_snd_pcm_sw_params_current_proc)pDevice->pContext->alsa.snd_pcm_sw_params_current)(pPCM, pSWParams);
14348  if (resultALSA < 0) {
14349  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
14350  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14351  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to initialize software parameters. snd_pcm_sw_params_current() failed.", ma_result_from_errno(-resultALSA));
14352  }
14353 
14354  resultALSA = ((ma_snd_pcm_sw_params_set_avail_min_proc)pDevice->pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, ma_prev_power_of_2(internalPeriodSizeInFrames));
14355  if (resultALSA < 0) {
14356  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
14357  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14358  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_sw_params_set_avail_min() failed.", ma_result_from_errno(-resultALSA));
14359  }
14360 
14361  resultALSA = ((ma_snd_pcm_sw_params_get_boundary_proc)pDevice->pContext->alsa.snd_pcm_sw_params_get_boundary)(pSWParams, &bufferBoundary);
14362  if (resultALSA < 0) {
14363  bufferBoundary = internalPeriodSizeInFrames * internalPeriods;
14364  }
14365 
14366  if (deviceType == ma_device_type_playback && !isUsingMMap) { /* Only playback devices in writei/readi mode need a start threshold. */
14367  /*
14368  Subtle detail here with the start threshold. When in playback-only mode (no full-duplex) we can set the start threshold to
14369  the size of a period. But for full-duplex we need to set it such that it is at least two periods.
14370  */
14371  resultALSA = ((ma_snd_pcm_sw_params_set_start_threshold_proc)pDevice->pContext->alsa.snd_pcm_sw_params_set_start_threshold)(pPCM, pSWParams, internalPeriodSizeInFrames*2);
14372  if (resultALSA < 0) {
14373  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
14374  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14375  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set start threshold for playback device. snd_pcm_sw_params_set_start_threshold() failed.", ma_result_from_errno(-resultALSA));
14376  }
14377 
14378  resultALSA = ((ma_snd_pcm_sw_params_set_stop_threshold_proc)pDevice->pContext->alsa.snd_pcm_sw_params_set_stop_threshold)(pPCM, pSWParams, bufferBoundary);
14379  if (resultALSA < 0) { /* Set to boundary to loop instead of stop in the event of an xrun. */
14380  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
14381  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14382  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set stop threshold for playback device. snd_pcm_sw_params_set_stop_threshold() failed.", ma_result_from_errno(-resultALSA));
14383  }
14384  }
14385 
14386  resultALSA = ((ma_snd_pcm_sw_params_proc)pDevice->pContext->alsa.snd_pcm_sw_params)(pPCM, pSWParams);
14387  if (resultALSA < 0) {
14388  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
14389  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14390  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to set software parameters. snd_pcm_sw_params() failed.", ma_result_from_errno(-resultALSA));
14391  }
14392 
14393  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
14394  pSWParams = NULL;
14395 
14396 
14397  /* Grab the internal channel map. For now we're not going to bother trying to change the channel map and instead just do it ourselves. */
14398  {
14399  ma_snd_pcm_chmap_t* pChmap = ((ma_snd_pcm_get_chmap_proc)pDevice->pContext->alsa.snd_pcm_get_chmap)(pPCM);
14400  if (pChmap != NULL) {
14401  ma_uint32 iChannel;
14402 
14403  /* There are cases where the returned channel map can have a different channel count than was returned by snd_pcm_hw_params_set_channels_near(). */
14404  if (pChmap->channels >= internalChannels) {
14405  /* Drop excess channels. */
14406  for (iChannel = 0; iChannel < internalChannels; ++iChannel) {
14407  internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
14408  }
14409  } else {
14410  ma_uint32 i;
14411 
14412  /*
14413  Excess channels use defaults. Do an initial fill with defaults, overwrite the first pChmap->channels, validate to ensure there are no duplicate
14414  channels. If validation fails, fall back to defaults.
14415  */
14416  ma_bool32 isValid = MA_TRUE;
14417 
14418  /* Fill with defaults. */
14419  ma_get_standard_channel_map(ma_standard_channel_map_alsa, internalChannels, internalChannelMap);
14420 
14421  /* Overwrite first pChmap->channels channels. */
14422  for (iChannel = 0; iChannel < pChmap->channels; ++iChannel) {
14423  internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
14424  }
14425 
14426  /* Validate. */
14427  for (i = 0; i < internalChannels && isValid; ++i) {
14428  ma_uint32 j;
14429  for (j = i+1; j < internalChannels; ++j) {
14430  if (internalChannelMap[i] == internalChannelMap[j]) {
14431  isValid = MA_FALSE;
14432  break;
14433  }
14434  }
14435  }
14436 
14437  /* If our channel map is invalid, fall back to defaults. */
14438  if (!isValid) {
14439  ma_get_standard_channel_map(ma_standard_channel_map_alsa, internalChannels, internalChannelMap);
14440  }
14441  }
14442 
14443  free(pChmap);
14444  pChmap = NULL;
14445  } else {
14446  /* Could not retrieve the channel map. Fall back to a hard-coded assumption. */
14447  ma_get_standard_channel_map(ma_standard_channel_map_alsa, internalChannels, internalChannelMap);
14448  }
14449  }
14450 
14451 
14452  /*
14453  We need to retrieve the poll descriptors so we can use poll() to wait for data to become
14454  available for reading or writing. There's no well defined maximum for this so we're just going
14455  to allocate this on the heap.
14456  */
14457  pollDescriptorCount = ((ma_snd_pcm_poll_descriptors_count_proc)pDevice->pContext->alsa.snd_pcm_poll_descriptors_count)(pPCM);
14458  if (pollDescriptorCount <= 0) {
14459  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14460  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to retrieve poll descriptors count.", MA_ERROR);
14461  }
14462 
14463  pPollDescriptors = (struct pollfd*)ma_malloc(sizeof(*pPollDescriptors) * (pollDescriptorCount + 1), &pDevice->pContext->allocationCallbacks/*, MA_ALLOCATION_TYPE_GENERAL*/); /* +1 because we want room for the wakeup descriptor. */
14464  if (pPollDescriptors == NULL) {
14465  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14466  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to allocate memory for poll descriptors.", MA_OUT_OF_MEMORY);
14467  }
14468 
14469  /*
14470  We need an eventfd to wakeup from poll() and avoid a deadlock in situations where the driver
14471  never returns from writei() and readi(). This has been observed with the "pulse" device.
14472  */
14473  wakeupfd = eventfd(0, 0);
14474  if (wakeupfd < 0) {
14475  ma_free(pPollDescriptors, &pDevice->pContext->allocationCallbacks);
14476  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14477  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to create eventfd for poll wakeup.", ma_result_from_errno(errno));
14478  }
14479 
14480  /* We'll place the wakeup fd at the start of the buffer. */
14481  pPollDescriptors[0].fd = wakeupfd;
14482  pPollDescriptors[0].events = POLLIN; /* We only care about waiting to read from the wakeup file descriptor. */
14483  pPollDescriptors[0].revents = 0;
14484 
14485  /* We can now extract the PCM poll descriptors which we place after the wakeup descriptor. */
14486  pollDescriptorCount = ((ma_snd_pcm_poll_descriptors_proc)pDevice->pContext->alsa.snd_pcm_poll_descriptors)(pPCM, pPollDescriptors + 1, pollDescriptorCount); /* +1 because we want to place these descriptors after the wakeup descriptor. */
14487  if (pollDescriptorCount <= 0) {
14488  close(wakeupfd);
14489  ma_free(pPollDescriptors, &pDevice->pContext->allocationCallbacks);
14490  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14491  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to retrieve poll descriptors.", MA_ERROR);
14492  }
14493 
14494  if (deviceType == ma_device_type_capture) {
14495  pDevice->alsa.pollDescriptorCountCapture = pollDescriptorCount;
14496  pDevice->alsa.pPollDescriptorsCapture = pPollDescriptors;
14497  pDevice->alsa.wakeupfdCapture = wakeupfd;
14498  } else {
14499  pDevice->alsa.pollDescriptorCountPlayback = pollDescriptorCount;
14500  pDevice->alsa.pPollDescriptorsPlayback = pPollDescriptors;
14501  pDevice->alsa.wakeupfdPlayback = wakeupfd;
14502  }
14503 
14504 
14505  /* We're done. Prepare the device. */
14506  resultALSA = ((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)(pPCM);
14507  if (resultALSA < 0) {
14508  close(wakeupfd);
14509  ma_free(pPollDescriptors, &pDevice->pContext->allocationCallbacks);
14510  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14511  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to prepare device.", ma_result_from_errno(-resultALSA));
14512  }
14513 
14514 
14515  if (deviceType == ma_device_type_capture) {
14516  pDevice->alsa.pPCMCapture = (ma_ptr)pPCM;
14517  pDevice->alsa.isUsingMMapCapture = isUsingMMap;
14518  } else {
14519  pDevice->alsa.pPCMPlayback = (ma_ptr)pPCM;
14520  pDevice->alsa.isUsingMMapPlayback = isUsingMMap;
14521  }
14522 
14523  pDescriptor->format = internalFormat;
14524  pDescriptor->channels = internalChannels;
14525  pDescriptor->sampleRate = internalSampleRate;
14526  ma_channel_map_copy(pDescriptor->channelMap, internalChannelMap, ma_min(internalChannels, MA_MAX_CHANNELS));
14527  pDescriptor->periodSizeInFrames = internalPeriodSizeInFrames;
14528  pDescriptor->periodCount = internalPeriods;
14529 
14530  return MA_SUCCESS;
14531 }
14532 
14533 static ma_result ma_device_init__alsa(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
14534 {
14535  MA_ASSERT(pDevice != NULL);
14536 
14537  MA_ZERO_OBJECT(&pDevice->alsa);
14538 
14539  if (pConfig->deviceType == ma_device_type_loopback) {
14541  }
14542 
14543  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
14544  ma_result result = ma_device_init_by_type__alsa(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
14545  if (result != MA_SUCCESS) {
14546  return result;
14547  }
14548  }
14549 
14550  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
14551  ma_result result = ma_device_init_by_type__alsa(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
14552  if (result != MA_SUCCESS) {
14553  return result;
14554  }
14555  }
14556 
14557  return MA_SUCCESS;
14558 }
14559 
14560 static ma_result ma_device_start__alsa(ma_device* pDevice)
14561 {
14562  int resultALSA;
14563 
14564  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
14565  resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
14566  if (resultALSA < 0) {
14567  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start capture device.", ma_result_from_errno(-resultALSA));
14568  }
14569  }
14570 
14571  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
14572  /* Don't need to do anything for playback because it'll be started automatically when enough data has been written. */
14573  }
14574 
14575  return MA_SUCCESS;
14576 }
14577 
14578 static ma_result ma_device_stop__alsa(ma_device* pDevice)
14579 {
14580  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
14581  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device... ");
14582  ((ma_snd_pcm_drop_proc)pDevice->pContext->alsa.snd_pcm_drop)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
14583  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
14584 
14585  /* We need to prepare the device again, otherwise we won't be able to restart the device. */
14586  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device... ");
14587  if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
14588  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Failed\n");
14589  } else {
14590  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
14591  }
14592  }
14593 
14594  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
14595  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping playback device... ");
14596  ((ma_snd_pcm_drop_proc)pDevice->pContext->alsa.snd_pcm_drop)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
14597  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
14598 
14599  /* We need to prepare the device again, otherwise we won't be able to restart the device. */
14600  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing playback device... ");
14601  if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) < 0) {
14602  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Failed\n");
14603  } else {
14604  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
14605  }
14606  }
14607 
14608  return MA_SUCCESS;
14609 }
14610 
14611 static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, struct pollfd* pPollDescriptors, int pollDescriptorCount, short requiredEvent)
14612 {
14613  for (;;) {
14614  unsigned short revents;
14615  int resultALSA;
14616  int resultPoll = poll(pPollDescriptors, pollDescriptorCount, -1);
14617  if (resultPoll < 0) {
14618  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] poll() failed.", ma_result_from_errno(errno));
14619  }
14620 
14621  /*
14622  Before checking the ALSA poll descriptor flag we need to check if the wakeup descriptor
14623  has had it's POLLIN flag set. If so, we need to actually read the data and then exit
14624  function. The wakeup descriptor will be the first item in the descriptors buffer.
14625  */
14626  if ((pPollDescriptors[0].revents & POLLIN) != 0) {
14627  ma_uint64 t;
14628  read(pPollDescriptors[0].fd, &t, sizeof(t)); /* <-- Important that we read here so that the next write() does not block. */
14629 
14630  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] POLLIN set for wakeupfd\n");
14631 
14632  return MA_DEVICE_NOT_STARTED;
14633  }
14634 
14635  /*
14636  Getting here means that some data should be able to be read. We need to use ALSA to
14637  translate the revents flags for us.
14638  */
14639  resultALSA = ((ma_snd_pcm_poll_descriptors_revents_proc)pDevice->pContext->alsa.snd_pcm_poll_descriptors_revents)(pPCM, pPollDescriptors + 1, pollDescriptorCount - 1, &revents); /* +1, -1 to ignore the wakeup descriptor. */
14640  if (resultALSA < 0) {
14641  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_poll_descriptors_revents() failed.", ma_result_from_errno(-resultALSA));
14642  }
14643 
14644  if ((revents & POLLERR) != 0) {
14645  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] POLLERR detected.", ma_result_from_errno(errno));
14646  }
14647 
14648  if ((revents & requiredEvent) == requiredEvent) {
14649  break; /* We're done. Data available for reading or writing. */
14650  }
14651  }
14652 
14653  return MA_SUCCESS;
14654 }
14655 
14656 static ma_result ma_device_wait_read__alsa(ma_device* pDevice)
14657 {
14658  return ma_device_wait__alsa(pDevice, (ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, (struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, pDevice->alsa.pollDescriptorCountCapture + 1, POLLIN); /* +1 to account for the wakeup descriptor. */
14659 }
14660 
14661 static ma_result ma_device_wait_write__alsa(ma_device* pDevice)
14662 {
14663  return ma_device_wait__alsa(pDevice, (ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, (struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, pDevice->alsa.pollDescriptorCountPlayback + 1, POLLOUT); /* +1 to account for the wakeup descriptor. */
14664 }
14665 
14666 static ma_result ma_device_read__alsa(ma_device* pDevice, void* pFramesOut, ma_uint32 frameCount, ma_uint32* pFramesRead)
14667 {
14668  ma_snd_pcm_sframes_t resultALSA;
14669 
14670  MA_ASSERT(pDevice != NULL);
14671  MA_ASSERT(pFramesOut != NULL);
14672 
14673  if (pFramesRead != NULL) {
14674  *pFramesRead = 0;
14675  }
14676 
14677  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
14678  ma_result result;
14679 
14680  /* The first thing to do is wait for data to become available for reading. This will return an error code if the device has been stopped. */
14681  result = ma_device_wait_read__alsa(pDevice);
14682  if (result != MA_SUCCESS) {
14683  return result;
14684  }
14685 
14686  /* Getting here means we should have data available. */
14687  resultALSA = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, pFramesOut, frameCount);
14688  if (resultALSA >= 0) {
14689  break; /* Success. */
14690  } else {
14691  if (resultALSA == -EAGAIN) {
14692  /*ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EGAIN (read)\n");*/
14693  continue; /* Try again. */
14694  } else if (resultALSA == -EPIPE) {
14695  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EPIPE (read)\n");
14696 
14697  /* Overrun. Recover and try again. If this fails we need to return an error. */
14698  resultALSA = ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, resultALSA, MA_TRUE);
14699  if (resultALSA < 0) {
14700  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to recover device after overrun.", ma_result_from_errno((int)-resultALSA));
14701  }
14702 
14703  resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
14704  if (resultALSA < 0) {
14705  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start device after underrun.", ma_result_from_errno((int)-resultALSA));
14706  }
14707 
14708  continue; /* Try reading again. */
14709  }
14710  }
14711  }
14712 
14713  if (pFramesRead != NULL) {
14714  *pFramesRead = resultALSA;
14715  }
14716 
14717  return MA_SUCCESS;
14718 }
14719 
14720 static ma_result ma_device_write__alsa(ma_device* pDevice, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
14721 {
14722  ma_snd_pcm_sframes_t resultALSA;
14723 
14724  MA_ASSERT(pDevice != NULL);
14725  MA_ASSERT(pFrames != NULL);
14726 
14727  if (pFramesWritten != NULL) {
14728  *pFramesWritten = 0;
14729  }
14730 
14731  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
14732  ma_result result;
14733 
14734  /* The first thing to do is wait for space to become available for writing. This will return an error code if the device has been stopped. */
14735  result = ma_device_wait_write__alsa(pDevice);
14736  if (result != MA_SUCCESS) {
14737  return result;
14738  }
14739 
14740  resultALSA = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, pFrames, frameCount);
14741  if (resultALSA >= 0) {
14742  break; /* Success. */
14743  } else {
14744  if (resultALSA == -EAGAIN) {
14745  /*ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EGAIN (write)\n");*/
14746  continue; /* Try again. */
14747  } else if (resultALSA == -EPIPE) {
14748  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EPIPE (write)\n");
14749 
14750  /* Underrun. Recover and try again. If this fails we need to return an error. */
14751  resultALSA = ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, resultALSA, MA_TRUE); /* MA_TRUE=silent (don't print anything on error). */
14752  if (resultALSA < 0) {
14753  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to recover device after underrun.", ma_result_from_errno((int)-resultALSA));
14754  }
14755 
14756  /*
14757  In my testing I have had a situation where writei() does not automatically restart the device even though I've set it
14758  up as such in the software parameters. What will happen is writei() will block indefinitely even though the number of
14759  frames is well beyond the auto-start threshold. To work around this I've needed to add an explicit start here. Not sure
14760  if this is me just being stupid and not recovering the device properly, but this definitely feels like something isn't
14761  quite right here.
14762  */
14763  resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
14764  if (resultALSA < 0) {
14765  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start device after underrun.", ma_result_from_errno((int)-resultALSA));
14766  }
14767 
14768  continue; /* Try writing again. */
14769  }
14770  }
14771  }
14772 
14773  if (pFramesWritten != NULL) {
14774  *pFramesWritten = resultALSA;
14775  }
14776 
14777  return MA_SUCCESS;
14778 }
14779 
14780 static ma_result ma_device_data_loop_wakeup__alsa(ma_device* pDevice)
14781 {
14782  ma_uint64 t = 1;
14783 
14784  MA_ASSERT(pDevice != NULL);
14785 
14786  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Waking up... ");
14787 
14788  /* Write to an eventfd to trigger a wakeup from poll() and abort any reading or writing. */
14789  if (pDevice->alsa.pPollDescriptorsCapture != NULL) {
14790  write(pDevice->alsa.wakeupfdCapture, &t, sizeof(t));
14791  }
14792  if (pDevice->alsa.pPollDescriptorsPlayback != NULL) {
14793  write(pDevice->alsa.wakeupfdPlayback, &t, sizeof(t));
14794  }
14795 
14796  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
14797 
14798  return MA_SUCCESS;
14799 }
14800 
14801 static ma_result ma_context_uninit__alsa(ma_context* pContext)
14802 {
14803  MA_ASSERT(pContext != NULL);
14804  MA_ASSERT(pContext->backend == ma_backend_alsa);
14805 
14806  /* Clean up memory for memory leak checkers. */
14807  ((ma_snd_config_update_free_global_proc)pContext->alsa.snd_config_update_free_global)();
14808 
14809 #ifndef MA_NO_RUNTIME_LINKING
14810  ma_dlclose(pContext, pContext->alsa.asoundSO);
14811 #endif
14812 
14813  ma_mutex_uninit(&pContext->alsa.internalDeviceEnumLock);
14814 
14815  return MA_SUCCESS;
14816 }
14817 
14818 static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
14819 {
14820 #ifndef MA_NO_RUNTIME_LINKING
14821  const char* libasoundNames[] = {
14822  "libasound.so.2",
14823  "libasound.so"
14824  };
14825  size_t i;
14826 
14827  for (i = 0; i < ma_countof(libasoundNames); ++i) {
14828  pContext->alsa.asoundSO = ma_dlopen(pContext, libasoundNames[i]);
14829  if (pContext->alsa.asoundSO != NULL) {
14830  break;
14831  }
14832  }
14833 
14834  if (pContext->alsa.asoundSO == NULL) {
14835  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to open shared object.\n");
14836  return MA_NO_BACKEND;
14837  }
14838 
14839  pContext->alsa.snd_pcm_open = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_open");
14840  pContext->alsa.snd_pcm_close = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_close");
14841  pContext->alsa.snd_pcm_hw_params_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_sizeof");
14842  pContext->alsa.snd_pcm_hw_params_any = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_any");
14843  pContext->alsa.snd_pcm_hw_params_set_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_format");
14844  pContext->alsa.snd_pcm_hw_params_set_format_first = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_format_first");
14845  pContext->alsa.snd_pcm_hw_params_get_format_mask = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_format_mask");
14846  pContext->alsa.snd_pcm_hw_params_set_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels");
14847  pContext->alsa.snd_pcm_hw_params_set_channels_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels_near");
14848  pContext->alsa.snd_pcm_hw_params_set_channels_minmax = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels_minmax");
14849  pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate_resample");
14850  pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate");
14851  pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate_near");
14852  pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_buffer_size_near");
14853  pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_periods_near");
14854  pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_access");
14855  pContext->alsa.snd_pcm_hw_params_get_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_format");
14856  pContext->alsa.snd_pcm_hw_params_get_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels");
14857  pContext->alsa.snd_pcm_hw_params_get_channels_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels_min");
14858  pContext->alsa.snd_pcm_hw_params_get_channels_max = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels_max");
14859  pContext->alsa.snd_pcm_hw_params_get_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate");
14860  pContext->alsa.snd_pcm_hw_params_get_rate_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate_min");
14861  pContext->alsa.snd_pcm_hw_params_get_rate_max = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate_max");
14862  pContext->alsa.snd_pcm_hw_params_get_buffer_size = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_buffer_size");
14863  pContext->alsa.snd_pcm_hw_params_get_periods = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_periods");
14864  pContext->alsa.snd_pcm_hw_params_get_access = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_access");
14865  pContext->alsa.snd_pcm_hw_params_test_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_format");
14866  pContext->alsa.snd_pcm_hw_params_test_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_channels");
14867  pContext->alsa.snd_pcm_hw_params_test_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_rate");
14868  pContext->alsa.snd_pcm_hw_params = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params");
14869  pContext->alsa.snd_pcm_sw_params_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_sizeof");
14870  pContext->alsa.snd_pcm_sw_params_current = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_current");
14871  pContext->alsa.snd_pcm_sw_params_get_boundary = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_get_boundary");
14872  pContext->alsa.snd_pcm_sw_params_set_avail_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_avail_min");
14873  pContext->alsa.snd_pcm_sw_params_set_start_threshold = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_start_threshold");
14874  pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_stop_threshold");
14875  pContext->alsa.snd_pcm_sw_params = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params");
14876  pContext->alsa.snd_pcm_format_mask_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_format_mask_sizeof");
14877  pContext->alsa.snd_pcm_format_mask_test = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_format_mask_test");
14878  pContext->alsa.snd_pcm_get_chmap = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_get_chmap");
14879  pContext->alsa.snd_pcm_state = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_state");
14880  pContext->alsa.snd_pcm_prepare = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_prepare");
14881  pContext->alsa.snd_pcm_start = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_start");
14882  pContext->alsa.snd_pcm_drop = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_drop");
14883  pContext->alsa.snd_pcm_drain = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_drain");
14884  pContext->alsa.snd_pcm_reset = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_reset");
14885  pContext->alsa.snd_device_name_hint = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_device_name_hint");
14886  pContext->alsa.snd_device_name_get_hint = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_device_name_get_hint");
14887  pContext->alsa.snd_card_get_index = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_card_get_index");
14888  pContext->alsa.snd_device_name_free_hint = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_device_name_free_hint");
14889  pContext->alsa.snd_pcm_mmap_begin = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_mmap_begin");
14890  pContext->alsa.snd_pcm_mmap_commit = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_mmap_commit");
14891  pContext->alsa.snd_pcm_recover = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_recover");
14892  pContext->alsa.snd_pcm_readi = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_readi");
14893  pContext->alsa.snd_pcm_writei = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_writei");
14894  pContext->alsa.snd_pcm_avail = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_avail");
14895  pContext->alsa.snd_pcm_avail_update = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_avail_update");
14896  pContext->alsa.snd_pcm_wait = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_wait");
14897  pContext->alsa.snd_pcm_nonblock = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_nonblock");
14898  pContext->alsa.snd_pcm_info = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_info");
14899  pContext->alsa.snd_pcm_info_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_info_sizeof");
14900  pContext->alsa.snd_pcm_info_get_name = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_info_get_name");
14901  pContext->alsa.snd_pcm_poll_descriptors = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_poll_descriptors");
14902  pContext->alsa.snd_pcm_poll_descriptors_count = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_poll_descriptors_count");
14903  pContext->alsa.snd_pcm_poll_descriptors_revents = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_poll_descriptors_revents");
14904  pContext->alsa.snd_config_update_free_global = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_config_update_free_global");
14905 #else
14906  /* The system below is just for type safety. */
14907  ma_snd_pcm_open_proc _snd_pcm_open = snd_pcm_open;
14908  ma_snd_pcm_close_proc _snd_pcm_close = snd_pcm_close;
14909  ma_snd_pcm_hw_params_sizeof_proc _snd_pcm_hw_params_sizeof = snd_pcm_hw_params_sizeof;
14910  ma_snd_pcm_hw_params_any_proc _snd_pcm_hw_params_any = snd_pcm_hw_params_any;
14911  ma_snd_pcm_hw_params_set_format_proc _snd_pcm_hw_params_set_format = snd_pcm_hw_params_set_format;
14912  ma_snd_pcm_hw_params_set_format_first_proc _snd_pcm_hw_params_set_format_first = snd_pcm_hw_params_set_format_first;
14913  ma_snd_pcm_hw_params_get_format_mask_proc _snd_pcm_hw_params_get_format_mask = snd_pcm_hw_params_get_format_mask;
14914  ma_snd_pcm_hw_params_set_channels_proc _snd_pcm_hw_params_set_channels = snd_pcm_hw_params_set_channels;
14915  ma_snd_pcm_hw_params_set_channels_near_proc _snd_pcm_hw_params_set_channels_near = snd_pcm_hw_params_set_channels_near;
14916  ma_snd_pcm_hw_params_set_rate_resample_proc _snd_pcm_hw_params_set_rate_resample = snd_pcm_hw_params_set_rate_resample;
14917  ma_snd_pcm_hw_params_set_rate_near _snd_pcm_hw_params_set_rate = snd_pcm_hw_params_set_rate;
14918  ma_snd_pcm_hw_params_set_rate_near_proc _snd_pcm_hw_params_set_rate_near = snd_pcm_hw_params_set_rate_near;
14919  ma_snd_pcm_hw_params_set_rate_minmax_proc _snd_pcm_hw_params_set_rate_minmax = snd_pcm_hw_params_set_rate_minmax;
14920  ma_snd_pcm_hw_params_set_buffer_size_near_proc _snd_pcm_hw_params_set_buffer_size_near = snd_pcm_hw_params_set_buffer_size_near;
14921  ma_snd_pcm_hw_params_set_periods_near_proc _snd_pcm_hw_params_set_periods_near = snd_pcm_hw_params_set_periods_near;
14922  ma_snd_pcm_hw_params_set_access_proc _snd_pcm_hw_params_set_access = snd_pcm_hw_params_set_access;
14923  ma_snd_pcm_hw_params_get_format_proc _snd_pcm_hw_params_get_format = snd_pcm_hw_params_get_format;
14924  ma_snd_pcm_hw_params_get_channels_proc _snd_pcm_hw_params_get_channels = snd_pcm_hw_params_get_channels;
14925  ma_snd_pcm_hw_params_get_channels_min_proc _snd_pcm_hw_params_get_channels_min = snd_pcm_hw_params_get_channels_min;
14926  ma_snd_pcm_hw_params_get_channels_max_proc _snd_pcm_hw_params_get_channels_max = snd_pcm_hw_params_get_channels_max;
14927  ma_snd_pcm_hw_params_get_rate_proc _snd_pcm_hw_params_get_rate = snd_pcm_hw_params_get_rate;
14928  ma_snd_pcm_hw_params_get_rate_min_proc _snd_pcm_hw_params_get_rate_min = snd_pcm_hw_params_get_rate_min;
14929  ma_snd_pcm_hw_params_get_rate_max_proc _snd_pcm_hw_params_get_rate_max = snd_pcm_hw_params_get_rate_max;
14930  ma_snd_pcm_hw_params_get_buffer_size_proc _snd_pcm_hw_params_get_buffer_size = snd_pcm_hw_params_get_buffer_size;
14931  ma_snd_pcm_hw_params_get_periods_proc _snd_pcm_hw_params_get_periods = snd_pcm_hw_params_get_periods;
14932  ma_snd_pcm_hw_params_get_access_proc _snd_pcm_hw_params_get_access = snd_pcm_hw_params_get_access;
14933  ma_snd_pcm_hw_params_test_format_proc _snd_pcm_hw_params_test_format = snd_pcm_hw_params_test_format;
14934  ma_snd_pcm_hw_params_test_channels_proc _snd_pcm_hw_params_test_channels = snd_pcm_hw_params_test_channels;
14935  ma_snd_pcm_hw_params_test_rate_proc _snd_pcm_hw_params_test_rate = snd_pcm_hw_params_test_rate;
14936  ma_snd_pcm_hw_params_proc _snd_pcm_hw_params = snd_pcm_hw_params;
14937  ma_snd_pcm_sw_params_sizeof_proc _snd_pcm_sw_params_sizeof = snd_pcm_sw_params_sizeof;
14938  ma_snd_pcm_sw_params_current_proc _snd_pcm_sw_params_current = snd_pcm_sw_params_current;
14939  ma_snd_pcm_sw_params_get_boundary_proc _snd_pcm_sw_params_get_boundary = snd_pcm_sw_params_get_boundary;
14940  ma_snd_pcm_sw_params_set_avail_min_proc _snd_pcm_sw_params_set_avail_min = snd_pcm_sw_params_set_avail_min;
14941  ma_snd_pcm_sw_params_set_start_threshold_proc _snd_pcm_sw_params_set_start_threshold = snd_pcm_sw_params_set_start_threshold;
14942  ma_snd_pcm_sw_params_set_stop_threshold_proc _snd_pcm_sw_params_set_stop_threshold = snd_pcm_sw_params_set_stop_threshold;
14943  ma_snd_pcm_sw_params_proc _snd_pcm_sw_params = snd_pcm_sw_params;
14944  ma_snd_pcm_format_mask_sizeof_proc _snd_pcm_format_mask_sizeof = snd_pcm_format_mask_sizeof;
14945  ma_snd_pcm_format_mask_test_proc _snd_pcm_format_mask_test = snd_pcm_format_mask_test;
14946  ma_snd_pcm_get_chmap_proc _snd_pcm_get_chmap = snd_pcm_get_chmap;
14947  ma_snd_pcm_state_proc _snd_pcm_state = snd_pcm_state;
14948  ma_snd_pcm_prepare_proc _snd_pcm_prepare = snd_pcm_prepare;
14949  ma_snd_pcm_start_proc _snd_pcm_start = snd_pcm_start;
14950  ma_snd_pcm_drop_proc _snd_pcm_drop = snd_pcm_drop;
14951  ma_snd_pcm_drain_proc _snd_pcm_drain = snd_pcm_drain;
14952  ma_snd_pcm_reset_proc _snd_pcm_reset = snd_pcm_reset;
14953  ma_snd_device_name_hint_proc _snd_device_name_hint = snd_device_name_hint;
14954  ma_snd_device_name_get_hint_proc _snd_device_name_get_hint = snd_device_name_get_hint;
14955  ma_snd_card_get_index_proc _snd_card_get_index = snd_card_get_index;
14956  ma_snd_device_name_free_hint_proc _snd_device_name_free_hint = snd_device_name_free_hint;
14957  ma_snd_pcm_mmap_begin_proc _snd_pcm_mmap_begin = snd_pcm_mmap_begin;
14958  ma_snd_pcm_mmap_commit_proc _snd_pcm_mmap_commit = snd_pcm_mmap_commit;
14959  ma_snd_pcm_recover_proc _snd_pcm_recover = snd_pcm_recover;
14960  ma_snd_pcm_readi_proc _snd_pcm_readi = snd_pcm_readi;
14961  ma_snd_pcm_writei_proc _snd_pcm_writei = snd_pcm_writei;
14962  ma_snd_pcm_avail_proc _snd_pcm_avail = snd_pcm_avail;
14963  ma_snd_pcm_avail_update_proc _snd_pcm_avail_update = snd_pcm_avail_update;
14964  ma_snd_pcm_wait_proc _snd_pcm_wait = snd_pcm_wait;
14965  ma_snd_pcm_nonblock_proc _snd_pcm_nonblock = snd_pcm_nonblock;
14966  ma_snd_pcm_info_proc _snd_pcm_info = snd_pcm_info;
14967  ma_snd_pcm_info_sizeof_proc _snd_pcm_info_sizeof = snd_pcm_info_sizeof;
14968  ma_snd_pcm_info_get_name_proc _snd_pcm_info_get_name = snd_pcm_info_get_name;
14969  ma_snd_pcm_poll_descriptors _snd_pcm_poll_descriptors = snd_pcm_poll_descriptors;
14970  ma_snd_pcm_poll_descriptors_count _snd_pcm_poll_descriptors_count = snd_pcm_poll_descriptors_count;
14971  ma_snd_pcm_poll_descriptors_revents _snd_pcm_poll_descriptors_revents = snd_pcm_poll_descriptors_revents;
14972  ma_snd_config_update_free_global_proc _snd_config_update_free_global = snd_config_update_free_global;
14973 
14974  pContext->alsa.snd_pcm_open = (ma_proc)_snd_pcm_open;
14975  pContext->alsa.snd_pcm_close = (ma_proc)_snd_pcm_close;
14976  pContext->alsa.snd_pcm_hw_params_sizeof = (ma_proc)_snd_pcm_hw_params_sizeof;
14977  pContext->alsa.snd_pcm_hw_params_any = (ma_proc)_snd_pcm_hw_params_any;
14978  pContext->alsa.snd_pcm_hw_params_set_format = (ma_proc)_snd_pcm_hw_params_set_format;
14979  pContext->alsa.snd_pcm_hw_params_set_format_first = (ma_proc)_snd_pcm_hw_params_set_format_first;
14980  pContext->alsa.snd_pcm_hw_params_get_format_mask = (ma_proc)_snd_pcm_hw_params_get_format_mask;
14981  pContext->alsa.snd_pcm_hw_params_set_channels = (ma_proc)_snd_pcm_hw_params_set_channels;
14982  pContext->alsa.snd_pcm_hw_params_set_channels_near = (ma_proc)_snd_pcm_hw_params_set_channels_near;
14983  pContext->alsa.snd_pcm_hw_params_set_channels_minmax = (ma_proc)_snd_pcm_hw_params_set_channels_minmax;
14984  pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)_snd_pcm_hw_params_set_rate_resample;
14985  pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)_snd_pcm_hw_params_set_rate;
14986  pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)_snd_pcm_hw_params_set_rate_near;
14987  pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (ma_proc)_snd_pcm_hw_params_set_buffer_size_near;
14988  pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)_snd_pcm_hw_params_set_periods_near;
14989  pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)_snd_pcm_hw_params_set_access;
14990  pContext->alsa.snd_pcm_hw_params_get_format = (ma_proc)_snd_pcm_hw_params_get_format;
14991  pContext->alsa.snd_pcm_hw_params_get_channels = (ma_proc)_snd_pcm_hw_params_get_channels;
14992  pContext->alsa.snd_pcm_hw_params_get_channels_min = (ma_proc)_snd_pcm_hw_params_get_channels_min;
14993  pContext->alsa.snd_pcm_hw_params_get_channels_max = (ma_proc)_snd_pcm_hw_params_get_channels_max;
14994  pContext->alsa.snd_pcm_hw_params_get_rate = (ma_proc)_snd_pcm_hw_params_get_rate;
14995  pContext->alsa.snd_pcm_hw_params_get_rate_min = (ma_proc)_snd_pcm_hw_params_get_rate_min;
14996  pContext->alsa.snd_pcm_hw_params_get_rate_max = (ma_proc)_snd_pcm_hw_params_get_rate_max;
14997  pContext->alsa.snd_pcm_hw_params_get_buffer_size = (ma_proc)_snd_pcm_hw_params_get_buffer_size;
14998  pContext->alsa.snd_pcm_hw_params_get_periods = (ma_proc)_snd_pcm_hw_params_get_periods;
14999  pContext->alsa.snd_pcm_hw_params_get_access = (ma_proc)_snd_pcm_hw_params_get_access;
15000  pContext->alsa.snd_pcm_hw_params_test_format = (ma_proc)_snd_pcm_hw_params_test_format;
15001  pContext->alsa.snd_pcm_hw_params_test_channels = (ma_proc)_snd_pcm_hw_params_test_channels;
15002  pContext->alsa.snd_pcm_hw_params_test_rate = (ma_proc)_snd_pcm_hw_params_test_rate;
15003  pContext->alsa.snd_pcm_hw_params = (ma_proc)_snd_pcm_hw_params;
15004  pContext->alsa.snd_pcm_sw_params_sizeof = (ma_proc)_snd_pcm_sw_params_sizeof;
15005  pContext->alsa.snd_pcm_sw_params_current = (ma_proc)_snd_pcm_sw_params_current;
15006  pContext->alsa.snd_pcm_sw_params_get_boundary = (ma_proc)_snd_pcm_sw_params_get_boundary;
15007  pContext->alsa.snd_pcm_sw_params_set_avail_min = (ma_proc)_snd_pcm_sw_params_set_avail_min;
15008  pContext->alsa.snd_pcm_sw_params_set_start_threshold = (ma_proc)_snd_pcm_sw_params_set_start_threshold;
15009  pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (ma_proc)_snd_pcm_sw_params_set_stop_threshold;
15010  pContext->alsa.snd_pcm_sw_params = (ma_proc)_snd_pcm_sw_params;
15011  pContext->alsa.snd_pcm_format_mask_sizeof = (ma_proc)_snd_pcm_format_mask_sizeof;
15012  pContext->alsa.snd_pcm_format_mask_test = (ma_proc)_snd_pcm_format_mask_test;
15013  pContext->alsa.snd_pcm_get_chmap = (ma_proc)_snd_pcm_get_chmap;
15014  pContext->alsa.snd_pcm_state = (ma_proc)_snd_pcm_state;
15015  pContext->alsa.snd_pcm_prepare = (ma_proc)_snd_pcm_prepare;
15016  pContext->alsa.snd_pcm_start = (ma_proc)_snd_pcm_start;
15017  pContext->alsa.snd_pcm_drop = (ma_proc)_snd_pcm_drop;
15018  pContext->alsa.snd_pcm_drain = (ma_proc)_snd_pcm_drain;
15019  pContext->alsa.snd_pcm_reset = (ma_proc)_snd_pcm_reset;
15020  pContext->alsa.snd_device_name_hint = (ma_proc)_snd_device_name_hint;
15021  pContext->alsa.snd_device_name_get_hint = (ma_proc)_snd_device_name_get_hint;
15022  pContext->alsa.snd_card_get_index = (ma_proc)_snd_card_get_index;
15023  pContext->alsa.snd_device_name_free_hint = (ma_proc)_snd_device_name_free_hint;
15024  pContext->alsa.snd_pcm_mmap_begin = (ma_proc)_snd_pcm_mmap_begin;
15025  pContext->alsa.snd_pcm_mmap_commit = (ma_proc)_snd_pcm_mmap_commit;
15026  pContext->alsa.snd_pcm_recover = (ma_proc)_snd_pcm_recover;
15027  pContext->alsa.snd_pcm_readi = (ma_proc)_snd_pcm_readi;
15028  pContext->alsa.snd_pcm_writei = (ma_proc)_snd_pcm_writei;
15029  pContext->alsa.snd_pcm_avail = (ma_proc)_snd_pcm_avail;
15030  pContext->alsa.snd_pcm_avail_update = (ma_proc)_snd_pcm_avail_update;
15031  pContext->alsa.snd_pcm_wait = (ma_proc)_snd_pcm_wait;
15032  pContext->alsa.snd_pcm_nonblock = (ma_proc)_snd_pcm_nonblock;
15033  pContext->alsa.snd_pcm_info = (ma_proc)_snd_pcm_info;
15034  pContext->alsa.snd_pcm_info_sizeof = (ma_proc)_snd_pcm_info_sizeof;
15035  pContext->alsa.snd_pcm_info_get_name = (ma_proc)_snd_pcm_info_get_name;
15036  pContext->alsa.snd_pcm_poll_descriptors = (ma_proc)_snd_pcm_poll_descriptors;
15037  pContext->alsa.snd_pcm_poll_descriptors_count = (ma_proc)_snd_pcm_poll_descriptors_count;
15038  pContext->alsa.snd_pcm_poll_descriptors_revents = (ma_proc)_snd_pcm_poll_descriptors_revents;
15039  pContext->alsa.snd_config_update_free_global = (ma_proc)_snd_config_update_free_global;
15040 #endif
15041 
15042  pContext->alsa.useVerboseDeviceEnumeration = pConfig->alsa.useVerboseDeviceEnumeration;
15043 
15044  if (ma_mutex_init(&pContext->alsa.internalDeviceEnumLock) != MA_SUCCESS) {
15045  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[ALSA] WARNING: Failed to initialize mutex for internal device enumeration.", MA_ERROR);
15046  }
15047 
15048  pCallbacks->onContextInit = ma_context_init__alsa;
15049  pCallbacks->onContextUninit = ma_context_uninit__alsa;
15050  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__alsa;
15051  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__alsa;
15052  pCallbacks->onDeviceInit = ma_device_init__alsa;
15053  pCallbacks->onDeviceUninit = ma_device_uninit__alsa;
15054  pCallbacks->onDeviceStart = ma_device_start__alsa;
15055  pCallbacks->onDeviceStop = ma_device_stop__alsa;
15056  pCallbacks->onDeviceRead = ma_device_read__alsa;
15057  pCallbacks->onDeviceWrite = ma_device_write__alsa;
15058  pCallbacks->onDeviceDataLoop = NULL;
15059  pCallbacks->onDeviceDataLoopWakeup = ma_device_data_loop_wakeup__alsa;
15060 
15061  return MA_SUCCESS;
15062 }
15063 #endif /* ALSA */
15064 
15065 
15066 
15067 /******************************************************************************
15068 
15069 PulseAudio Backend
15070 
15071 ******************************************************************************/
15072 #ifdef MA_HAS_PULSEAUDIO
15073 /*
15074 The PulseAudio API, along with Apple's Core Audio, is the worst of the maintream audio APIs. This is a brief description of what's going on
15075 in the PulseAudio backend. I apologize if this gets a bit ranty for your liking - you might want to skip this discussion.
15076 
15077 PulseAudio has something they call the "Simple API", which unfortunately isn't suitable for miniaudio. I've not seen anywhere where it
15078 allows you to enumerate over devices, nor does it seem to support the ability to stop and start streams. Looking at the documentation, it
15079 appears as though the stream is constantly running and you prevent sound from being emitted or captured by simply not calling the read or
15080 write functions. This is not a professional solution as it would be much better to *actually* stop the underlying stream. Perhaps the
15081 simple API has some smarts to do this automatically, but I'm not sure. Another limitation with the simple API is that it seems inefficient
15082 when you want to have multiple streams to a single context. For these reasons, miniaudio is not using the simple API.
15083 
15084 Since we're not using the simple API, we're left with the asynchronous API as our only other option. And boy, is this where it starts to
15085 get fun, and I don't mean that in a good way...
15086 
15087 The problems start with the very name of the API - "asynchronous". Yes, this is an asynchronous oriented API which means your commands
15088 don't immediately take effect. You instead need to issue your commands, and then wait for them to complete. The waiting mechanism is
15089 enabled through the use of a "main loop". In the asychronous API you cannot get away from the main loop, and the main loop is where almost
15090 all of PulseAudio's problems stem from.
15091 
15092 When you first initialize PulseAudio you need an object referred to as "main loop". You can implement this yourself by defining your own
15093 vtable, but it's much easier to just use one of the built-in main loop implementations. There's two generic implementations called
15094 pa_mainloop and pa_threaded_mainloop, and another implementation specific to GLib called pa_glib_mainloop. We're using pa_threaded_mainloop
15095 because it simplifies management of the worker thread. The idea of the main loop object is pretty self explanatory - you're supposed to use
15096 it to implement a worker thread which runs in a loop. The main loop is where operations are actually executed.
15097 
15098 To initialize the main loop, you just use `pa_threaded_mainloop_new()`. This is the first function you'll call. You can then get a pointer
15099 to the vtable with `pa_threaded_mainloop_get_api()` (the main loop vtable is called `pa_mainloop_api`). Again, you can bypass the threaded
15100 main loop object entirely and just implement `pa_mainloop_api` directly, but there's no need for it unless you're doing something extremely
15101 specialized such as if you want to integrate it into your application's existing main loop infrastructure.
15102 
15103 (EDIT 2021-01-26: miniaudio is no longer using `pa_threaded_mainloop` due to this issue: https://github.com/mackron/miniaudio/issues/262.
15104 It is now using `pa_mainloop` which turns out to be a simpler solution anyway. The rest of this rant still applies, however.)
15105 
15106 Once you have your main loop vtable (the `pa_mainloop_api` object) you can create the PulseAudio context. This is very similar to
15107 miniaudio's context and they map to each other quite well. You have one context to many streams, which is basically the same as miniaudio's
15108 one `ma_context` to many `ma_device`s. Here's where it starts to get annoying, however. When you first create the PulseAudio context, which
15109 is done with `pa_context_new()`, it's not actually connected to anything. When you connect, you call `pa_context_connect()`. However, if
15110 you remember, PulseAudio is an asynchronous API. That means you cannot just assume the context is connected after `pa_context_context()`
15111 has returned. You instead need to wait for it to connect. To do this, you need to either wait for a callback to get fired, which you can
15112 set with `pa_context_set_state_callback()`, or you can continuously poll the context's state. Either way, you need to run this in a loop.
15113 All objects from here out are created from the context, and, I believe, you can't be creating these objects until the context is connected.
15114 This waiting loop is therefore unavoidable. In order for the waiting to ever complete, however, the main loop needs to be running. Before
15115 attempting to connect the context, the main loop needs to be started with `pa_threaded_mainloop_start()`.
15116 
15117 The reason for this asynchronous design is to support cases where you're connecting to a remote server, say through a local network or an
15118 internet connection. However, the *VAST* majority of cases don't involve this at all - they just connect to a local "server" running on the
15119 host machine. The fact that this would be the default rather than making `pa_context_connect()` synchronous tends to boggle the mind.
15120 
15121 Once the context has been created and connected you can start creating a stream. A PulseAudio stream is analogous to miniaudio's device.
15122 The initialization of a stream is fairly standard - you configure some attributes (analogous to miniaudio's device config) and then call
15123 `pa_stream_new()` to actually create it. Here is where we start to get into "operations". When configuring the stream, you can get
15124 information about the source (such as sample format, sample rate, etc.), however it's not synchronous. Instead, a `pa_operation` object
15125 is returned from `pa_context_get_source_info_by_name()` (capture) or `pa_context_get_sink_info_by_name()` (playback). Then, you need to
15126 run a loop (again!) to wait for the operation to complete which you can determine via a callback or polling, just like we did with the
15127 context. Then, as an added bonus, you need to decrement the reference counter of the `pa_operation` object to ensure memory is cleaned up.
15128 All of that just to retrieve basic information about a device!
15129 
15130 Once the basic information about the device has been retrieved, miniaudio can now create the stream with `ma_stream_new()`. Like the
15131 context, this needs to be connected. But we need to be careful here, because we're now about to introduce one of the most horrific design
15132 choices in PulseAudio.
15133 
15134 PulseAudio allows you to specify a callback that is fired when data can be written to or read from a stream. The language is important here
15135 because PulseAudio takes it literally, specifically the "can be". You would think these callbacks would be appropriate as the place for
15136 writing and reading data to and from the stream, and that would be right, except when it's not. When you initialize the stream, you can
15137 set a flag that tells PulseAudio to not start the stream automatically. This is required because miniaudio does not auto-start devices
15138 straight after initialization - you need to call `ma_device_start()` manually. The problem is that even when this flag is specified,
15139 PulseAudio will immediately fire it's write or read callback. This is *technically* correct (based on the wording in the documentation)
15140 because indeed, data *can* be written at this point. The problem is that it's not *practical*. It makes sense that the write/read callback
15141 would be where a program will want to write or read data to or from the stream, but when it's called before the application has even
15142 requested that the stream be started, it's just not practical because the program probably isn't ready for any kind of data delivery at
15143 that point (it may still need to load files or whatnot). Instead, this callback should only be fired when the application requests the
15144 stream be started which is how it works with literally *every* other callback-based audio API. Since miniaudio forbids firing of the data
15145 callback until the device has been started (as it should be with *all* callback based APIs), logic needs to be added to ensure miniaudio
15146 doesn't just blindly fire the application-defined data callback from within the PulseAudio callback before the stream has actually been
15147 started. The device state is used for this - if the state is anything other than `MA_STATE_STARTING` or `MA_STATE_STARTED`, the main data
15148 callback is not fired.
15149 
15150 This, unfortunately, is not the end of the problems with the PulseAudio write callback. Any normal callback based audio API will
15151 continuously fire the callback at regular intervals based on the size of the internal buffer. This will only ever be fired when the device
15152 is running, and will be fired regardless of whether or not the user actually wrote anything to the device/stream. This not the case in
15153 PulseAudio. In PulseAudio, the data callback will *only* be called if you wrote something to it previously. That means, if you don't call
15154 `pa_stream_write()`, the callback will not get fired. On the surface you wouldn't think this would matter because you should be always
15155 writing data, and if you don't have anything to write, just write silence. That's fine until you want to drain the stream. You see, if
15156 you're continuously writing data to the stream, the stream will never get drained! That means in order to drain the stream, you need to
15157 *not* write data to it! But remember, when you don't write data to the stream, the callback won't get fired again! Why is draining
15158 important? Because that's how we've defined stopping to work in miniaudio. In miniaudio, stopping the device requires it to be drained
15159 before returning from ma_device_stop(). So we've stopped the device, which requires us to drain, but draining requires us to *not* write
15160 data to the stream (or else it won't ever complete draining), but not writing to the stream means the callback won't get fired again!
15161 
15162 This becomes a problem when stopping and then restarting the device. When the device is stopped, it's drained, which requires us to *not*
15163 write anything to the stream. But then, since we didn't write anything to it, the write callback will *never* get called again if we just
15164 resume the stream naively. This means that starting the stream requires us to write data to the stream from outside the callback. This
15165 disconnect is something PulseAudio has got seriously wrong - there should only ever be a single source of data delivery, that being the
15166 callback. (I have tried using `pa_stream_flush()` to trigger the write callback to fire, but this just doesn't work for some reason.)
15167 
15168 Once you've created the stream, you need to connect it which involves the whole waiting procedure. This is the same process as the context,
15169 only this time you'll poll for the state with `pa_stream_get_status()`. The starting and stopping of a streaming is referred to as
15170 "corking" in PulseAudio. The analogy is corking a barrel. To start the stream, you uncork it, to stop it you cork it. Personally I think
15171 it's silly - why would you not just call it "starting" and "stopping" like any other normal audio API? Anyway, the act of corking is, you
15172 guessed it, asynchronous. This means you'll need our waiting loop as usual. Again, why this asynchronous design is the default is
15173 absolutely beyond me. Would it really be that hard to just make it run synchronously?
15174 
15175 Teardown is pretty simple (what?!). It's just a matter of calling the relevant `_unref()` function on each object in reverse order that
15176 they were initialized in.
15177 
15178 That's about it from the PulseAudio side. A bit ranty, I know, but they really need to fix that main loop and callback system. They're
15179 embarrassingly unpractical. The main loop thing is an easy fix - have synchronous versions of all APIs. If an application wants these to
15180 run asynchronously, they can execute them in a separate thread themselves. The desire to run these asynchronously is such a niche
15181 requirement - it makes no sense to make it the default. The stream write callback needs to be change, or an alternative provided, that is
15182 constantly fired, regardless of whether or not `pa_stream_write()` has been called, and it needs to take a pointer to a buffer as a
15183 parameter which the program just writes to directly rather than having to call `pa_stream_writable_size()` and `pa_stream_write()`. These
15184 changes alone will change PulseAudio from one of the worst audio APIs to one of the best.
15185 */
15186 
15187 
15188 /*
15189 It is assumed pulseaudio.h is available when linking at compile time. When linking at compile time, we use the declarations in the header
15190 to check for type safety. We cannot do this when linking at run time because the header might not be available.
15191 */
15192 #ifdef MA_NO_RUNTIME_LINKING
15193 
15194 /* pulseaudio.h marks some functions with "inline" which isn't always supported. Need to emulate it. */
15195 #if !defined(__cplusplus)
15196  #if defined(__STRICT_ANSI__)
15197  #if !defined(inline)
15198  #define inline __inline__ __attribute__((always_inline))
15199  #define MA_INLINE_DEFINED
15200  #endif
15201  #endif
15202 #endif
15203 #include <pulse/pulseaudio.h>
15204 #if defined(MA_INLINE_DEFINED)
15205  #undef inline
15206  #undef MA_INLINE_DEFINED
15207 #endif
15208 
15209 #define MA_PA_OK PA_OK
15210 #define MA_PA_ERR_ACCESS PA_ERR_ACCESS
15211 #define MA_PA_ERR_INVALID PA_ERR_INVALID
15212 #define MA_PA_ERR_NOENTITY PA_ERR_NOENTITY
15213 #define MA_PA_ERR_NOTSUPPORTED PA_ERR_NOTSUPPORTED
15214 
15215 #define MA_PA_CHANNELS_MAX PA_CHANNELS_MAX
15216 #define MA_PA_RATE_MAX PA_RATE_MAX
15217 
15218 typedef pa_context_flags_t ma_pa_context_flags_t;
15219 #define MA_PA_CONTEXT_NOFLAGS PA_CONTEXT_NOFLAGS
15220 #define MA_PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN
15221 #define MA_PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL
15222 
15223 typedef pa_stream_flags_t ma_pa_stream_flags_t;
15224 #define MA_PA_STREAM_NOFLAGS PA_STREAM_NOFLAGS
15225 #define MA_PA_STREAM_START_CORKED PA_STREAM_START_CORKED
15226 #define MA_PA_STREAM_INTERPOLATE_TIMING PA_STREAM_INTERPOLATE_TIMING
15227 #define MA_PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONIC
15228 #define MA_PA_STREAM_AUTO_TIMING_UPDATE PA_STREAM_AUTO_TIMING_UPDATE
15229 #define MA_PA_STREAM_NO_REMAP_CHANNELS PA_STREAM_NO_REMAP_CHANNELS
15230 #define MA_PA_STREAM_NO_REMIX_CHANNELS PA_STREAM_NO_REMIX_CHANNELS
15231 #define MA_PA_STREAM_FIX_FORMAT PA_STREAM_FIX_FORMAT
15232 #define MA_PA_STREAM_FIX_RATE PA_STREAM_FIX_RATE
15233 #define MA_PA_STREAM_FIX_CHANNELS PA_STREAM_FIX_CHANNELS
15234 #define MA_PA_STREAM_DONT_MOVE PA_STREAM_DONT_MOVE
15235 #define MA_PA_STREAM_VARIABLE_RATE PA_STREAM_VARIABLE_RATE
15236 #define MA_PA_STREAM_PEAK_DETECT PA_STREAM_PEAK_DETECT
15237 #define MA_PA_STREAM_START_MUTED PA_STREAM_START_MUTED
15238 #define MA_PA_STREAM_ADJUST_LATENCY PA_STREAM_ADJUST_LATENCY
15239 #define MA_PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS
15240 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
15241 #define MA_PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
15242 #define MA_PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
15243 #define MA_PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
15244 #define MA_PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH
15245 
15246 typedef pa_sink_flags_t ma_pa_sink_flags_t;
15247 #define MA_PA_SINK_NOFLAGS PA_SINK_NOFLAGS
15248 #define MA_PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL
15249 #define MA_PA_SINK_LATENCY PA_SINK_LATENCY
15250 #define MA_PA_SINK_HARDWARE PA_SINK_HARDWARE
15251 #define MA_PA_SINK_NETWORK PA_SINK_NETWORK
15252 #define MA_PA_SINK_HW_MUTE_CTRL PA_SINK_HW_MUTE_CTRL
15253 #define MA_PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME
15254 #define MA_PA_SINK_FLAT_VOLUME PA_SINK_FLAT_VOLUME
15255 #define MA_PA_SINK_DYNAMIC_LATENCY PA_SINK_DYNAMIC_LATENCY
15256 #define MA_PA_SINK_SET_FORMATS PA_SINK_SET_FORMATS
15257 
15258 typedef pa_source_flags_t ma_pa_source_flags_t;
15259 #define MA_PA_SOURCE_NOFLAGS PA_SOURCE_NOFLAGS
15260 #define MA_PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL
15261 #define MA_PA_SOURCE_LATENCY PA_SOURCE_LATENCY
15262 #define MA_PA_SOURCE_HARDWARE PA_SOURCE_HARDWARE
15263 #define MA_PA_SOURCE_NETWORK PA_SOURCE_NETWORK
15264 #define MA_PA_SOURCE_HW_MUTE_CTRL PA_SOURCE_HW_MUTE_CTRL
15265 #define MA_PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME
15266 #define MA_PA_SOURCE_DYNAMIC_LATENCY PA_SOURCE_DYNAMIC_LATENCY
15267 #define MA_PA_SOURCE_FLAT_VOLUME PA_SOURCE_FLAT_VOLUME
15268 
15269 typedef pa_context_state_t ma_pa_context_state_t;
15270 #define MA_PA_CONTEXT_UNCONNECTED PA_CONTEXT_UNCONNECTED
15271 #define MA_PA_CONTEXT_CONNECTING PA_CONTEXT_CONNECTING
15272 #define MA_PA_CONTEXT_AUTHORIZING PA_CONTEXT_AUTHORIZING
15273 #define MA_PA_CONTEXT_SETTING_NAME PA_CONTEXT_SETTING_NAME
15274 #define MA_PA_CONTEXT_READY PA_CONTEXT_READY
15275 #define MA_PA_CONTEXT_FAILED PA_CONTEXT_FAILED
15276 #define MA_PA_CONTEXT_TERMINATED PA_CONTEXT_TERMINATED
15277 
15278 typedef pa_stream_state_t ma_pa_stream_state_t;
15279 #define MA_PA_STREAM_UNCONNECTED PA_STREAM_UNCONNECTED
15280 #define MA_PA_STREAM_CREATING PA_STREAM_CREATING
15281 #define MA_PA_STREAM_READY PA_STREAM_READY
15282 #define MA_PA_STREAM_FAILED PA_STREAM_FAILED
15283 #define MA_PA_STREAM_TERMINATED PA_STREAM_TERMINATED
15284 
15285 typedef pa_operation_state_t ma_pa_operation_state_t;
15286 #define MA_PA_OPERATION_RUNNING PA_OPERATION_RUNNING
15287 #define MA_PA_OPERATION_DONE PA_OPERATION_DONE
15288 #define MA_PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
15289 
15290 typedef pa_sink_state_t ma_pa_sink_state_t;
15291 #define MA_PA_SINK_INVALID_STATE PA_SINK_INVALID_STATE
15292 #define MA_PA_SINK_RUNNING PA_SINK_RUNNING
15293 #define MA_PA_SINK_IDLE PA_SINK_IDLE
15294 #define MA_PA_SINK_SUSPENDED PA_SINK_SUSPENDED
15295 
15296 typedef pa_source_state_t ma_pa_source_state_t;
15297 #define MA_PA_SOURCE_INVALID_STATE PA_SOURCE_INVALID_STATE
15298 #define MA_PA_SOURCE_RUNNING PA_SOURCE_RUNNING
15299 #define MA_PA_SOURCE_IDLE PA_SOURCE_IDLE
15300 #define MA_PA_SOURCE_SUSPENDED PA_SOURCE_SUSPENDED
15301 
15302 typedef pa_seek_mode_t ma_pa_seek_mode_t;
15303 #define MA_PA_SEEK_RELATIVE PA_SEEK_RELATIVE
15304 #define MA_PA_SEEK_ABSOLUTE PA_SEEK_ABSOLUTE
15305 #define MA_PA_SEEK_RELATIVE_ON_READ PA_SEEK_RELATIVE_ON_READ
15306 #define MA_PA_SEEK_RELATIVE_END PA_SEEK_RELATIVE_END
15307 
15308 typedef pa_channel_position_t ma_pa_channel_position_t;
15309 #define MA_PA_CHANNEL_POSITION_INVALID PA_CHANNEL_POSITION_INVALID
15310 #define MA_PA_CHANNEL_POSITION_MONO PA_CHANNEL_POSITION_MONO
15311 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT PA_CHANNEL_POSITION_FRONT_LEFT
15312 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT PA_CHANNEL_POSITION_FRONT_RIGHT
15313 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER PA_CHANNEL_POSITION_FRONT_CENTER
15314 #define MA_PA_CHANNEL_POSITION_REAR_CENTER PA_CHANNEL_POSITION_REAR_CENTER
15315 #define MA_PA_CHANNEL_POSITION_REAR_LEFT PA_CHANNEL_POSITION_REAR_LEFT
15316 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT PA_CHANNEL_POSITION_REAR_RIGHT
15317 #define MA_PA_CHANNEL_POSITION_LFE PA_CHANNEL_POSITION_LFE
15318 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
15319 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
15320 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT PA_CHANNEL_POSITION_SIDE_LEFT
15321 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT PA_CHANNEL_POSITION_SIDE_RIGHT
15322 #define MA_PA_CHANNEL_POSITION_AUX0 PA_CHANNEL_POSITION_AUX0
15323 #define MA_PA_CHANNEL_POSITION_AUX1 PA_CHANNEL_POSITION_AUX1
15324 #define MA_PA_CHANNEL_POSITION_AUX2 PA_CHANNEL_POSITION_AUX2
15325 #define MA_PA_CHANNEL_POSITION_AUX3 PA_CHANNEL_POSITION_AUX3
15326 #define MA_PA_CHANNEL_POSITION_AUX4 PA_CHANNEL_POSITION_AUX4
15327 #define MA_PA_CHANNEL_POSITION_AUX5 PA_CHANNEL_POSITION_AUX5
15328 #define MA_PA_CHANNEL_POSITION_AUX6 PA_CHANNEL_POSITION_AUX6
15329 #define MA_PA_CHANNEL_POSITION_AUX7 PA_CHANNEL_POSITION_AUX7
15330 #define MA_PA_CHANNEL_POSITION_AUX8 PA_CHANNEL_POSITION_AUX8
15331 #define MA_PA_CHANNEL_POSITION_AUX9 PA_CHANNEL_POSITION_AUX9
15332 #define MA_PA_CHANNEL_POSITION_AUX10 PA_CHANNEL_POSITION_AUX10
15333 #define MA_PA_CHANNEL_POSITION_AUX11 PA_CHANNEL_POSITION_AUX11
15334 #define MA_PA_CHANNEL_POSITION_AUX12 PA_CHANNEL_POSITION_AUX12
15335 #define MA_PA_CHANNEL_POSITION_AUX13 PA_CHANNEL_POSITION_AUX13
15336 #define MA_PA_CHANNEL_POSITION_AUX14 PA_CHANNEL_POSITION_AUX14
15337 #define MA_PA_CHANNEL_POSITION_AUX15 PA_CHANNEL_POSITION_AUX15
15338 #define MA_PA_CHANNEL_POSITION_AUX16 PA_CHANNEL_POSITION_AUX16
15339 #define MA_PA_CHANNEL_POSITION_AUX17 PA_CHANNEL_POSITION_AUX17
15340 #define MA_PA_CHANNEL_POSITION_AUX18 PA_CHANNEL_POSITION_AUX18
15341 #define MA_PA_CHANNEL_POSITION_AUX19 PA_CHANNEL_POSITION_AUX19
15342 #define MA_PA_CHANNEL_POSITION_AUX20 PA_CHANNEL_POSITION_AUX20
15343 #define MA_PA_CHANNEL_POSITION_AUX21 PA_CHANNEL_POSITION_AUX21
15344 #define MA_PA_CHANNEL_POSITION_AUX22 PA_CHANNEL_POSITION_AUX22
15345 #define MA_PA_CHANNEL_POSITION_AUX23 PA_CHANNEL_POSITION_AUX23
15346 #define MA_PA_CHANNEL_POSITION_AUX24 PA_CHANNEL_POSITION_AUX24
15347 #define MA_PA_CHANNEL_POSITION_AUX25 PA_CHANNEL_POSITION_AUX25
15348 #define MA_PA_CHANNEL_POSITION_AUX26 PA_CHANNEL_POSITION_AUX26
15349 #define MA_PA_CHANNEL_POSITION_AUX27 PA_CHANNEL_POSITION_AUX27
15350 #define MA_PA_CHANNEL_POSITION_AUX28 PA_CHANNEL_POSITION_AUX28
15351 #define MA_PA_CHANNEL_POSITION_AUX29 PA_CHANNEL_POSITION_AUX29
15352 #define MA_PA_CHANNEL_POSITION_AUX30 PA_CHANNEL_POSITION_AUX30
15353 #define MA_PA_CHANNEL_POSITION_AUX31 PA_CHANNEL_POSITION_AUX31
15354 #define MA_PA_CHANNEL_POSITION_TOP_CENTER PA_CHANNEL_POSITION_TOP_CENTER
15355 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT PA_CHANNEL_POSITION_TOP_FRONT_LEFT
15356 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
15357 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER PA_CHANNEL_POSITION_TOP_FRONT_CENTER
15358 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT PA_CHANNEL_POSITION_TOP_REAR_LEFT
15359 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT PA_CHANNEL_POSITION_TOP_REAR_RIGHT
15360 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER PA_CHANNEL_POSITION_TOP_REAR_CENTER
15361 #define MA_PA_CHANNEL_POSITION_LEFT PA_CHANNEL_POSITION_LEFT
15362 #define MA_PA_CHANNEL_POSITION_RIGHT PA_CHANNEL_POSITION_RIGHT
15363 #define MA_PA_CHANNEL_POSITION_CENTER PA_CHANNEL_POSITION_CENTER
15364 #define MA_PA_CHANNEL_POSITION_SUBWOOFER PA_CHANNEL_POSITION_SUBWOOFER
15365 
15366 typedef pa_channel_map_def_t ma_pa_channel_map_def_t;
15367 #define MA_PA_CHANNEL_MAP_AIFF PA_CHANNEL_MAP_AIFF
15368 #define MA_PA_CHANNEL_MAP_ALSA PA_CHANNEL_MAP_ALSA
15369 #define MA_PA_CHANNEL_MAP_AUX PA_CHANNEL_MAP_AUX
15370 #define MA_PA_CHANNEL_MAP_WAVEEX PA_CHANNEL_MAP_WAVEEX
15371 #define MA_PA_CHANNEL_MAP_OSS PA_CHANNEL_MAP_OSS
15372 #define MA_PA_CHANNEL_MAP_DEFAULT PA_CHANNEL_MAP_DEFAULT
15373 
15374 typedef pa_sample_format_t ma_pa_sample_format_t;
15375 #define MA_PA_SAMPLE_INVALID PA_SAMPLE_INVALID
15376 #define MA_PA_SAMPLE_U8 PA_SAMPLE_U8
15377 #define MA_PA_SAMPLE_ALAW PA_SAMPLE_ALAW
15378 #define MA_PA_SAMPLE_ULAW PA_SAMPLE_ULAW
15379 #define MA_PA_SAMPLE_S16LE PA_SAMPLE_S16LE
15380 #define MA_PA_SAMPLE_S16BE PA_SAMPLE_S16BE
15381 #define MA_PA_SAMPLE_FLOAT32LE PA_SAMPLE_FLOAT32LE
15382 #define MA_PA_SAMPLE_FLOAT32BE PA_SAMPLE_FLOAT32BE
15383 #define MA_PA_SAMPLE_S32LE PA_SAMPLE_S32LE
15384 #define MA_PA_SAMPLE_S32BE PA_SAMPLE_S32BE
15385 #define MA_PA_SAMPLE_S24LE PA_SAMPLE_S24LE
15386 #define MA_PA_SAMPLE_S24BE PA_SAMPLE_S24BE
15387 #define MA_PA_SAMPLE_S24_32LE PA_SAMPLE_S24_32LE
15388 #define MA_PA_SAMPLE_S24_32BE PA_SAMPLE_S24_32BE
15389 
15390 typedef pa_mainloop ma_pa_mainloop;
15391 typedef pa_threaded_mainloop ma_pa_threaded_mainloop;
15392 typedef pa_mainloop_api ma_pa_mainloop_api;
15393 typedef pa_context ma_pa_context;
15394 typedef pa_operation ma_pa_operation;
15395 typedef pa_stream ma_pa_stream;
15396 typedef pa_spawn_api ma_pa_spawn_api;
15397 typedef pa_buffer_attr ma_pa_buffer_attr;
15398 typedef pa_channel_map ma_pa_channel_map;
15399 typedef pa_cvolume ma_pa_cvolume;
15400 typedef pa_sample_spec ma_pa_sample_spec;
15401 typedef pa_sink_info ma_pa_sink_info;
15402 typedef pa_source_info ma_pa_source_info;
15403 
15404 typedef pa_context_notify_cb_t ma_pa_context_notify_cb_t;
15405 typedef pa_sink_info_cb_t ma_pa_sink_info_cb_t;
15406 typedef pa_source_info_cb_t ma_pa_source_info_cb_t;
15407 typedef pa_stream_success_cb_t ma_pa_stream_success_cb_t;
15408 typedef pa_stream_request_cb_t ma_pa_stream_request_cb_t;
15409 typedef pa_stream_notify_cb_t ma_pa_stream_notify_cb_t;
15410 typedef pa_free_cb_t ma_pa_free_cb_t;
15411 #else
15412 #define MA_PA_OK 0
15413 #define MA_PA_ERR_ACCESS 1
15414 #define MA_PA_ERR_INVALID 2
15415 #define MA_PA_ERR_NOENTITY 5
15416 #define MA_PA_ERR_NOTSUPPORTED 19
15417 
15418 #define MA_PA_CHANNELS_MAX 32
15419 #define MA_PA_RATE_MAX 384000
15420 
15421 typedef int ma_pa_context_flags_t;
15422 #define MA_PA_CONTEXT_NOFLAGS 0x00000000
15423 #define MA_PA_CONTEXT_NOAUTOSPAWN 0x00000001
15424 #define MA_PA_CONTEXT_NOFAIL 0x00000002
15425 
15426 typedef int ma_pa_stream_flags_t;
15427 #define MA_PA_STREAM_NOFLAGS 0x00000000
15428 #define MA_PA_STREAM_START_CORKED 0x00000001
15429 #define MA_PA_STREAM_INTERPOLATE_TIMING 0x00000002
15430 #define MA_PA_STREAM_NOT_MONOTONIC 0x00000004
15431 #define MA_PA_STREAM_AUTO_TIMING_UPDATE 0x00000008
15432 #define MA_PA_STREAM_NO_REMAP_CHANNELS 0x00000010
15433 #define MA_PA_STREAM_NO_REMIX_CHANNELS 0x00000020
15434 #define MA_PA_STREAM_FIX_FORMAT 0x00000040
15435 #define MA_PA_STREAM_FIX_RATE 0x00000080
15436 #define MA_PA_STREAM_FIX_CHANNELS 0x00000100
15437 #define MA_PA_STREAM_DONT_MOVE 0x00000200
15438 #define MA_PA_STREAM_VARIABLE_RATE 0x00000400
15439 #define MA_PA_STREAM_PEAK_DETECT 0x00000800
15440 #define MA_PA_STREAM_START_MUTED 0x00001000
15441 #define MA_PA_STREAM_ADJUST_LATENCY 0x00002000
15442 #define MA_PA_STREAM_EARLY_REQUESTS 0x00004000
15443 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND 0x00008000
15444 #define MA_PA_STREAM_START_UNMUTED 0x00010000
15445 #define MA_PA_STREAM_FAIL_ON_SUSPEND 0x00020000
15446 #define MA_PA_STREAM_RELATIVE_VOLUME 0x00040000
15447 #define MA_PA_STREAM_PASSTHROUGH 0x00080000
15448 
15449 typedef int ma_pa_sink_flags_t;
15450 #define MA_PA_SINK_NOFLAGS 0x00000000
15451 #define MA_PA_SINK_HW_VOLUME_CTRL 0x00000001
15452 #define MA_PA_SINK_LATENCY 0x00000002
15453 #define MA_PA_SINK_HARDWARE 0x00000004
15454 #define MA_PA_SINK_NETWORK 0x00000008
15455 #define MA_PA_SINK_HW_MUTE_CTRL 0x00000010
15456 #define MA_PA_SINK_DECIBEL_VOLUME 0x00000020
15457 #define MA_PA_SINK_FLAT_VOLUME 0x00000040
15458 #define MA_PA_SINK_DYNAMIC_LATENCY 0x00000080
15459 #define MA_PA_SINK_SET_FORMATS 0x00000100
15460 
15461 typedef int ma_pa_source_flags_t;
15462 #define MA_PA_SOURCE_NOFLAGS 0x00000000
15463 #define MA_PA_SOURCE_HW_VOLUME_CTRL 0x00000001
15464 #define MA_PA_SOURCE_LATENCY 0x00000002
15465 #define MA_PA_SOURCE_HARDWARE 0x00000004
15466 #define MA_PA_SOURCE_NETWORK 0x00000008
15467 #define MA_PA_SOURCE_HW_MUTE_CTRL 0x00000010
15468 #define MA_PA_SOURCE_DECIBEL_VOLUME 0x00000020
15469 #define MA_PA_SOURCE_DYNAMIC_LATENCY 0x00000040
15470 #define MA_PA_SOURCE_FLAT_VOLUME 0x00000080
15471 
15472 typedef int ma_pa_context_state_t;
15473 #define MA_PA_CONTEXT_UNCONNECTED 0
15474 #define MA_PA_CONTEXT_CONNECTING 1
15475 #define MA_PA_CONTEXT_AUTHORIZING 2
15476 #define MA_PA_CONTEXT_SETTING_NAME 3
15477 #define MA_PA_CONTEXT_READY 4
15478 #define MA_PA_CONTEXT_FAILED 5
15479 #define MA_PA_CONTEXT_TERMINATED 6
15480 
15481 typedef int ma_pa_stream_state_t;
15482 #define MA_PA_STREAM_UNCONNECTED 0
15483 #define MA_PA_STREAM_CREATING 1
15484 #define MA_PA_STREAM_READY 2
15485 #define MA_PA_STREAM_FAILED 3
15486 #define MA_PA_STREAM_TERMINATED 4
15487 
15488 typedef int ma_pa_operation_state_t;
15489 #define MA_PA_OPERATION_RUNNING 0
15490 #define MA_PA_OPERATION_DONE 1
15491 #define MA_PA_OPERATION_CANCELLED 2
15492 
15493 typedef int ma_pa_sink_state_t;
15494 #define MA_PA_SINK_INVALID_STATE -1
15495 #define MA_PA_SINK_RUNNING 0
15496 #define MA_PA_SINK_IDLE 1
15497 #define MA_PA_SINK_SUSPENDED 2
15498 
15499 typedef int ma_pa_source_state_t;
15500 #define MA_PA_SOURCE_INVALID_STATE -1
15501 #define MA_PA_SOURCE_RUNNING 0
15502 #define MA_PA_SOURCE_IDLE 1
15503 #define MA_PA_SOURCE_SUSPENDED 2
15504 
15505 typedef int ma_pa_seek_mode_t;
15506 #define MA_PA_SEEK_RELATIVE 0
15507 #define MA_PA_SEEK_ABSOLUTE 1
15508 #define MA_PA_SEEK_RELATIVE_ON_READ 2
15509 #define MA_PA_SEEK_RELATIVE_END 3
15510 
15511 typedef int ma_pa_channel_position_t;
15512 #define MA_PA_CHANNEL_POSITION_INVALID -1
15513 #define MA_PA_CHANNEL_POSITION_MONO 0
15514 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT 1
15515 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT 2
15516 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER 3
15517 #define MA_PA_CHANNEL_POSITION_REAR_CENTER 4
15518 #define MA_PA_CHANNEL_POSITION_REAR_LEFT 5
15519 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT 6
15520 #define MA_PA_CHANNEL_POSITION_LFE 7
15521 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER 8
15522 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER 9
15523 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT 10
15524 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT 11
15525 #define MA_PA_CHANNEL_POSITION_AUX0 12
15526 #define MA_PA_CHANNEL_POSITION_AUX1 13
15527 #define MA_PA_CHANNEL_POSITION_AUX2 14
15528 #define MA_PA_CHANNEL_POSITION_AUX3 15
15529 #define MA_PA_CHANNEL_POSITION_AUX4 16
15530 #define MA_PA_CHANNEL_POSITION_AUX5 17
15531 #define MA_PA_CHANNEL_POSITION_AUX6 18
15532 #define MA_PA_CHANNEL_POSITION_AUX7 19
15533 #define MA_PA_CHANNEL_POSITION_AUX8 20
15534 #define MA_PA_CHANNEL_POSITION_AUX9 21
15535 #define MA_PA_CHANNEL_POSITION_AUX10 22
15536 #define MA_PA_CHANNEL_POSITION_AUX11 23
15537 #define MA_PA_CHANNEL_POSITION_AUX12 24
15538 #define MA_PA_CHANNEL_POSITION_AUX13 25
15539 #define MA_PA_CHANNEL_POSITION_AUX14 26
15540 #define MA_PA_CHANNEL_POSITION_AUX15 27
15541 #define MA_PA_CHANNEL_POSITION_AUX16 28
15542 #define MA_PA_CHANNEL_POSITION_AUX17 29
15543 #define MA_PA_CHANNEL_POSITION_AUX18 30
15544 #define MA_PA_CHANNEL_POSITION_AUX19 31
15545 #define MA_PA_CHANNEL_POSITION_AUX20 32
15546 #define MA_PA_CHANNEL_POSITION_AUX21 33
15547 #define MA_PA_CHANNEL_POSITION_AUX22 34
15548 #define MA_PA_CHANNEL_POSITION_AUX23 35
15549 #define MA_PA_CHANNEL_POSITION_AUX24 36
15550 #define MA_PA_CHANNEL_POSITION_AUX25 37
15551 #define MA_PA_CHANNEL_POSITION_AUX26 38
15552 #define MA_PA_CHANNEL_POSITION_AUX27 39
15553 #define MA_PA_CHANNEL_POSITION_AUX28 40
15554 #define MA_PA_CHANNEL_POSITION_AUX29 41
15555 #define MA_PA_CHANNEL_POSITION_AUX30 42
15556 #define MA_PA_CHANNEL_POSITION_AUX31 43
15557 #define MA_PA_CHANNEL_POSITION_TOP_CENTER 44
15558 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT 45
15559 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT 46
15560 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER 47
15561 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT 48
15562 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT 49
15563 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER 50
15564 #define MA_PA_CHANNEL_POSITION_LEFT MA_PA_CHANNEL_POSITION_FRONT_LEFT
15565 #define MA_PA_CHANNEL_POSITION_RIGHT MA_PA_CHANNEL_POSITION_FRONT_RIGHT
15566 #define MA_PA_CHANNEL_POSITION_CENTER MA_PA_CHANNEL_POSITION_FRONT_CENTER
15567 #define MA_PA_CHANNEL_POSITION_SUBWOOFER MA_PA_CHANNEL_POSITION_LFE
15568 
15569 typedef int ma_pa_channel_map_def_t;
15570 #define MA_PA_CHANNEL_MAP_AIFF 0
15571 #define MA_PA_CHANNEL_MAP_ALSA 1
15572 #define MA_PA_CHANNEL_MAP_AUX 2
15573 #define MA_PA_CHANNEL_MAP_WAVEEX 3
15574 #define MA_PA_CHANNEL_MAP_OSS 4
15575 #define MA_PA_CHANNEL_MAP_DEFAULT MA_PA_CHANNEL_MAP_AIFF
15576 
15577 typedef int ma_pa_sample_format_t;
15578 #define MA_PA_SAMPLE_INVALID -1
15579 #define MA_PA_SAMPLE_U8 0
15580 #define MA_PA_SAMPLE_ALAW 1
15581 #define MA_PA_SAMPLE_ULAW 2
15582 #define MA_PA_SAMPLE_S16LE 3
15583 #define MA_PA_SAMPLE_S16BE 4
15584 #define MA_PA_SAMPLE_FLOAT32LE 5
15585 #define MA_PA_SAMPLE_FLOAT32BE 6
15586 #define MA_PA_SAMPLE_S32LE 7
15587 #define MA_PA_SAMPLE_S32BE 8
15588 #define MA_PA_SAMPLE_S24LE 9
15589 #define MA_PA_SAMPLE_S24BE 10
15590 #define MA_PA_SAMPLE_S24_32LE 11
15591 #define MA_PA_SAMPLE_S24_32BE 12
15592 
15593 typedef struct ma_pa_mainloop ma_pa_mainloop;
15594 typedef struct ma_pa_threaded_mainloop ma_pa_threaded_mainloop;
15595 typedef struct ma_pa_mainloop_api ma_pa_mainloop_api;
15596 typedef struct ma_pa_context ma_pa_context;
15597 typedef struct ma_pa_operation ma_pa_operation;
15598 typedef struct ma_pa_stream ma_pa_stream;
15599 typedef struct ma_pa_spawn_api ma_pa_spawn_api;
15600 
15601 typedef struct
15602 {
15603  ma_uint32 maxlength;
15604  ma_uint32 tlength;
15605  ma_uint32 prebuf;
15606  ma_uint32 minreq;
15607  ma_uint32 fragsize;
15608 } ma_pa_buffer_attr;
15609 
15610 typedef struct
15611 {
15612  ma_uint8 channels;
15613  ma_pa_channel_position_t map[MA_PA_CHANNELS_MAX];
15614 } ma_pa_channel_map;
15615 
15616 typedef struct
15617 {
15618  ma_uint8 channels;
15619  ma_uint32 values[MA_PA_CHANNELS_MAX];
15620 } ma_pa_cvolume;
15621 
15622 typedef struct
15623 {
15624  ma_pa_sample_format_t format;
15625  ma_uint32 rate;
15626  ma_uint8 channels;
15627 } ma_pa_sample_spec;
15628 
15629 typedef struct
15630 {
15631  const char* name;
15632  ma_uint32 index;
15633  const char* description;
15634  ma_pa_sample_spec sample_spec;
15635  ma_pa_channel_map channel_map;
15636  ma_uint32 owner_module;
15637  ma_pa_cvolume volume;
15638  int mute;
15639  ma_uint32 monitor_source;
15640  const char* monitor_source_name;
15641  ma_uint64 latency;
15642  const char* driver;
15643  ma_pa_sink_flags_t flags;
15644  void* proplist;
15645  ma_uint64 configured_latency;
15646  ma_uint32 base_volume;
15647  ma_pa_sink_state_t state;
15648  ma_uint32 n_volume_steps;
15649  ma_uint32 card;
15650  ma_uint32 n_ports;
15651  void** ports;
15652  void* active_port;
15653  ma_uint8 n_formats;
15654  void** formats;
15655 } ma_pa_sink_info;
15656 
15657 typedef struct
15658 {
15659  const char *name;
15660  ma_uint32 index;
15661  const char *description;
15662  ma_pa_sample_spec sample_spec;
15663  ma_pa_channel_map channel_map;
15664  ma_uint32 owner_module;
15665  ma_pa_cvolume volume;
15666  int mute;
15667  ma_uint32 monitor_of_sink;
15668  const char *monitor_of_sink_name;
15669  ma_uint64 latency;
15670  const char *driver;
15671  ma_pa_source_flags_t flags;
15672  void* proplist;
15673  ma_uint64 configured_latency;
15674  ma_uint32 base_volume;
15675  ma_pa_source_state_t state;
15676  ma_uint32 n_volume_steps;
15677  ma_uint32 card;
15678  ma_uint32 n_ports;
15679  void** ports;
15680  void* active_port;
15681  ma_uint8 n_formats;
15682  void** formats;
15683 } ma_pa_source_info;
15684 
15685 typedef void (* ma_pa_context_notify_cb_t)(ma_pa_context* c, void* userdata);
15686 typedef void (* ma_pa_sink_info_cb_t) (ma_pa_context* c, const ma_pa_sink_info* i, int eol, void* userdata);
15687 typedef void (* ma_pa_source_info_cb_t) (ma_pa_context* c, const ma_pa_source_info* i, int eol, void* userdata);
15688 typedef void (* ma_pa_stream_success_cb_t)(ma_pa_stream* s, int success, void* userdata);
15689 typedef void (* ma_pa_stream_request_cb_t)(ma_pa_stream* s, size_t nbytes, void* userdata);
15690 typedef void (* ma_pa_stream_notify_cb_t) (ma_pa_stream* s, void* userdata);
15691 typedef void (* ma_pa_free_cb_t) (void* p);
15692 #endif
15693 
15694 
15695 typedef ma_pa_mainloop* (* ma_pa_mainloop_new_proc) (void);
15696 typedef void (* ma_pa_mainloop_free_proc) (ma_pa_mainloop* m);
15697 typedef void (* ma_pa_mainloop_quit_proc) (ma_pa_mainloop* m, int retval);
15698 typedef ma_pa_mainloop_api* (* ma_pa_mainloop_get_api_proc) (ma_pa_mainloop* m);
15699 typedef int (* ma_pa_mainloop_iterate_proc) (ma_pa_mainloop* m, int block, int* retval);
15700 typedef void (* ma_pa_mainloop_wakeup_proc) (ma_pa_mainloop* m);
15701 typedef ma_pa_threaded_mainloop* (* ma_pa_threaded_mainloop_new_proc) (void);
15702 typedef void (* ma_pa_threaded_mainloop_free_proc) (ma_pa_threaded_mainloop* m);
15703 typedef int (* ma_pa_threaded_mainloop_start_proc) (ma_pa_threaded_mainloop* m);
15704 typedef void (* ma_pa_threaded_mainloop_stop_proc) (ma_pa_threaded_mainloop* m);
15705 typedef void (* ma_pa_threaded_mainloop_lock_proc) (ma_pa_threaded_mainloop* m);
15706 typedef void (* ma_pa_threaded_mainloop_unlock_proc) (ma_pa_threaded_mainloop* m);
15707 typedef void (* ma_pa_threaded_mainloop_wait_proc) (ma_pa_threaded_mainloop* m);
15708 typedef void (* ma_pa_threaded_mainloop_signal_proc) (ma_pa_threaded_mainloop* m, int wait_for_accept);
15709 typedef void (* ma_pa_threaded_mainloop_accept_proc) (ma_pa_threaded_mainloop* m);
15710 typedef int (* ma_pa_threaded_mainloop_get_retval_proc) (ma_pa_threaded_mainloop* m);
15711 typedef ma_pa_mainloop_api* (* ma_pa_threaded_mainloop_get_api_proc) (ma_pa_threaded_mainloop* m);
15712 typedef int (* ma_pa_threaded_mainloop_in_thread_proc) (ma_pa_threaded_mainloop* m);
15713 typedef void (* ma_pa_threaded_mainloop_set_name_proc) (ma_pa_threaded_mainloop* m, const char* name);
15714 typedef ma_pa_context* (* ma_pa_context_new_proc) (ma_pa_mainloop_api* mainloop, const char* name);
15715 typedef void (* ma_pa_context_unref_proc) (ma_pa_context* c);
15716 typedef int (* ma_pa_context_connect_proc) (ma_pa_context* c, const char* server, ma_pa_context_flags_t flags, const ma_pa_spawn_api* api);
15717 typedef void (* ma_pa_context_disconnect_proc) (ma_pa_context* c);
15718 typedef void (* ma_pa_context_set_state_callback_proc) (ma_pa_context* c, ma_pa_context_notify_cb_t cb, void* userdata);
15719 typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (ma_pa_context* c);
15720 typedef ma_pa_operation* (* ma_pa_context_get_sink_info_list_proc) (ma_pa_context* c, ma_pa_sink_info_cb_t cb, void* userdata);
15721 typedef ma_pa_operation* (* ma_pa_context_get_source_info_list_proc) (ma_pa_context* c, ma_pa_source_info_cb_t cb, void* userdata);
15722 typedef ma_pa_operation* (* ma_pa_context_get_sink_info_by_name_proc) (ma_pa_context* c, const char* name, ma_pa_sink_info_cb_t cb, void* userdata);
15723 typedef ma_pa_operation* (* ma_pa_context_get_source_info_by_name_proc)(ma_pa_context* c, const char* name, ma_pa_source_info_cb_t cb, void* userdata);
15724 typedef void (* ma_pa_operation_unref_proc) (ma_pa_operation* o);
15725 typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (ma_pa_operation* o);
15726 typedef ma_pa_channel_map* (* ma_pa_channel_map_init_extend_proc) (ma_pa_channel_map* m, unsigned channels, ma_pa_channel_map_def_t def);
15727 typedef int (* ma_pa_channel_map_valid_proc) (const ma_pa_channel_map* m);
15728 typedef int (* ma_pa_channel_map_compatible_proc) (const ma_pa_channel_map* m, const ma_pa_sample_spec* ss);
15729 typedef ma_pa_stream* (* ma_pa_stream_new_proc) (ma_pa_context* c, const char* name, const ma_pa_sample_spec* ss, const ma_pa_channel_map* map);
15730 typedef void (* ma_pa_stream_unref_proc) (ma_pa_stream* s);
15731 typedef int (* ma_pa_stream_connect_playback_proc) (ma_pa_stream* s, const char* dev, const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags, const ma_pa_cvolume* volume, ma_pa_stream* sync_stream);
15732 typedef int (* ma_pa_stream_connect_record_proc) (ma_pa_stream* s, const char* dev, const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags);
15733 typedef int (* ma_pa_stream_disconnect_proc) (ma_pa_stream* s);
15734 typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (ma_pa_stream* s);
15735 typedef const ma_pa_sample_spec* (* ma_pa_stream_get_sample_spec_proc) (ma_pa_stream* s);
15736 typedef const ma_pa_channel_map* (* ma_pa_stream_get_channel_map_proc) (ma_pa_stream* s);
15737 typedef const ma_pa_buffer_attr* (* ma_pa_stream_get_buffer_attr_proc) (ma_pa_stream* s);
15738 typedef ma_pa_operation* (* ma_pa_stream_set_buffer_attr_proc) (ma_pa_stream* s, const ma_pa_buffer_attr* attr, ma_pa_stream_success_cb_t cb, void* userdata);
15739 typedef const char* (* ma_pa_stream_get_device_name_proc) (ma_pa_stream* s);
15740 typedef void (* ma_pa_stream_set_write_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata);
15741 typedef void (* ma_pa_stream_set_read_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata);
15742 typedef void (* ma_pa_stream_set_suspended_callback_proc) (ma_pa_stream* s, ma_pa_stream_notify_cb_t cb, void* userdata);
15743 typedef int (* ma_pa_stream_is_suspended_proc) (const ma_pa_stream* s);
15744 typedef ma_pa_operation* (* ma_pa_stream_flush_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
15745 typedef ma_pa_operation* (* ma_pa_stream_drain_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
15746 typedef int (* ma_pa_stream_is_corked_proc) (ma_pa_stream* s);
15747 typedef ma_pa_operation* (* ma_pa_stream_cork_proc) (ma_pa_stream* s, int b, ma_pa_stream_success_cb_t cb, void* userdata);
15748 typedef ma_pa_operation* (* ma_pa_stream_trigger_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
15749 typedef int (* ma_pa_stream_begin_write_proc) (ma_pa_stream* s, void** data, size_t* nbytes);
15750 typedef int (* ma_pa_stream_write_proc) (ma_pa_stream* s, const void* data, size_t nbytes, ma_pa_free_cb_t free_cb, int64_t offset, ma_pa_seek_mode_t seek);
15751 typedef int (* ma_pa_stream_peek_proc) (ma_pa_stream* s, const void** data, size_t* nbytes);
15752 typedef int (* ma_pa_stream_drop_proc) (ma_pa_stream* s);
15753 typedef size_t (* ma_pa_stream_writable_size_proc) (ma_pa_stream* s);
15754 typedef size_t (* ma_pa_stream_readable_size_proc) (ma_pa_stream* s);
15755 
15756 typedef struct
15757 {
15758  ma_uint32 count;
15759  ma_uint32 capacity;
15760  ma_device_info* pInfo;
15761 } ma_pulse_device_enum_data;
15762 
15763 static ma_result ma_result_from_pulse(int result)
15764 {
15765  if (result < 0) {
15766  return MA_ERROR;
15767  }
15768 
15769  switch (result) {
15770  case MA_PA_OK: return MA_SUCCESS;
15771  case MA_PA_ERR_ACCESS: return MA_ACCESS_DENIED;
15772  case MA_PA_ERR_INVALID: return MA_INVALID_ARGS;
15773  case MA_PA_ERR_NOENTITY: return MA_NO_DEVICE;
15774  default: return MA_ERROR;
15775  }
15776 }
15777 
15778 #if 0
15779 static ma_pa_sample_format_t ma_format_to_pulse(ma_format format)
15780 {
15781  if (ma_is_little_endian()) {
15782  switch (format) {
15783  case ma_format_s16: return MA_PA_SAMPLE_S16LE;
15784  case ma_format_s24: return MA_PA_SAMPLE_S24LE;
15785  case ma_format_s32: return MA_PA_SAMPLE_S32LE;
15786  case ma_format_f32: return MA_PA_SAMPLE_FLOAT32LE;
15787  default: break;
15788  }
15789  } else {
15790  switch (format) {
15791  case ma_format_s16: return MA_PA_SAMPLE_S16BE;
15792  case ma_format_s24: return MA_PA_SAMPLE_S24BE;
15793  case ma_format_s32: return MA_PA_SAMPLE_S32BE;
15794  case ma_format_f32: return MA_PA_SAMPLE_FLOAT32BE;
15795  default: break;
15796  }
15797  }
15798 
15799  /* Endian agnostic. */
15800  switch (format) {
15801  case ma_format_u8: return MA_PA_SAMPLE_U8;
15802  default: return MA_PA_SAMPLE_INVALID;
15803  }
15804 }
15805 #endif
15806 
15807 static ma_format ma_format_from_pulse(ma_pa_sample_format_t format)
15808 {
15809  if (ma_is_little_endian()) {
15810  switch (format) {
15811  case MA_PA_SAMPLE_S16LE: return ma_format_s16;
15812  case MA_PA_SAMPLE_S24LE: return ma_format_s24;
15813  case MA_PA_SAMPLE_S32LE: return ma_format_s32;
15814  case MA_PA_SAMPLE_FLOAT32LE: return ma_format_f32;
15815  default: break;
15816  }
15817  } else {
15818  switch (format) {
15819  case MA_PA_SAMPLE_S16BE: return ma_format_s16;
15820  case MA_PA_SAMPLE_S24BE: return ma_format_s24;
15821  case MA_PA_SAMPLE_S32BE: return ma_format_s32;
15822  case MA_PA_SAMPLE_FLOAT32BE: return ma_format_f32;
15823  default: break;
15824  }
15825  }
15826 
15827  /* Endian agnostic. */
15828  switch (format) {
15829  case MA_PA_SAMPLE_U8: return ma_format_u8;
15830  default: return ma_format_unknown;
15831  }
15832 }
15833 
15834 static ma_channel ma_channel_position_from_pulse(ma_pa_channel_position_t position)
15835 {
15836  switch (position)
15837  {
15838  case MA_PA_CHANNEL_POSITION_INVALID: return MA_CHANNEL_NONE;
15839  case MA_PA_CHANNEL_POSITION_MONO: return MA_CHANNEL_MONO;
15840  case MA_PA_CHANNEL_POSITION_FRONT_LEFT: return MA_CHANNEL_FRONT_LEFT;
15841  case MA_PA_CHANNEL_POSITION_FRONT_RIGHT: return MA_CHANNEL_FRONT_RIGHT;
15842  case MA_PA_CHANNEL_POSITION_FRONT_CENTER: return MA_CHANNEL_FRONT_CENTER;
15843  case MA_PA_CHANNEL_POSITION_REAR_CENTER: return MA_CHANNEL_BACK_CENTER;
15844  case MA_PA_CHANNEL_POSITION_REAR_LEFT: return MA_CHANNEL_BACK_LEFT;
15845  case MA_PA_CHANNEL_POSITION_REAR_RIGHT: return MA_CHANNEL_BACK_RIGHT;
15846  case MA_PA_CHANNEL_POSITION_LFE: return MA_CHANNEL_LFE;
15847  case MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: return MA_CHANNEL_FRONT_LEFT_CENTER;
15848  case MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return MA_CHANNEL_FRONT_RIGHT_CENTER;
15849  case MA_PA_CHANNEL_POSITION_SIDE_LEFT: return MA_CHANNEL_SIDE_LEFT;
15850  case MA_PA_CHANNEL_POSITION_SIDE_RIGHT: return MA_CHANNEL_SIDE_RIGHT;
15851  case MA_PA_CHANNEL_POSITION_AUX0: return MA_CHANNEL_AUX_0;
15852  case MA_PA_CHANNEL_POSITION_AUX1: return MA_CHANNEL_AUX_1;
15853  case MA_PA_CHANNEL_POSITION_AUX2: return MA_CHANNEL_AUX_2;
15854  case MA_PA_CHANNEL_POSITION_AUX3: return MA_CHANNEL_AUX_3;
15855  case MA_PA_CHANNEL_POSITION_AUX4: return MA_CHANNEL_AUX_4;
15856  case MA_PA_CHANNEL_POSITION_AUX5: return MA_CHANNEL_AUX_5;
15857  case MA_PA_CHANNEL_POSITION_AUX6: return MA_CHANNEL_AUX_6;
15858  case MA_PA_CHANNEL_POSITION_AUX7: return MA_CHANNEL_AUX_7;
15859  case MA_PA_CHANNEL_POSITION_AUX8: return MA_CHANNEL_AUX_8;
15860  case MA_PA_CHANNEL_POSITION_AUX9: return MA_CHANNEL_AUX_9;
15861  case MA_PA_CHANNEL_POSITION_AUX10: return MA_CHANNEL_AUX_10;
15862  case MA_PA_CHANNEL_POSITION_AUX11: return MA_CHANNEL_AUX_11;
15863  case MA_PA_CHANNEL_POSITION_AUX12: return MA_CHANNEL_AUX_12;
15864  case MA_PA_CHANNEL_POSITION_AUX13: return MA_CHANNEL_AUX_13;
15865  case MA_PA_CHANNEL_POSITION_AUX14: return MA_CHANNEL_AUX_14;
15866  case MA_PA_CHANNEL_POSITION_AUX15: return MA_CHANNEL_AUX_15;
15867  case MA_PA_CHANNEL_POSITION_AUX16: return MA_CHANNEL_AUX_16;
15868  case MA_PA_CHANNEL_POSITION_AUX17: return MA_CHANNEL_AUX_17;
15869  case MA_PA_CHANNEL_POSITION_AUX18: return MA_CHANNEL_AUX_18;
15870  case MA_PA_CHANNEL_POSITION_AUX19: return MA_CHANNEL_AUX_19;
15871  case MA_PA_CHANNEL_POSITION_AUX20: return MA_CHANNEL_AUX_20;
15872  case MA_PA_CHANNEL_POSITION_AUX21: return MA_CHANNEL_AUX_21;
15873  case MA_PA_CHANNEL_POSITION_AUX22: return MA_CHANNEL_AUX_22;
15874  case MA_PA_CHANNEL_POSITION_AUX23: return MA_CHANNEL_AUX_23;
15875  case MA_PA_CHANNEL_POSITION_AUX24: return MA_CHANNEL_AUX_24;
15876  case MA_PA_CHANNEL_POSITION_AUX25: return MA_CHANNEL_AUX_25;
15877  case MA_PA_CHANNEL_POSITION_AUX26: return MA_CHANNEL_AUX_26;
15878  case MA_PA_CHANNEL_POSITION_AUX27: return MA_CHANNEL_AUX_27;
15879  case MA_PA_CHANNEL_POSITION_AUX28: return MA_CHANNEL_AUX_28;
15880  case MA_PA_CHANNEL_POSITION_AUX29: return MA_CHANNEL_AUX_29;
15881  case MA_PA_CHANNEL_POSITION_AUX30: return MA_CHANNEL_AUX_30;
15882  case MA_PA_CHANNEL_POSITION_AUX31: return MA_CHANNEL_AUX_31;
15883  case MA_PA_CHANNEL_POSITION_TOP_CENTER: return MA_CHANNEL_TOP_CENTER;
15884  case MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT: return MA_CHANNEL_TOP_FRONT_LEFT;
15885  case MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: return MA_CHANNEL_TOP_FRONT_RIGHT;
15886  case MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER: return MA_CHANNEL_TOP_FRONT_CENTER;
15887  case MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT: return MA_CHANNEL_TOP_BACK_LEFT;
15888  case MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT: return MA_CHANNEL_TOP_BACK_RIGHT;
15889  case MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER: return MA_CHANNEL_TOP_BACK_CENTER;
15890  default: return MA_CHANNEL_NONE;
15891  }
15892 }
15893 
15894 #if 0
15895 static ma_pa_channel_position_t ma_channel_position_to_pulse(ma_channel position)
15896 {
15897  switch (position)
15898  {
15899  case MA_CHANNEL_NONE: return MA_PA_CHANNEL_POSITION_INVALID;
15900  case MA_CHANNEL_FRONT_LEFT: return MA_PA_CHANNEL_POSITION_FRONT_LEFT;
15901  case MA_CHANNEL_FRONT_RIGHT: return MA_PA_CHANNEL_POSITION_FRONT_RIGHT;
15902  case MA_CHANNEL_FRONT_CENTER: return MA_PA_CHANNEL_POSITION_FRONT_CENTER;
15903  case MA_CHANNEL_LFE: return MA_PA_CHANNEL_POSITION_LFE;
15904  case MA_CHANNEL_BACK_LEFT: return MA_PA_CHANNEL_POSITION_REAR_LEFT;
15905  case MA_CHANNEL_BACK_RIGHT: return MA_PA_CHANNEL_POSITION_REAR_RIGHT;
15906  case MA_CHANNEL_FRONT_LEFT_CENTER: return MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
15907  case MA_CHANNEL_FRONT_RIGHT_CENTER: return MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
15908  case MA_CHANNEL_BACK_CENTER: return MA_PA_CHANNEL_POSITION_REAR_CENTER;
15909  case MA_CHANNEL_SIDE_LEFT: return MA_PA_CHANNEL_POSITION_SIDE_LEFT;
15910  case MA_CHANNEL_SIDE_RIGHT: return MA_PA_CHANNEL_POSITION_SIDE_RIGHT;
15911  case MA_CHANNEL_TOP_CENTER: return MA_PA_CHANNEL_POSITION_TOP_CENTER;
15912  case MA_CHANNEL_TOP_FRONT_LEFT: return MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
15913  case MA_CHANNEL_TOP_FRONT_CENTER: return MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
15914  case MA_CHANNEL_TOP_FRONT_RIGHT: return MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
15915  case MA_CHANNEL_TOP_BACK_LEFT: return MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT;
15916  case MA_CHANNEL_TOP_BACK_CENTER: return MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER;
15917  case MA_CHANNEL_TOP_BACK_RIGHT: return MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
15918  case MA_CHANNEL_19: return MA_PA_CHANNEL_POSITION_AUX18;
15919  case MA_CHANNEL_20: return MA_PA_CHANNEL_POSITION_AUX19;
15920  case MA_CHANNEL_21: return MA_PA_CHANNEL_POSITION_AUX20;
15921  case MA_CHANNEL_22: return MA_PA_CHANNEL_POSITION_AUX21;
15922  case MA_CHANNEL_23: return MA_PA_CHANNEL_POSITION_AUX22;
15923  case MA_CHANNEL_24: return MA_PA_CHANNEL_POSITION_AUX23;
15924  case MA_CHANNEL_25: return MA_PA_CHANNEL_POSITION_AUX24;
15925  case MA_CHANNEL_26: return MA_PA_CHANNEL_POSITION_AUX25;
15926  case MA_CHANNEL_27: return MA_PA_CHANNEL_POSITION_AUX26;
15927  case MA_CHANNEL_28: return MA_PA_CHANNEL_POSITION_AUX27;
15928  case MA_CHANNEL_29: return MA_PA_CHANNEL_POSITION_AUX28;
15929  case MA_CHANNEL_30: return MA_PA_CHANNEL_POSITION_AUX29;
15930  case MA_CHANNEL_31: return MA_PA_CHANNEL_POSITION_AUX30;
15931  case MA_CHANNEL_32: return MA_PA_CHANNEL_POSITION_AUX31;
15932  default: return (ma_pa_channel_position_t)position;
15933  }
15934 }
15935 #endif
15936 
15937 static ma_result ma_wait_for_operation__pulse(ma_context* pContext, ma_pa_operation* pOP)
15938 {
15939  int resultPA;
15940  ma_pa_operation_state_t state;
15941 
15942  MA_ASSERT(pContext != NULL);
15943  MA_ASSERT(pOP != NULL);
15944 
15945  for (;;) {
15946  state = ((ma_pa_operation_get_state_proc)pContext->pulse.pa_operation_get_state)(pOP);
15947  if (state != MA_PA_OPERATION_RUNNING) {
15948  break; /* Done. */
15949  }
15950 
15951  resultPA = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pContext->pulse.pMainLoop, 1, NULL);
15952  if (resultPA < 0) {
15953  return ma_result_from_pulse(resultPA);
15954  }
15955  }
15956 
15957  return MA_SUCCESS;
15958 }
15959 
15960 static ma_result ma_wait_for_operation_and_unref__pulse(ma_context* pContext, ma_pa_operation* pOP)
15961 {
15962  ma_result result;
15963 
15964  if (pOP == NULL) {
15965  return MA_INVALID_ARGS;
15966  }
15967 
15968  result = ma_wait_for_operation__pulse(pContext, pOP);
15969  ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15970 
15971  return result;
15972 }
15973 
15974 static ma_result ma_context_wait_for_pa_context_to_connect__pulse(ma_context* pContext)
15975 {
15976  int resultPA;
15977  ma_pa_context_state_t state;
15978 
15979  for (;;) {
15980  state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)((ma_pa_context*)pContext->pulse.pPulseContext);
15981  if (state == MA_PA_CONTEXT_READY) {
15982  break; /* Done. */
15983  }
15984 
15985  if (state == MA_PA_CONTEXT_FAILED || state == MA_PA_CONTEXT_TERMINATED) {
15986  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] An error occurred while connecting the PulseAudio context.", MA_ERROR);
15987  }
15988 
15989  resultPA = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pContext->pulse.pMainLoop, 1, NULL);
15990  if (resultPA < 0) {
15991  return ma_result_from_pulse(resultPA);
15992  }
15993  }
15994 
15995  /* Should never get here. */
15996  return MA_SUCCESS;
15997 }
15998 
15999 static ma_result ma_context_wait_for_pa_stream_to_connect__pulse(ma_context* pContext, ma_pa_stream* pStream)
16000 {
16001  int resultPA;
16002  ma_pa_stream_state_t state;
16003 
16004  for (;;) {
16005  state = ((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)(pStream);
16006  if (state == MA_PA_STREAM_READY) {
16007  break; /* Done. */
16008  }
16009 
16010  if (state == MA_PA_STREAM_FAILED || state == MA_PA_STREAM_TERMINATED) {
16011  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] An error occurred while connecting the PulseAudio stream.", MA_ERROR);
16012  }
16013 
16014  resultPA = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pContext->pulse.pMainLoop, 1, NULL);
16015  if (resultPA < 0) {
16016  return ma_result_from_pulse(resultPA);
16017  }
16018  }
16019 
16020  return MA_SUCCESS;
16021 }
16022 
16023 
16024 static void ma_device_sink_info_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
16025 {
16026  ma_pa_sink_info* pInfoOut;
16027 
16028  if (endOfList > 0) {
16029  return;
16030  }
16031 
16032  pInfoOut = (ma_pa_sink_info*)pUserData;
16033  MA_ASSERT(pInfoOut != NULL);
16034 
16035  *pInfoOut = *pInfo;
16036 
16037  (void)pPulseContext; /* Unused. */
16038 }
16039 
16040 static void ma_device_source_info_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
16041 {
16042  ma_pa_source_info* pInfoOut;
16043 
16044  if (endOfList > 0) {
16045  return;
16046  }
16047 
16048  pInfoOut = (ma_pa_source_info*)pUserData;
16049  MA_ASSERT(pInfoOut != NULL);
16050 
16051  *pInfoOut = *pInfo;
16052 
16053  (void)pPulseContext; /* Unused. */
16054 }
16055 
16056 static void ma_device_sink_name_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
16057 {
16058  ma_device* pDevice;
16059 
16060  if (endOfList > 0) {
16061  return;
16062  }
16063 
16064  pDevice = (ma_device*)pUserData;
16065  MA_ASSERT(pDevice != NULL);
16066 
16067  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), pInfo->description, (size_t)-1);
16068 
16069  (void)pPulseContext; /* Unused. */
16070 }
16071 
16072 static void ma_device_source_name_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
16073 {
16074  ma_device* pDevice;
16075 
16076  if (endOfList > 0) {
16077  return;
16078  }
16079 
16080  pDevice = (ma_device*)pUserData;
16081  MA_ASSERT(pDevice != NULL);
16082 
16083  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), pInfo->description, (size_t)-1);
16084 
16085  (void)pPulseContext; /* Unused. */
16086 }
16087 
16088 
16089 static ma_result ma_context_get_sink_info__pulse(ma_context* pContext, const char* pDeviceName, ma_pa_sink_info* pSinkInfo)
16090 {
16091  ma_pa_operation* pOP;
16092 
16093  pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, pDeviceName, ma_device_sink_info_callback, pSinkInfo);
16094  if (pOP == NULL) {
16095  return MA_ERROR;
16096  }
16097 
16098  return ma_wait_for_operation_and_unref__pulse(pContext, pOP);
16099 }
16100 
16101 static ma_result ma_context_get_source_info__pulse(ma_context* pContext, const char* pDeviceName, ma_pa_source_info* pSourceInfo)
16102 {
16103  ma_pa_operation* pOP;
16104 
16105  pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, pDeviceName, ma_device_source_info_callback, pSourceInfo);
16106  if (pOP == NULL) {
16107  return MA_ERROR;
16108  }
16109 
16110  return ma_wait_for_operation_and_unref__pulse(pContext, pOP);;
16111 }
16112 
16113 static ma_result ma_context_get_default_device_index__pulse(ma_context* pContext, ma_device_type deviceType, ma_uint32* pIndex)
16114 {
16115  ma_result result;
16116 
16117  MA_ASSERT(pContext != NULL);
16118  MA_ASSERT(pIndex != NULL);
16119 
16120  if (pIndex != NULL) {
16121  *pIndex = (ma_uint32)-1;
16122  }
16123 
16124  if (deviceType == ma_device_type_playback) {
16125  ma_pa_sink_info sinkInfo;
16126  result = ma_context_get_sink_info__pulse(pContext, NULL, &sinkInfo);
16127  if (result != MA_SUCCESS) {
16128  return result;
16129  }
16130 
16131  if (pIndex != NULL) {
16132  *pIndex = sinkInfo.index;
16133  }
16134  }
16135 
16136  if (deviceType == ma_device_type_capture) {
16137  ma_pa_source_info sourceInfo;
16138  result = ma_context_get_source_info__pulse(pContext, NULL, &sourceInfo);
16139  if (result != MA_SUCCESS) {
16140  return result;
16141  }
16142 
16143  if (pIndex != NULL) {
16144  *pIndex = sourceInfo.index;
16145  }
16146  }
16147 
16148  return MA_SUCCESS;
16149 }
16150 
16151 
16152 typedef struct
16153 {
16154  ma_context* pContext;
16156  void* pUserData;
16157  ma_bool32 isTerminated;
16158  ma_uint32 defaultDeviceIndexPlayback;
16159  ma_uint32 defaultDeviceIndexCapture;
16160 } ma_context_enumerate_devices_callback_data__pulse;
16161 
16162 static void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_sink_info* pSinkInfo, int endOfList, void* pUserData)
16163 {
16164  ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
16165  ma_device_info deviceInfo;
16166 
16167  MA_ASSERT(pData != NULL);
16168 
16169  if (endOfList || pData->isTerminated) {
16170  return;
16171  }
16172 
16173  MA_ZERO_OBJECT(&deviceInfo);
16174 
16175  /* The name from PulseAudio is the ID for miniaudio. */
16176  if (pSinkInfo->name != NULL) {
16177  ma_strncpy_s(deviceInfo.id.pulse, sizeof(deviceInfo.id.pulse), pSinkInfo->name, (size_t)-1);
16178  }
16179 
16180  /* The description from PulseAudio is the name for miniaudio. */
16181  if (pSinkInfo->description != NULL) {
16182  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSinkInfo->description, (size_t)-1);
16183  }
16184 
16185  if (pSinkInfo->index == pData->defaultDeviceIndexPlayback) {
16186  deviceInfo.isDefault = MA_TRUE;
16187  }
16188 
16189  pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_playback, &deviceInfo, pData->pUserData);
16190 
16191  (void)pPulseContext; /* Unused. */
16192 }
16193 
16194 static void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_source_info* pSourceInfo, int endOfList, void* pUserData)
16195 {
16196  ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
16197  ma_device_info deviceInfo;
16198 
16199  MA_ASSERT(pData != NULL);
16200 
16201  if (endOfList || pData->isTerminated) {
16202  return;
16203  }
16204 
16205  MA_ZERO_OBJECT(&deviceInfo);
16206 
16207  /* The name from PulseAudio is the ID for miniaudio. */
16208  if (pSourceInfo->name != NULL) {
16209  ma_strncpy_s(deviceInfo.id.pulse, sizeof(deviceInfo.id.pulse), pSourceInfo->name, (size_t)-1);
16210  }
16211 
16212  /* The description from PulseAudio is the name for miniaudio. */
16213  if (pSourceInfo->description != NULL) {
16214  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSourceInfo->description, (size_t)-1);
16215  }
16216 
16217  if (pSourceInfo->index == pData->defaultDeviceIndexCapture) {
16218  deviceInfo.isDefault = MA_TRUE;
16219  }
16220 
16221  pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_capture, &deviceInfo, pData->pUserData);
16222 
16223  (void)pPulseContext; /* Unused. */
16224 }
16225 
16226 static ma_result ma_context_enumerate_devices__pulse(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
16227 {
16228  ma_result result = MA_SUCCESS;
16229  ma_context_enumerate_devices_callback_data__pulse callbackData;
16230  ma_pa_operation* pOP = NULL;
16231 
16232  MA_ASSERT(pContext != NULL);
16233  MA_ASSERT(callback != NULL);
16234 
16235  callbackData.pContext = pContext;
16236  callbackData.callback = callback;
16237  callbackData.pUserData = pUserData;
16238  callbackData.isTerminated = MA_FALSE;
16239  callbackData.defaultDeviceIndexPlayback = (ma_uint32)-1;
16240  callbackData.defaultDeviceIndexCapture = (ma_uint32)-1;
16241 
16242  /* We need to get the index of the default devices. */
16243  ma_context_get_default_device_index__pulse(pContext, ma_device_type_playback, &callbackData.defaultDeviceIndexPlayback);
16244  ma_context_get_default_device_index__pulse(pContext, ma_device_type_capture, &callbackData.defaultDeviceIndexCapture);
16245 
16246  /* Playback. */
16247  if (!callbackData.isTerminated) {
16248  pOP = ((ma_pa_context_get_sink_info_list_proc)pContext->pulse.pa_context_get_sink_info_list)((ma_pa_context*)(pContext->pulse.pPulseContext), ma_context_enumerate_devices_sink_callback__pulse, &callbackData);
16249  if (pOP == NULL) {
16250  result = MA_ERROR;
16251  goto done;
16252  }
16253 
16254  result = ma_wait_for_operation__pulse(pContext, pOP);
16255  ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16256 
16257  if (result != MA_SUCCESS) {
16258  goto done;
16259  }
16260  }
16261 
16262 
16263  /* Capture. */
16264  if (!callbackData.isTerminated) {
16265  pOP = ((ma_pa_context_get_source_info_list_proc)pContext->pulse.pa_context_get_source_info_list)((ma_pa_context*)(pContext->pulse.pPulseContext), ma_context_enumerate_devices_source_callback__pulse, &callbackData);
16266  if (pOP == NULL) {
16267  result = MA_ERROR;
16268  goto done;
16269  }
16270 
16271  result = ma_wait_for_operation__pulse(pContext, pOP);
16272  ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16273 
16274  if (result != MA_SUCCESS) {
16275  goto done;
16276  }
16277  }
16278 
16279 done:
16280  return result;
16281 }
16282 
16283 
16284 typedef struct
16285 {
16286  ma_device_info* pDeviceInfo;
16287  ma_uint32 defaultDeviceIndex;
16288  ma_bool32 foundDevice;
16289 } ma_context_get_device_info_callback_data__pulse;
16290 
16291 static void ma_context_get_device_info_sink_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
16292 {
16293  ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
16294 
16295  if (endOfList > 0) {
16296  return;
16297  }
16298 
16299  MA_ASSERT(pData != NULL);
16300  pData->foundDevice = MA_TRUE;
16301 
16302  if (pInfo->name != NULL) {
16303  ma_strncpy_s(pData->pDeviceInfo->id.pulse, sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (size_t)-1);
16304  }
16305 
16306  if (pInfo->description != NULL) {
16307  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pInfo->description, (size_t)-1);
16308  }
16309 
16310  /*
16311  We're just reporting a single data format here. I think technically PulseAudio might support
16312  all formats, but I don't trust that PulseAudio will do *anything* right, so I'm just going to
16313  report the "native" device format.
16314  */
16315  pData->pDeviceInfo->nativeDataFormats[0].format = ma_format_from_pulse(pInfo->sample_spec.format);
16316  pData->pDeviceInfo->nativeDataFormats[0].channels = pInfo->sample_spec.channels;
16317  pData->pDeviceInfo->nativeDataFormats[0].sampleRate = pInfo->sample_spec.rate;
16318  pData->pDeviceInfo->nativeDataFormats[0].flags = 0;
16319  pData->pDeviceInfo->nativeDataFormatCount = 1;
16320 
16321  if (pData->defaultDeviceIndex == pInfo->index) {
16322  pData->pDeviceInfo->isDefault = MA_TRUE;
16323  }
16324 
16325  (void)pPulseContext; /* Unused. */
16326 }
16327 
16328 static void ma_context_get_device_info_source_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
16329 {
16330  ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
16331 
16332  if (endOfList > 0) {
16333  return;
16334  }
16335 
16336  MA_ASSERT(pData != NULL);
16337  pData->foundDevice = MA_TRUE;
16338 
16339  if (pInfo->name != NULL) {
16340  ma_strncpy_s(pData->pDeviceInfo->id.pulse, sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (size_t)-1);
16341  }
16342 
16343  if (pInfo->description != NULL) {
16344  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pInfo->description, (size_t)-1);
16345  }
16346 
16347  /*
16348  We're just reporting a single data format here. I think technically PulseAudio might support
16349  all formats, but I don't trust that PulseAudio will do *anything* right, so I'm just going to
16350  report the "native" device format.
16351  */
16352  pData->pDeviceInfo->nativeDataFormats[0].format = ma_format_from_pulse(pInfo->sample_spec.format);
16353  pData->pDeviceInfo->nativeDataFormats[0].channels = pInfo->sample_spec.channels;
16354  pData->pDeviceInfo->nativeDataFormats[0].sampleRate = pInfo->sample_spec.rate;
16355  pData->pDeviceInfo->nativeDataFormats[0].flags = 0;
16356  pData->pDeviceInfo->nativeDataFormatCount = 1;
16357 
16358  if (pData->defaultDeviceIndex == pInfo->index) {
16359  pData->pDeviceInfo->isDefault = MA_TRUE;
16360  }
16361 
16362  (void)pPulseContext; /* Unused. */
16363 }
16364 
16365 static ma_result ma_context_get_device_info__pulse(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
16366 {
16367  ma_result result = MA_SUCCESS;
16368  ma_context_get_device_info_callback_data__pulse callbackData;
16369  ma_pa_operation* pOP = NULL;
16370  const char* pDeviceName = NULL;
16371 
16372  MA_ASSERT(pContext != NULL);
16373 
16374  callbackData.pDeviceInfo = pDeviceInfo;
16375  callbackData.foundDevice = MA_FALSE;
16376 
16377  if (pDeviceID != NULL) {
16378  pDeviceName = pDeviceID->pulse;
16379  } else {
16380  pDeviceName = NULL;
16381  }
16382 
16383  result = ma_context_get_default_device_index__pulse(pContext, deviceType, &callbackData.defaultDeviceIndex);
16384 
16385  if (deviceType == ma_device_type_playback) {
16386  pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)(pContext->pulse.pPulseContext), pDeviceName, ma_context_get_device_info_sink_callback__pulse, &callbackData);
16387  } else {
16388  pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)(pContext->pulse.pPulseContext), pDeviceName, ma_context_get_device_info_source_callback__pulse, &callbackData);
16389  }
16390 
16391  if (pOP != NULL) {
16392  ma_wait_for_operation_and_unref__pulse(pContext, pOP);
16393  } else {
16394  result = MA_ERROR;
16395  goto done;
16396  }
16397 
16398  if (!callbackData.foundDevice) {
16399  result = MA_NO_DEVICE;
16400  goto done;
16401  }
16402 
16403 done:
16404  return result;
16405 }
16406 
16407 static ma_result ma_device_uninit__pulse(ma_device* pDevice)
16408 {
16409  ma_context* pContext;
16410 
16411  MA_ASSERT(pDevice != NULL);
16412 
16413  pContext = pDevice->pContext;
16414  MA_ASSERT(pContext != NULL);
16415 
16416  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
16417  ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16418  ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16419  }
16420 
16421  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
16422  ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16423  ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16424  }
16425 
16426  if (pDevice->type == ma_device_type_duplex) {
16427  ma_duplex_rb_uninit(&pDevice->duplexRB);
16428  }
16429 
16430  return MA_SUCCESS;
16431 }
16432 
16433 static ma_pa_buffer_attr ma_device__pa_buffer_attr_new(ma_uint32 periodSizeInFrames, ma_uint32 periods, const ma_pa_sample_spec* ss)
16434 {
16435  ma_pa_buffer_attr attr;
16436  attr.maxlength = periodSizeInFrames * periods * ma_get_bytes_per_frame(ma_format_from_pulse(ss->format), ss->channels);
16437  attr.tlength = attr.maxlength / periods;
16438  attr.prebuf = (ma_uint32)-1;
16439  attr.minreq = (ma_uint32)-1;
16440  attr.fragsize = attr.maxlength / periods;
16441 
16442  return attr;
16443 }
16444 
16445 static ma_pa_stream* ma_context__pa_stream_new__pulse(ma_context* pContext, const char* pStreamName, const ma_pa_sample_spec* ss, const ma_pa_channel_map* cmap)
16446 {
16447  static int g_StreamCounter = 0;
16448  char actualStreamName[256];
16449 
16450  if (pStreamName != NULL) {
16451  ma_strncpy_s(actualStreamName, sizeof(actualStreamName), pStreamName, (size_t)-1);
16452  } else {
16453  ma_strcpy_s(actualStreamName, sizeof(actualStreamName), "miniaudio:");
16454  ma_itoa_s(g_StreamCounter, actualStreamName + 8, sizeof(actualStreamName)-8, 10); /* 8 = strlen("miniaudio:") */
16455  }
16456  g_StreamCounter += 1;
16457 
16458  return ((ma_pa_stream_new_proc)pContext->pulse.pa_stream_new)((ma_pa_context*)pContext->pulse.pPulseContext, actualStreamName, ss, cmap);
16459 }
16460 
16461 
16462 static void ma_device_on_read__pulse(ma_pa_stream* pStream, size_t byteCount, void* pUserData)
16463 {
16464  ma_device* pDevice = (ma_device*)pUserData;
16465  ma_uint32 bpf;
16466  ma_uint32 deviceState;
16467  ma_uint64 frameCount;
16468  ma_uint64 framesProcessed;
16469 
16470  MA_ASSERT(pDevice != NULL);
16471 
16472  /*
16473  Don't do anything if the device isn't initialized yet. Yes, this can happen because PulseAudio
16474  can fire this callback before the stream has even started. Ridiculous.
16475  */
16476  deviceState = ma_device_get_state(pDevice);
16477  if (deviceState != MA_STATE_STARTING && deviceState != MA_STATE_STARTED) {
16478  return;
16479  }
16480 
16482  MA_ASSERT(bpf > 0);
16483 
16484  frameCount = byteCount / bpf;
16485  framesProcessed = 0;
16486 
16487  while (ma_device_get_state(pDevice) == MA_STATE_STARTED && framesProcessed < frameCount) {
16488  const void* pMappedPCMFrames;
16489  size_t bytesMapped;
16490  ma_uint64 framesMapped;
16491 
16492  int pulseResult = ((ma_pa_stream_peek_proc)pDevice->pContext->pulse.pa_stream_peek)(pStream, &pMappedPCMFrames, &bytesMapped);
16493  if (pulseResult < 0) {
16494  break; /* Failed to map. Abort. */
16495  }
16496 
16497  framesMapped = bytesMapped / bpf;
16498  if (framesMapped > 0) {
16499  if (pMappedPCMFrames != NULL) {
16500  ma_device_handle_backend_data_callback(pDevice, NULL, pMappedPCMFrames, framesMapped);
16501  } else {
16502  /* It's a hole. */
16503  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] ma_device_on_read__pulse: Hole.\n");
16504  }
16505 
16506  pulseResult = ((ma_pa_stream_drop_proc)pDevice->pContext->pulse.pa_stream_drop)(pStream);
16507  if (pulseResult < 0) {
16508  break; /* Failed to drop the buffer. */
16509  }
16510 
16511  framesProcessed += framesMapped;
16512 
16513  } else {
16514  /* Nothing was mapped. Just abort. */
16515  break;
16516  }
16517  }
16518 }
16519 
16520 static ma_result ma_device_write_to_stream__pulse(ma_device* pDevice, ma_pa_stream* pStream, ma_uint64* pFramesProcessed)
16521 {
16522  ma_result result = MA_SUCCESS;
16523  ma_uint64 framesProcessed = 0;
16524  size_t bytesMapped;
16525  ma_uint32 bpf;
16526  ma_uint32 deviceState;
16527 
16528  MA_ASSERT(pDevice != NULL);
16529  MA_ASSERT(pStream != NULL);
16530 
16532  MA_ASSERT(bpf > 0);
16533 
16534  deviceState = ma_device_get_state(pDevice);
16535 
16536  bytesMapped = ((ma_pa_stream_writable_size_proc)pDevice->pContext->pulse.pa_stream_writable_size)(pStream);
16537  if (bytesMapped != (size_t)-1) {
16538  if (bytesMapped > 0) {
16539  ma_uint64 framesMapped;
16540  void* pMappedPCMFrames;
16541  int pulseResult = ((ma_pa_stream_begin_write_proc)pDevice->pContext->pulse.pa_stream_begin_write)(pStream, &pMappedPCMFrames, &bytesMapped);
16542  if (pulseResult < 0) {
16543  result = ma_result_from_pulse(pulseResult);
16544  goto done;
16545  }
16546 
16547  framesMapped = bytesMapped / bpf;
16548 
16549  if (deviceState == MA_STATE_STARTED || deviceState == MA_STATE_STARTING) { /* Check for starting state just in case this is being used to do the initial fill. */
16550  ma_device_handle_backend_data_callback(pDevice, pMappedPCMFrames, NULL, framesMapped);
16551  } else {
16552  /* Device is not started. Write silence. */
16553  ma_silence_pcm_frames(pMappedPCMFrames, framesMapped, pDevice->playback.format, pDevice->playback.channels);
16554  }
16555 
16556  pulseResult = ((ma_pa_stream_write_proc)pDevice->pContext->pulse.pa_stream_write)(pStream, pMappedPCMFrames, bytesMapped, NULL, 0, MA_PA_SEEK_RELATIVE);
16557  if (pulseResult < 0) {
16558  result = ma_result_from_pulse(pulseResult);
16559  goto done; /* Failed to write data to stream. */
16560  }
16561 
16562  framesProcessed += framesMapped;
16563  } else {
16564  result = MA_ERROR; /* No data available. Abort. */
16565  goto done;
16566  }
16567  } else {
16568  result = MA_ERROR; /* Failed to retrieve the writable size. Abort. */
16569  goto done;
16570  }
16571 
16572 done:
16573  if (pFramesProcessed != NULL) {
16574  *pFramesProcessed = framesProcessed;
16575  }
16576 
16577  return result;
16578 }
16579 
16580 static void ma_device_on_write__pulse(ma_pa_stream* pStream, size_t byteCount, void* pUserData)
16581 {
16582  ma_device* pDevice = (ma_device*)pUserData;
16583  ma_uint32 bpf;
16584  ma_uint64 frameCount;
16585  ma_uint64 framesProcessed;
16586  ma_uint32 deviceState;
16587  ma_result result;
16588 
16589  MA_ASSERT(pDevice != NULL);
16590 
16591  /*
16592  Don't do anything if the device isn't initialized yet. Yes, this can happen because PulseAudio
16593  can fire this callback before the stream has even started. Ridiculous.
16594  */
16595  deviceState = ma_device_get_state(pDevice);
16596  if (deviceState != MA_STATE_STARTING && deviceState != MA_STATE_STARTED) {
16597  return;
16598  }
16599 
16601  MA_ASSERT(bpf > 0);
16602 
16603  frameCount = byteCount / bpf;
16604  framesProcessed = 0;
16605 
16606  while (framesProcessed < frameCount) {
16607  ma_uint64 framesProcessedThisIteration;
16608 
16609  /* Don't keep trying to process frames if the device isn't started. */
16610  deviceState = ma_device_get_state(pDevice);
16611  if (deviceState != MA_STATE_STARTING && deviceState != MA_STATE_STARTED) {
16612  break;
16613  }
16614 
16615  result = ma_device_write_to_stream__pulse(pDevice, pStream, &framesProcessedThisIteration);
16616  if (result != MA_SUCCESS) {
16617  break;
16618  }
16619 
16620  framesProcessed += framesProcessedThisIteration;
16621  }
16622 }
16623 
16624 static void ma_device_on_suspended__pulse(ma_pa_stream* pStream, void* pUserData)
16625 {
16626  ma_device* pDevice = (ma_device*)pUserData;
16627  int suspended;
16628 
16629  (void)pStream;
16630 
16631  suspended = ((ma_pa_stream_is_suspended_proc)pDevice->pContext->pulse.pa_stream_is_suspended)(pStream);
16632  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[Pulse] Device suspended state changed. pa_stream_is_suspended() returned %d.\n", suspended);
16633 
16634  if (suspended < 0) {
16635  return;
16636  }
16637 
16638  if (suspended == 1) {
16639  ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[Pulse] Device suspended state changed. Suspended.\n");
16640 
16641  if (pDevice->onStop) {
16642  pDevice->onStop(pDevice);
16643  }
16644  } else {
16645  ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[Pulse] Device suspended state changed. Resumed.\n");
16646  }
16647 }
16648 
16649 static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
16650 {
16651  /*
16652  Notes for PulseAudio:
16653 
16654  - We're always using native format/channels/rate regardless of whether or not PulseAudio
16655  supports the format directly through their own data conversion system. I'm doing this to
16656  reduce as much variability from the PulseAudio side as possible because it's seems to be
16657  extremely unreliable at everything it does.
16658 
16659  - When both the period size in frames and milliseconds are 0, we default to miniaudio's
16660  default buffer sizes rather than leaving it up to PulseAudio because I don't trust
16661  PulseAudio to give us any kind of reasonable latency by default.
16662 
16663  - Do not ever, *ever* forget to use MA_PA_STREAM_ADJUST_LATENCY. If you don't specify this
16664  flag, capture mode will just not work properly until you open another PulseAudio app.
16665  */
16666 
16667  ma_result result = MA_SUCCESS;
16668  int error = 0;
16669  const char* devPlayback = NULL;
16670  const char* devCapture = NULL;
16671  ma_format format = ma_format_unknown;
16672  ma_uint32 channels = 0;
16673  ma_uint32 sampleRate = 0;
16674  ma_pa_sink_info sinkInfo;
16675  ma_pa_source_info sourceInfo;
16676  ma_pa_sample_spec ss;
16677  ma_pa_channel_map cmap;
16678  ma_pa_buffer_attr attr;
16679  const ma_pa_sample_spec* pActualSS = NULL;
16680  const ma_pa_channel_map* pActualCMap = NULL;
16681  const ma_pa_buffer_attr* pActualAttr = NULL;
16682  ma_uint32 iChannel;
16683  ma_pa_stream_flags_t streamFlags;
16684 
16685  MA_ASSERT(pDevice != NULL);
16686  MA_ZERO_OBJECT(&pDevice->pulse);
16687 
16688  if (pConfig->deviceType == ma_device_type_loopback) {
16690  }
16691 
16692  /* No exclusive mode with the PulseAudio backend. */
16696  }
16697 
16698  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
16699  if (pDescriptorPlayback->pDeviceID != NULL) {
16700  devPlayback = pDescriptorPlayback->pDeviceID->pulse;
16701  }
16702 
16703  format = pDescriptorPlayback->format;
16704  channels = pDescriptorPlayback->channels;
16705  sampleRate = pDescriptorPlayback->sampleRate;
16706  }
16707 
16708  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
16709  if (pDescriptorCapture->pDeviceID != NULL) {
16710  devCapture = pDescriptorCapture->pDeviceID->pulse;
16711  }
16712 
16713  format = pDescriptorCapture->format;
16714  channels = pDescriptorCapture->channels;
16715  sampleRate = pDescriptorCapture->sampleRate;
16716  }
16717 
16718  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
16719  result = ma_context_get_source_info__pulse(pDevice->pContext, devCapture, &sourceInfo);
16720  if (result != MA_SUCCESS) {
16721  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve source info for capture device.", result);
16722  goto on_error0;
16723  }
16724 
16725  ss = sourceInfo.sample_spec;
16726  cmap = sourceInfo.channel_map;
16727 
16728  if (ma_format_from_pulse(ss.format) == ma_format_unknown) {
16729  if (ma_is_little_endian()) {
16730  ss.format = MA_PA_SAMPLE_FLOAT32LE;
16731  } else {
16732  ss.format = MA_PA_SAMPLE_FLOAT32BE;
16733  }
16734  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.format not supported by miniaudio. Defaulting to PA_SAMPLE_RATE_FLOAT32\n");
16735  }
16736  if (ss.rate == 0) {
16737  ss.rate = MA_DEFAULT_SAMPLE_RATE;
16738  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.rate = 0. Defaulting to %d\n", ss.rate);
16739  }
16740  if (ss.channels == 0) {
16741  ss.channels = MA_DEFAULT_CHANNELS;
16742  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.channels = 0. Defaulting to %d\n", ss.channels);
16743  }
16744 
16745  /* We now have enough information to calculate our actual period size in frames. */
16746  pDescriptorCapture->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorCapture, ss.rate, pConfig->performanceProfile);
16747 
16748  attr = ma_device__pa_buffer_attr_new(pDescriptorCapture->periodSizeInFrames, pDescriptorCapture->periodCount, &ss);
16749  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] Capture attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; periodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDescriptorCapture->periodSizeInFrames);
16750 
16751  pDevice->pulse.pStreamCapture = ma_context__pa_stream_new__pulse(pDevice->pContext, pConfig->pulse.pStreamNameCapture, &ss, &cmap);
16752  if (pDevice->pulse.pStreamCapture == NULL) {
16753  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio capture stream.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
16754  goto on_error0;
16755  }
16756 
16757 
16758  /* The callback needs to be set before connecting the stream. */
16759  ((ma_pa_stream_set_read_callback_proc)pDevice->pContext->pulse.pa_stream_set_read_callback)((ma_pa_stream*)pDevice->pulse.pStreamCapture, ma_device_on_read__pulse, pDevice);
16760 
16761  /* State callback for checking when the device has been corked. */
16762  ((ma_pa_stream_set_suspended_callback_proc)pDevice->pContext->pulse.pa_stream_set_suspended_callback)((ma_pa_stream*)pDevice->pulse.pStreamCapture, ma_device_on_suspended__pulse, pDevice);
16763 
16764 
16765  /* Connect after we've got all of our internal state set up. */
16766  streamFlags = MA_PA_STREAM_START_CORKED | MA_PA_STREAM_ADJUST_LATENCY | MA_PA_STREAM_FIX_FORMAT | MA_PA_STREAM_FIX_RATE | MA_PA_STREAM_FIX_CHANNELS;
16767  if (devCapture != NULL) {
16768  streamFlags |= MA_PA_STREAM_DONT_MOVE;
16769  }
16770 
16771  error = ((ma_pa_stream_connect_record_proc)pDevice->pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
16772  if (error != MA_PA_OK) {
16773  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio capture stream.", ma_result_from_pulse(error));
16774  goto on_error1;
16775  }
16776 
16777  result = ma_context_wait_for_pa_stream_to_connect__pulse(pDevice->pContext, (ma_pa_stream*)pDevice->pulse.pStreamCapture);
16778  if (result != MA_SUCCESS) {
16779  goto on_error2;
16780  }
16781 
16782  /* Internal format. */
16783  pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16784  if (pActualSS != NULL) {
16785  ss = *pActualSS;
16786  }
16787 
16788  pDescriptorCapture->format = ma_format_from_pulse(ss.format);
16789  pDescriptorCapture->channels = ss.channels;
16790  pDescriptorCapture->sampleRate = ss.rate;
16791 
16792  /* Internal channel map. */
16793  pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16794  if (pActualCMap != NULL) {
16795  cmap = *pActualCMap;
16796  }
16797 
16798  for (iChannel = 0; iChannel < pDescriptorCapture->channels; ++iChannel) {
16799  pDescriptorCapture->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
16800  }
16801 
16802 
16803  /* Buffer. */
16804  pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pDevice->pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16805  if (pActualAttr != NULL) {
16806  attr = *pActualAttr;
16807  }
16808 
16809  pDescriptorCapture->periodCount = attr.maxlength / attr.fragsize;
16810  pDescriptorCapture->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) / pDescriptorCapture->periodCount;
16811 
16812  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] Capture actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; periodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDescriptorCapture->periodSizeInFrames);
16813 
16814 
16815  /* Name. */
16816  devCapture = ((ma_pa_stream_get_device_name_proc)pDevice->pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16817  if (devCapture != NULL) {
16818  ma_pa_operation* pOP = ((ma_pa_context_get_source_info_by_name_proc)pDevice->pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pDevice->pContext->pulse.pPulseContext, devCapture, ma_device_source_name_callback, pDevice);
16819  ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
16820  }
16821  }
16822 
16823  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
16824  result = ma_context_get_sink_info__pulse(pDevice->pContext, devPlayback, &sinkInfo);
16825  if (result != MA_SUCCESS) {
16826  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve sink info for playback device.", result);
16827  goto on_error2;
16828  }
16829 
16830  ss = sinkInfo.sample_spec;
16831  cmap = sinkInfo.channel_map;
16832 
16833  if (ma_format_from_pulse(ss.format) == ma_format_unknown) {
16834  if (ma_is_little_endian()) {
16835  ss.format = MA_PA_SAMPLE_FLOAT32LE;
16836  } else {
16837  ss.format = MA_PA_SAMPLE_FLOAT32BE;
16838  }
16839  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.format not supported by miniaudio. Defaulting to PA_SAMPLE_RATE_FLOAT32\n");
16840  }
16841  if (ss.rate == 0) {
16842  ss.rate = MA_DEFAULT_SAMPLE_RATE;
16843  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.rate = 0. Defaulting to %d\n", ss.rate);
16844  }
16845  if (ss.channels == 0) {
16846  ss.channels = MA_DEFAULT_CHANNELS;
16847  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.channels = 0. Defaulting to %d\n", ss.channels);
16848  }
16849 
16850  /* We now have enough information to calculate the actual buffer size in frames. */
16851  pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, ss.rate, pConfig->performanceProfile);
16852 
16853  attr = ma_device__pa_buffer_attr_new(pDescriptorPlayback->periodSizeInFrames, pDescriptorPlayback->periodCount, &ss);
16854 
16855  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] Playback attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; periodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDescriptorPlayback->periodSizeInFrames);
16856 
16857  pDevice->pulse.pStreamPlayback = ma_context__pa_stream_new__pulse(pDevice->pContext, pConfig->pulse.pStreamNamePlayback, &ss, &cmap);
16858  if (pDevice->pulse.pStreamPlayback == NULL) {
16859  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio playback stream.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
16860  goto on_error2;
16861  }
16862 
16863 
16864  /*
16865  Note that this callback will be fired as soon as the stream is connected, even though it's started as corked. The callback needs to handle a
16866  device state of MA_STATE_UNINITIALIZED.
16867  */
16868  ((ma_pa_stream_set_write_callback_proc)pDevice->pContext->pulse.pa_stream_set_write_callback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_device_on_write__pulse, pDevice);
16869 
16870  /* State callback for checking when the device has been corked. */
16871  ((ma_pa_stream_set_suspended_callback_proc)pDevice->pContext->pulse.pa_stream_set_suspended_callback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_device_on_suspended__pulse, pDevice);
16872 
16873 
16874  /* Connect after we've got all of our internal state set up. */
16875  streamFlags = MA_PA_STREAM_START_CORKED | MA_PA_STREAM_ADJUST_LATENCY | MA_PA_STREAM_FIX_FORMAT | MA_PA_STREAM_FIX_RATE | MA_PA_STREAM_FIX_CHANNELS;
16876  if (devPlayback != NULL) {
16877  streamFlags |= MA_PA_STREAM_DONT_MOVE;
16878  }
16879 
16880  error = ((ma_pa_stream_connect_playback_proc)pDevice->pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags, NULL, NULL);
16881  if (error != MA_PA_OK) {
16882  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio playback stream.", ma_result_from_pulse(error));
16883  goto on_error3;
16884  }
16885 
16886  result = ma_context_wait_for_pa_stream_to_connect__pulse(pDevice->pContext, (ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16887  if (result != MA_SUCCESS) {
16888  goto on_error3;
16889  }
16890 
16891 
16892  /* Internal format. */
16893  pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16894  if (pActualSS != NULL) {
16895  ss = *pActualSS;
16896  }
16897 
16898  pDescriptorPlayback->format = ma_format_from_pulse(ss.format);
16899  pDescriptorPlayback->channels = ss.channels;
16900  pDescriptorPlayback->sampleRate = ss.rate;
16901 
16902  /* Internal channel map. */
16903  pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16904  if (pActualCMap != NULL) {
16905  cmap = *pActualCMap;
16906  }
16907 
16908  for (iChannel = 0; iChannel < pDescriptorPlayback->channels; ++iChannel) {
16909  pDescriptorPlayback->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
16910  }
16911 
16912 
16913  /* Buffer. */
16914  pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pDevice->pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16915  if (pActualAttr != NULL) {
16916  attr = *pActualAttr;
16917  }
16918 
16919  pDescriptorPlayback->periodCount = attr.maxlength / attr.tlength;
16920  pDescriptorPlayback->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) / pDescriptorPlayback->periodCount;
16921  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDescriptorPlayback->periodSizeInFrames);
16922 
16923 
16924  /* Name. */
16925  devPlayback = ((ma_pa_stream_get_device_name_proc)pDevice->pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16926  if (devPlayback != NULL) {
16927  ma_pa_operation* pOP = ((ma_pa_context_get_sink_info_by_name_proc)pDevice->pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pDevice->pContext->pulse.pPulseContext, devPlayback, ma_device_sink_name_callback, pDevice);
16928  ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
16929  }
16930  }
16931 
16932 
16933  /*
16934  We need a ring buffer for handling duplex mode. We can use the main duplex ring buffer in the main
16935  part of the ma_device struct. We cannot, however, depend on ma_device_init() initializing this for
16936  us later on because that will only do it if it's a fully asynchronous backend - i.e. the
16937  onDeviceDataLoop callback is NULL, which is not the case for PulseAudio.
16938  */
16939  if (pConfig->deviceType == ma_device_type_duplex) {
16940  result = ma_duplex_rb_init(format, channels, sampleRate, pDescriptorCapture->sampleRate, pDescriptorCapture->periodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->duplexRB);
16941  if (result != MA_SUCCESS) {
16942  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to initialize ring buffer.", result);
16943  goto on_error4;
16944  }
16945  }
16946 
16947  return MA_SUCCESS;
16948 
16949 
16950 on_error4:
16951  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
16952  ((ma_pa_stream_disconnect_proc)pDevice->pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16953  }
16954 on_error3:
16955  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
16956  ((ma_pa_stream_unref_proc)pDevice->pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16957  }
16958 on_error2:
16959  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
16960  ((ma_pa_stream_disconnect_proc)pDevice->pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16961  }
16962 on_error1:
16963  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
16964  ((ma_pa_stream_unref_proc)pDevice->pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16965  }
16966 on_error0:
16967  return result;
16968 }
16969 
16970 
16971 static void ma_pulse_operation_complete_callback(ma_pa_stream* pStream, int success, void* pUserData)
16972 {
16973  ma_bool32* pIsSuccessful = (ma_bool32*)pUserData;
16974  MA_ASSERT(pIsSuccessful != NULL);
16975 
16976  *pIsSuccessful = (ma_bool32)success;
16977 
16978  (void)pStream; /* Unused. */
16979 }
16980 
16981 static ma_result ma_device__cork_stream__pulse(ma_device* pDevice, ma_device_type deviceType, int cork)
16982 {
16983  ma_context* pContext = pDevice->pContext;
16984  ma_bool32 wasSuccessful;
16985  ma_pa_stream* pStream;
16986  ma_pa_operation* pOP;
16987  ma_result result;
16988 
16989  /* This should not be called with a duplex device type. */
16990  if (deviceType == ma_device_type_duplex) {
16991  return MA_INVALID_ARGS;
16992  }
16993 
16994  wasSuccessful = MA_FALSE;
16995 
16996  pStream = (ma_pa_stream*)((deviceType == ma_device_type_capture) ? pDevice->pulse.pStreamCapture : pDevice->pulse.pStreamPlayback);
16997  MA_ASSERT(pStream != NULL);
16998 
16999  pOP = ((ma_pa_stream_cork_proc)pContext->pulse.pa_stream_cork)(pStream, cork, ma_pulse_operation_complete_callback, &wasSuccessful);
17000  if (pOP == NULL) {
17001  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to cork PulseAudio stream.", (cork == 0) ? MA_FAILED_TO_START_BACKEND_DEVICE : MA_FAILED_TO_STOP_BACKEND_DEVICE);
17002  }
17003 
17004  result = ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
17005  if (result != MA_SUCCESS) {
17006  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] An error occurred while waiting for the PulseAudio stream to cork.", result);
17007  }
17008 
17009  if (!wasSuccessful) {
17010  if (cork) {
17011  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to stop PulseAudio stream.", MA_FAILED_TO_STOP_BACKEND_DEVICE);
17012  } else {
17013  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to start PulseAudio stream.", MA_FAILED_TO_START_BACKEND_DEVICE);
17014  }
17015  }
17016 
17017  return MA_SUCCESS;
17018 }
17019 
17020 static ma_result ma_device_start__pulse(ma_device* pDevice)
17021 {
17022  ma_result result;
17023 
17024  MA_ASSERT(pDevice != NULL);
17025 
17026  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17027  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_capture, 0);
17028  if (result != MA_SUCCESS) {
17029  return result;
17030  }
17031  }
17032 
17033  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
17034  /* We need to fill some data before uncorking. Not doing this will result in the write callback never getting fired. */
17035  result = ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL);
17036  if (result != MA_SUCCESS) {
17037  return result; /* Failed to write data. Not sure what to do here... Just aborting. */
17038  }
17039 
17040  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 0);
17041  if (result != MA_SUCCESS) {
17042  return result;
17043  }
17044  }
17045 
17046  return MA_SUCCESS;
17047 }
17048 
17049 static ma_result ma_device_stop__pulse(ma_device* pDevice)
17050 {
17051  ma_result result;
17052  ma_bool32 wasSuccessful;
17053 
17054  MA_ASSERT(pDevice != NULL);
17055 
17056  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17057  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_capture, 1);
17058  if (result != MA_SUCCESS) {
17059  return result;
17060  }
17061  }
17062 
17063  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
17064  /* The stream needs to be drained if it's a playback device. */
17065  ma_pa_operation* pOP = ((ma_pa_stream_drain_proc)pDevice->pContext->pulse.pa_stream_drain)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_pulse_operation_complete_callback, &wasSuccessful);
17066  ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
17067 
17068  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 1);
17069  if (result != MA_SUCCESS) {
17070  return result;
17071  }
17072  }
17073 
17074  return MA_SUCCESS;
17075 }
17076 
17077 static ma_result ma_device_data_loop__pulse(ma_device* pDevice)
17078 {
17079  int resultPA;
17080 
17081  MA_ASSERT(pDevice != NULL);
17082 
17083  /* NOTE: Don't start the device here. It'll be done at a higher level. */
17084 
17085  /*
17086  All data is handled through callbacks. All we need to do is iterate over the main loop and let
17087  the callbacks deal with it.
17088  */
17089  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
17090  resultPA = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pContext->pulse.pMainLoop, 1, NULL);
17091  if (resultPA < 0) {
17092  break;
17093  }
17094  }
17095 
17096  /* NOTE: Don't stop the device here. It'll be done at a higher level. */
17097  return MA_SUCCESS;
17098 }
17099 
17100 static ma_result ma_device_data_loop_wakeup__pulse(ma_device* pDevice)
17101 {
17102  MA_ASSERT(pDevice != NULL);
17103 
17104  ((ma_pa_mainloop_wakeup_proc)pDevice->pContext->pulse.pa_mainloop_wakeup)((ma_pa_mainloop*)pDevice->pContext->pulse.pMainLoop);
17105 
17106  return MA_SUCCESS;
17107 }
17108 
17109 static ma_result ma_context_uninit__pulse(ma_context* pContext)
17110 {
17111  MA_ASSERT(pContext != NULL);
17112  MA_ASSERT(pContext->backend == ma_backend_pulseaudio);
17113 
17114  ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pContext->pulse.pPulseContext);
17115  ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pContext->pulse.pPulseContext);
17116  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pContext->pulse.pMainLoop);
17117 
17118 #ifndef MA_NO_RUNTIME_LINKING
17119  ma_dlclose(pContext, pContext->pulse.pulseSO);
17120 #endif
17121 
17122  return MA_SUCCESS;
17123 }
17124 
17125 static ma_result ma_context_init__pulse(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
17126 {
17127  ma_result result;
17128 #ifndef MA_NO_RUNTIME_LINKING
17129  const char* libpulseNames[] = {
17130  "libpulse.so",
17131  "libpulse.so.0"
17132  };
17133  size_t i;
17134 
17135  for (i = 0; i < ma_countof(libpulseNames); ++i) {
17136  pContext->pulse.pulseSO = ma_dlopen(pContext, libpulseNames[i]);
17137  if (pContext->pulse.pulseSO != NULL) {
17138  break;
17139  }
17140  }
17141 
17142  if (pContext->pulse.pulseSO == NULL) {
17143  return MA_NO_BACKEND;
17144  }
17145 
17146  pContext->pulse.pa_mainloop_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_new");
17147  pContext->pulse.pa_mainloop_free = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_free");
17148  pContext->pulse.pa_mainloop_quit = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_quit");
17149  pContext->pulse.pa_mainloop_get_api = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_get_api");
17150  pContext->pulse.pa_mainloop_iterate = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_iterate");
17151  pContext->pulse.pa_mainloop_wakeup = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_wakeup");
17152  pContext->pulse.pa_threaded_mainloop_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_new");
17153  pContext->pulse.pa_threaded_mainloop_free = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_free");
17154  pContext->pulse.pa_threaded_mainloop_start = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_start");
17155  pContext->pulse.pa_threaded_mainloop_stop = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_stop");
17156  pContext->pulse.pa_threaded_mainloop_lock = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_lock");
17157  pContext->pulse.pa_threaded_mainloop_unlock = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_unlock");
17158  pContext->pulse.pa_threaded_mainloop_wait = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_wait");
17159  pContext->pulse.pa_threaded_mainloop_signal = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_signal");
17160  pContext->pulse.pa_threaded_mainloop_accept = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_accept");
17161  pContext->pulse.pa_threaded_mainloop_get_retval = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_get_retval");
17162  pContext->pulse.pa_threaded_mainloop_get_api = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_get_api");
17163  pContext->pulse.pa_threaded_mainloop_in_thread = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_in_thread");
17164  pContext->pulse.pa_threaded_mainloop_set_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_set_name");
17165  pContext->pulse.pa_context_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_new");
17166  pContext->pulse.pa_context_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_unref");
17167  pContext->pulse.pa_context_connect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_connect");
17168  pContext->pulse.pa_context_disconnect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_disconnect");
17169  pContext->pulse.pa_context_set_state_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_set_state_callback");
17170  pContext->pulse.pa_context_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_state");
17171  pContext->pulse.pa_context_get_sink_info_list = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_sink_info_list");
17172  pContext->pulse.pa_context_get_source_info_list = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_source_info_list");
17173  pContext->pulse.pa_context_get_sink_info_by_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_sink_info_by_name");
17174  pContext->pulse.pa_context_get_source_info_by_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_source_info_by_name");
17175  pContext->pulse.pa_operation_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_operation_unref");
17176  pContext->pulse.pa_operation_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_operation_get_state");
17177  pContext->pulse.pa_channel_map_init_extend = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_init_extend");
17178  pContext->pulse.pa_channel_map_valid = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_valid");
17179  pContext->pulse.pa_channel_map_compatible = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_compatible");
17180  pContext->pulse.pa_stream_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_new");
17181  pContext->pulse.pa_stream_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_unref");
17182  pContext->pulse.pa_stream_connect_playback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_connect_playback");
17183  pContext->pulse.pa_stream_connect_record = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_connect_record");
17184  pContext->pulse.pa_stream_disconnect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_disconnect");
17185  pContext->pulse.pa_stream_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_state");
17186  pContext->pulse.pa_stream_get_sample_spec = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_sample_spec");
17187  pContext->pulse.pa_stream_get_channel_map = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_channel_map");
17188  pContext->pulse.pa_stream_get_buffer_attr = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_buffer_attr");
17189  pContext->pulse.pa_stream_set_buffer_attr = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_buffer_attr");
17190  pContext->pulse.pa_stream_get_device_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_device_name");
17191  pContext->pulse.pa_stream_set_write_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_write_callback");
17192  pContext->pulse.pa_stream_set_read_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_read_callback");
17193  pContext->pulse.pa_stream_set_suspended_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_suspended_callback");
17194  pContext->pulse.pa_stream_is_suspended = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_is_suspended");
17195  pContext->pulse.pa_stream_flush = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_flush");
17196  pContext->pulse.pa_stream_drain = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_drain");
17197  pContext->pulse.pa_stream_is_corked = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_is_corked");
17198  pContext->pulse.pa_stream_cork = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_cork");
17199  pContext->pulse.pa_stream_trigger = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_trigger");
17200  pContext->pulse.pa_stream_begin_write = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_begin_write");
17201  pContext->pulse.pa_stream_write = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_write");
17202  pContext->pulse.pa_stream_peek = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_peek");
17203  pContext->pulse.pa_stream_drop = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_drop");
17204  pContext->pulse.pa_stream_writable_size = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_writable_size");
17205  pContext->pulse.pa_stream_readable_size = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_readable_size");
17206 #else
17207  /* This strange assignment system is just for type safety. */
17208  ma_pa_mainloop_new_proc _pa_mainloop_new = pa_mainloop_new;
17209  ma_pa_mainloop_free_proc _pa_mainloop_free = pa_mainloop_free;
17210  ma_pa_mainloop_quit_proc _pa_mainloop_quit = pa_mainloop_quit;
17211  ma_pa_mainloop_get_api_proc _pa_mainloop_get_api = pa_mainloop_get_api;
17212  ma_pa_mainloop_iterate_proc _pa_mainloop_iterate = pa_mainloop_iterate;
17213  ma_pa_mainloop_wakeup_proc _pa_mainloop_wakeup = pa_mainloop_wakeup;
17214  ma_pa_threaded_mainloop_new_proc _pa_threaded_mainloop_new = pa_threaded_mainloop_new;
17215  ma_pa_threaded_mainloop_free_proc _pa_threaded_mainloop_free = pa_threaded_mainloop_free;
17216  ma_pa_threaded_mainloop_start_proc _pa_threaded_mainloop_start = pa_threaded_mainloop_start;
17217  ma_pa_threaded_mainloop_stop_proc _pa_threaded_mainloop_stop = pa_threaded_mainloop_stop;
17218  ma_pa_threaded_mainloop_lock_proc _pa_threaded_mainloop_lock = pa_threaded_mainloop_lock;
17219  ma_pa_threaded_mainloop_unlock_proc _pa_threaded_mainloop_unlock = pa_threaded_mainloop_unlock;
17220  ma_pa_threaded_mainloop_wait_proc _pa_threaded_mainloop_wait = pa_threaded_mainloop_wait;
17221  ma_pa_threaded_mainloop_signal_proc _pa_threaded_mainloop_signal = pa_threaded_mainloop_signal;
17222  ma_pa_threaded_mainloop_accept_proc _pa_threaded_mainloop_accept = pa_threaded_mainloop_accept;
17223  ma_pa_threaded_mainloop_get_retval_proc _pa_threaded_mainloop_get_retval = pa_threaded_mainloop_get_retval;
17224  ma_pa_threaded_mainloop_get_api_proc _pa_threaded_mainloop_get_api = pa_threaded_mainloop_get_api;
17225  ma_pa_threaded_mainloop_in_thread_proc _pa_threaded_mainloop_in_thread = pa_threaded_mainloop_in_thread;
17226  ma_pa_threaded_mainloop_set_name_proc _pa_threaded_mainloop_set_name = pa_threaded_mainloop_set_name;
17227  ma_pa_context_new_proc _pa_context_new = pa_context_new;
17228  ma_pa_context_unref_proc _pa_context_unref = pa_context_unref;
17229  ma_pa_context_connect_proc _pa_context_connect = pa_context_connect;
17230  ma_pa_context_disconnect_proc _pa_context_disconnect = pa_context_disconnect;
17231  ma_pa_context_set_state_callback_proc _pa_context_set_state_callback = pa_context_set_state_callback;
17232  ma_pa_context_get_state_proc _pa_context_get_state = pa_context_get_state;
17233  ma_pa_context_get_sink_info_list_proc _pa_context_get_sink_info_list = pa_context_get_sink_info_list;
17234  ma_pa_context_get_source_info_list_proc _pa_context_get_source_info_list = pa_context_get_source_info_list;
17235  ma_pa_context_get_sink_info_by_name_proc _pa_context_get_sink_info_by_name = pa_context_get_sink_info_by_name;
17236  ma_pa_context_get_source_info_by_name_proc _pa_context_get_source_info_by_name= pa_context_get_source_info_by_name;
17237  ma_pa_operation_unref_proc _pa_operation_unref = pa_operation_unref;
17238  ma_pa_operation_get_state_proc _pa_operation_get_state = pa_operation_get_state;
17239  ma_pa_channel_map_init_extend_proc _pa_channel_map_init_extend = pa_channel_map_init_extend;
17240  ma_pa_channel_map_valid_proc _pa_channel_map_valid = pa_channel_map_valid;
17241  ma_pa_channel_map_compatible_proc _pa_channel_map_compatible = pa_channel_map_compatible;
17242  ma_pa_stream_new_proc _pa_stream_new = pa_stream_new;
17243  ma_pa_stream_unref_proc _pa_stream_unref = pa_stream_unref;
17244  ma_pa_stream_connect_playback_proc _pa_stream_connect_playback = pa_stream_connect_playback;
17245  ma_pa_stream_connect_record_proc _pa_stream_connect_record = pa_stream_connect_record;
17246  ma_pa_stream_disconnect_proc _pa_stream_disconnect = pa_stream_disconnect;
17247  ma_pa_stream_get_state_proc _pa_stream_get_state = pa_stream_get_state;
17248  ma_pa_stream_get_sample_spec_proc _pa_stream_get_sample_spec = pa_stream_get_sample_spec;
17249  ma_pa_stream_get_channel_map_proc _pa_stream_get_channel_map = pa_stream_get_channel_map;
17250  ma_pa_stream_get_buffer_attr_proc _pa_stream_get_buffer_attr = pa_stream_get_buffer_attr;
17251  ma_pa_stream_set_buffer_attr_proc _pa_stream_set_buffer_attr = pa_stream_set_buffer_attr;
17252  ma_pa_stream_get_device_name_proc _pa_stream_get_device_name = pa_stream_get_device_name;
17253  ma_pa_stream_set_write_callback_proc _pa_stream_set_write_callback = pa_stream_set_write_callback;
17254  ma_pa_stream_set_read_callback_proc _pa_stream_set_read_callback = pa_stream_set_read_callback;
17255  ma_pa_stream_set_suspended_callback_proc _pa_stream_set_suspended_callback = pa_stream_set_suspended_callback;
17256  ma_pa_stream_is_suspended_proc _pa_stream_is_suspended = pa_stream_is_suspended;
17257  ma_pa_stream_flush_proc _pa_stream_flush = pa_stream_flush;
17258  ma_pa_stream_drain_proc _pa_stream_drain = pa_stream_drain;
17259  ma_pa_stream_is_corked_proc _pa_stream_is_corked = pa_stream_is_corked;
17260  ma_pa_stream_cork_proc _pa_stream_cork = pa_stream_cork;
17261  ma_pa_stream_trigger_proc _pa_stream_trigger = pa_stream_trigger;
17262  ma_pa_stream_begin_write_proc _pa_stream_begin_write = pa_stream_begin_write;
17263  ma_pa_stream_write_proc _pa_stream_write = pa_stream_write;
17264  ma_pa_stream_peek_proc _pa_stream_peek = pa_stream_peek;
17265  ma_pa_stream_drop_proc _pa_stream_drop = pa_stream_drop;
17266  ma_pa_stream_writable_size_proc _pa_stream_writable_size = pa_stream_writable_size;
17267  ma_pa_stream_readable_size_proc _pa_stream_readable_size = pa_stream_readable_size;
17268 
17269  pContext->pulse.pa_mainloop_new = (ma_proc)_pa_mainloop_new;
17270  pContext->pulse.pa_mainloop_free = (ma_proc)_pa_mainloop_free;
17271  pContext->pulse.pa_mainloop_quit = (ma_proc)_pa_mainloop_quit;
17272  pContext->pulse.pa_mainloop_get_api = (ma_proc)_pa_mainloop_get_api;
17273  pContext->pulse.pa_mainloop_iterate = (ma_proc)_pa_mainloop_iterate;
17274  pContext->pulse.pa_mainloop_wakeup = (ma_proc)_pa_mainloop_wakeup;
17275  pContext->pulse.pa_threaded_mainloop_new = (ma_proc)_pa_threaded_mainloop_new;
17276  pContext->pulse.pa_threaded_mainloop_free = (ma_proc)_pa_threaded_mainloop_free;
17277  pContext->pulse.pa_threaded_mainloop_start = (ma_proc)_pa_threaded_mainloop_start;
17278  pContext->pulse.pa_threaded_mainloop_stop = (ma_proc)_pa_threaded_mainloop_stop;
17279  pContext->pulse.pa_threaded_mainloop_lock = (ma_proc)_pa_threaded_mainloop_lock;
17280  pContext->pulse.pa_threaded_mainloop_unlock = (ma_proc)_pa_threaded_mainloop_unlock;
17281  pContext->pulse.pa_threaded_mainloop_wait = (ma_proc)_pa_threaded_mainloop_wait;
17282  pContext->pulse.pa_threaded_mainloop_signal = (ma_proc)_pa_threaded_mainloop_signal;
17283  pContext->pulse.pa_threaded_mainloop_accept = (ma_proc)_pa_threaded_mainloop_accept;
17284  pContext->pulse.pa_threaded_mainloop_get_retval = (ma_proc)_pa_threaded_mainloop_get_retval;
17285  pContext->pulse.pa_threaded_mainloop_get_api = (ma_proc)_pa_threaded_mainloop_get_api;
17286  pContext->pulse.pa_threaded_mainloop_in_thread = (ma_proc)_pa_threaded_mainloop_in_thread;
17287  pContext->pulse.pa_threaded_mainloop_set_name = (ma_proc)_pa_threaded_mainloop_set_name;
17288  pContext->pulse.pa_context_new = (ma_proc)_pa_context_new;
17289  pContext->pulse.pa_context_unref = (ma_proc)_pa_context_unref;
17290  pContext->pulse.pa_context_connect = (ma_proc)_pa_context_connect;
17291  pContext->pulse.pa_context_disconnect = (ma_proc)_pa_context_disconnect;
17292  pContext->pulse.pa_context_set_state_callback = (ma_proc)_pa_context_set_state_callback;
17293  pContext->pulse.pa_context_get_state = (ma_proc)_pa_context_get_state;
17294  pContext->pulse.pa_context_get_sink_info_list = (ma_proc)_pa_context_get_sink_info_list;
17295  pContext->pulse.pa_context_get_source_info_list = (ma_proc)_pa_context_get_source_info_list;
17296  pContext->pulse.pa_context_get_sink_info_by_name = (ma_proc)_pa_context_get_sink_info_by_name;
17297  pContext->pulse.pa_context_get_source_info_by_name = (ma_proc)_pa_context_get_source_info_by_name;
17298  pContext->pulse.pa_operation_unref = (ma_proc)_pa_operation_unref;
17299  pContext->pulse.pa_operation_get_state = (ma_proc)_pa_operation_get_state;
17300  pContext->pulse.pa_channel_map_init_extend = (ma_proc)_pa_channel_map_init_extend;
17301  pContext->pulse.pa_channel_map_valid = (ma_proc)_pa_channel_map_valid;
17302  pContext->pulse.pa_channel_map_compatible = (ma_proc)_pa_channel_map_compatible;
17303  pContext->pulse.pa_stream_new = (ma_proc)_pa_stream_new;
17304  pContext->pulse.pa_stream_unref = (ma_proc)_pa_stream_unref;
17305  pContext->pulse.pa_stream_connect_playback = (ma_proc)_pa_stream_connect_playback;
17306  pContext->pulse.pa_stream_connect_record = (ma_proc)_pa_stream_connect_record;
17307  pContext->pulse.pa_stream_disconnect = (ma_proc)_pa_stream_disconnect;
17308  pContext->pulse.pa_stream_get_state = (ma_proc)_pa_stream_get_state;
17309  pContext->pulse.pa_stream_get_sample_spec = (ma_proc)_pa_stream_get_sample_spec;
17310  pContext->pulse.pa_stream_get_channel_map = (ma_proc)_pa_stream_get_channel_map;
17311  pContext->pulse.pa_stream_get_buffer_attr = (ma_proc)_pa_stream_get_buffer_attr;
17312  pContext->pulse.pa_stream_set_buffer_attr = (ma_proc)_pa_stream_set_buffer_attr;
17313  pContext->pulse.pa_stream_get_device_name = (ma_proc)_pa_stream_get_device_name;
17314  pContext->pulse.pa_stream_set_write_callback = (ma_proc)_pa_stream_set_write_callback;
17315  pContext->pulse.pa_stream_set_read_callback = (ma_proc)_pa_stream_set_read_callback;
17316  pContext->pulse.pa_stream_set_suspended_callback = (ma_proc)_pa_stream_set_suspended_callback;
17317  pContext->pulse.pa_stream_is_suspended = (ma_proc)_pa_stream_is_suspended;
17318  pContext->pulse.pa_stream_flush = (ma_proc)_pa_stream_flush;
17319  pContext->pulse.pa_stream_drain = (ma_proc)_pa_stream_drain;
17320  pContext->pulse.pa_stream_is_corked = (ma_proc)_pa_stream_is_corked;
17321  pContext->pulse.pa_stream_cork = (ma_proc)_pa_stream_cork;
17322  pContext->pulse.pa_stream_trigger = (ma_proc)_pa_stream_trigger;
17323  pContext->pulse.pa_stream_begin_write = (ma_proc)_pa_stream_begin_write;
17324  pContext->pulse.pa_stream_write = (ma_proc)_pa_stream_write;
17325  pContext->pulse.pa_stream_peek = (ma_proc)_pa_stream_peek;
17326  pContext->pulse.pa_stream_drop = (ma_proc)_pa_stream_drop;
17327  pContext->pulse.pa_stream_writable_size = (ma_proc)_pa_stream_writable_size;
17328  pContext->pulse.pa_stream_readable_size = (ma_proc)_pa_stream_readable_size;
17329 #endif
17330 
17331  /* The PulseAudio context maps well to miniaudio's notion of a context. The pa_context object will be initialized as part of the ma_context. */
17332  pContext->pulse.pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
17333  if (pContext->pulse.pMainLoop == NULL) {
17334  result = ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create mainloop.", MA_FAILED_TO_INIT_BACKEND);
17335  #ifndef MA_NO_RUNTIME_LINKING
17336  ma_dlclose(pContext, pContext->pulse.pulseSO);
17337  #endif
17338  return result;
17339  }
17340 
17341  pContext->pulse.pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)((ma_pa_mainloop*)pContext->pulse.pMainLoop), pConfig->pulse.pApplicationName);
17342  if (pContext->pulse.pPulseContext == NULL) {
17343  result = ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio context.", MA_FAILED_TO_INIT_BACKEND);
17344  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pContext->pulse.pMainLoop));
17345  #ifndef MA_NO_RUNTIME_LINKING
17346  ma_dlclose(pContext, pContext->pulse.pulseSO);
17347  #endif
17348  return result;
17349  }
17350 
17351  /* Now we need to connect to the context. Everything is asynchronous so we need to wait for it to connect before returning. */
17352  result = ma_result_from_pulse(((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pContext->pulse.pPulseContext, pConfig->pulse.pServerName, (pConfig->pulse.tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN, NULL));
17353  if (result != MA_SUCCESS) {
17354  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio context.", result);
17355  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pContext->pulse.pMainLoop));
17356  #ifndef MA_NO_RUNTIME_LINKING
17357  ma_dlclose(pContext, pContext->pulse.pulseSO);
17358  #endif
17359  return result;
17360  }
17361 
17362  /* Since ma_context_init() runs synchronously we need to wait for the PulseAudio context to connect before we return. */
17363  result = ma_context_wait_for_pa_context_to_connect__pulse(pContext);
17364  if (result != MA_SUCCESS) {
17365  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pContext->pulse.pMainLoop));
17366  #ifndef MA_NO_RUNTIME_LINKING
17367  ma_dlclose(pContext, pContext->pulse.pulseSO);
17368  #endif
17369  return result;
17370  }
17371 
17372 
17373  /* With pa_mainloop we run a synchronous backend, but we implement our own main loop. */
17374  pCallbacks->onContextInit = ma_context_init__pulse;
17375  pCallbacks->onContextUninit = ma_context_uninit__pulse;
17376  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__pulse;
17377  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__pulse;
17378  pCallbacks->onDeviceInit = ma_device_init__pulse;
17379  pCallbacks->onDeviceUninit = ma_device_uninit__pulse;
17380  pCallbacks->onDeviceStart = ma_device_start__pulse;
17381  pCallbacks->onDeviceStop = ma_device_stop__pulse;
17382  pCallbacks->onDeviceRead = NULL; /* Not used because we're implementing onDeviceDataLoop. */
17383  pCallbacks->onDeviceWrite = NULL; /* Not used because we're implementing onDeviceDataLoop. */
17384  pCallbacks->onDeviceDataLoop = ma_device_data_loop__pulse;
17385  pCallbacks->onDeviceDataLoopWakeup = ma_device_data_loop_wakeup__pulse;
17386 
17387  return MA_SUCCESS;
17388 }
17389 #endif
17390 
17391 
17392 /******************************************************************************
17393 
17394 JACK Backend
17395 
17396 ******************************************************************************/
17397 #ifdef MA_HAS_JACK
17398 
17399 /* It is assumed jack.h is available when compile-time linking is being used. */
17400 #ifdef MA_NO_RUNTIME_LINKING
17401 #include <jack/jack.h>
17402 
17403 typedef jack_nframes_t ma_jack_nframes_t;
17404 typedef jack_options_t ma_jack_options_t;
17405 typedef jack_status_t ma_jack_status_t;
17406 typedef jack_client_t ma_jack_client_t;
17407 typedef jack_port_t ma_jack_port_t;
17408 typedef JackProcessCallback ma_JackProcessCallback;
17409 typedef JackBufferSizeCallback ma_JackBufferSizeCallback;
17410 typedef JackShutdownCallback ma_JackShutdownCallback;
17411 #define MA_JACK_DEFAULT_AUDIO_TYPE JACK_DEFAULT_AUDIO_TYPE
17412 #define ma_JackNoStartServer JackNoStartServer
17413 #define ma_JackPortIsInput JackPortIsInput
17414 #define ma_JackPortIsOutput JackPortIsOutput
17415 #define ma_JackPortIsPhysical JackPortIsPhysical
17416 #else
17417 typedef ma_uint32 ma_jack_nframes_t;
17418 typedef int ma_jack_options_t;
17419 typedef int ma_jack_status_t;
17420 typedef struct ma_jack_client_t ma_jack_client_t;
17421 typedef struct ma_jack_port_t ma_jack_port_t;
17422 typedef int (* ma_JackProcessCallback) (ma_jack_nframes_t nframes, void* arg);
17423 typedef int (* ma_JackBufferSizeCallback)(ma_jack_nframes_t nframes, void* arg);
17424 typedef void (* ma_JackShutdownCallback) (void* arg);
17425 #define MA_JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio"
17426 #define ma_JackNoStartServer 1
17427 #define ma_JackPortIsInput 1
17428 #define ma_JackPortIsOutput 2
17429 #define ma_JackPortIsPhysical 4
17430 #endif
17431 
17432 typedef ma_jack_client_t* (* ma_jack_client_open_proc) (const char* client_name, ma_jack_options_t options, ma_jack_status_t* status, ...);
17433 typedef int (* ma_jack_client_close_proc) (ma_jack_client_t* client);
17434 typedef int (* ma_jack_client_name_size_proc) (void);
17435 typedef int (* ma_jack_set_process_callback_proc) (ma_jack_client_t* client, ma_JackProcessCallback process_callback, void* arg);
17436 typedef int (* ma_jack_set_buffer_size_callback_proc)(ma_jack_client_t* client, ma_JackBufferSizeCallback bufsize_callback, void* arg);
17437 typedef void (* ma_jack_on_shutdown_proc) (ma_jack_client_t* client, ma_JackShutdownCallback function, void* arg);
17438 typedef ma_jack_nframes_t (* ma_jack_get_sample_rate_proc) (ma_jack_client_t* client);
17439 typedef ma_jack_nframes_t (* ma_jack_get_buffer_size_proc) (ma_jack_client_t* client);
17440 typedef const char** (* ma_jack_get_ports_proc) (ma_jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags);
17441 typedef int (* ma_jack_activate_proc) (ma_jack_client_t* client);
17442 typedef int (* ma_jack_deactivate_proc) (ma_jack_client_t* client);
17443 typedef int (* ma_jack_connect_proc) (ma_jack_client_t* client, const char* source_port, const char* destination_port);
17444 typedef ma_jack_port_t* (* ma_jack_port_register_proc) (ma_jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size);
17445 typedef const char* (* ma_jack_port_name_proc) (const ma_jack_port_t* port);
17446 typedef void* (* ma_jack_port_get_buffer_proc) (ma_jack_port_t* port, ma_jack_nframes_t nframes);
17447 typedef void (* ma_jack_free_proc) (void* ptr);
17448 
17449 static ma_result ma_context_open_client__jack(ma_context* pContext, ma_jack_client_t** ppClient)
17450 {
17451  size_t maxClientNameSize;
17452  char clientName[256];
17453  ma_jack_status_t status;
17454  ma_jack_client_t* pClient;
17455 
17456  MA_ASSERT(pContext != NULL);
17457  MA_ASSERT(ppClient != NULL);
17458 
17459  if (ppClient) {
17460  *ppClient = NULL;
17461  }
17462 
17463  maxClientNameSize = ((ma_jack_client_name_size_proc)pContext->jack.jack_client_name_size)(); /* Includes null terminator. */
17464  ma_strncpy_s(clientName, ma_min(sizeof(clientName), maxClientNameSize), (pContext->jack.pClientName != NULL) ? pContext->jack.pClientName : "miniaudio", (size_t)-1);
17465 
17466  pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? 0 : ma_JackNoStartServer, &status, NULL);
17467  if (pClient == NULL) {
17469  }
17470 
17471  if (ppClient) {
17472  *ppClient = pClient;
17473  }
17474 
17475  return MA_SUCCESS;
17476 }
17477 
17478 
17479 static ma_result ma_context_enumerate_devices__jack(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
17480 {
17481  ma_bool32 cbResult = MA_TRUE;
17482 
17483  MA_ASSERT(pContext != NULL);
17484  MA_ASSERT(callback != NULL);
17485 
17486  /* Playback. */
17487  if (cbResult) {
17488  ma_device_info deviceInfo;
17489  MA_ZERO_OBJECT(&deviceInfo);
17490  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
17491  deviceInfo.isDefault = MA_TRUE; /* JACK only uses default devices. */
17492  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
17493  }
17494 
17495  /* Capture. */
17496  if (cbResult) {
17497  ma_device_info deviceInfo;
17498  MA_ZERO_OBJECT(&deviceInfo);
17499  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
17500  deviceInfo.isDefault = MA_TRUE; /* JACK only uses default devices. */
17501  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
17502  }
17503 
17504  (void)cbResult; /* For silencing a static analysis warning. */
17505 
17506  return MA_SUCCESS;
17507 }
17508 
17509 static ma_result ma_context_get_device_info__jack(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
17510 {
17511  ma_jack_client_t* pClient;
17512  ma_result result;
17513  const char** ppPorts;
17514 
17515  MA_ASSERT(pContext != NULL);
17516 
17517  if (pDeviceID != NULL && pDeviceID->jack != 0) {
17518  return MA_NO_DEVICE; /* Don't know the device. */
17519  }
17520 
17521  /* Name / Description */
17522  if (deviceType == ma_device_type_playback) {
17523  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
17524  } else {
17525  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
17526  }
17527 
17528  /* Jack only uses default devices. */
17529  pDeviceInfo->isDefault = MA_TRUE;
17530 
17531  /* Jack only supports f32 and has a specific channel count and sample rate. */
17532  pDeviceInfo->nativeDataFormats[0].format = ma_format_f32;
17533 
17534  /* The channel count and sample rate can only be determined by opening the device. */
17535  result = ma_context_open_client__jack(pContext, &pClient);
17536  if (result != MA_SUCCESS) {
17537  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[JACK] Failed to open client.", result);
17538  }
17539 
17540  pDeviceInfo->nativeDataFormats[0].sampleRate = ((ma_jack_get_sample_rate_proc)pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pClient);
17541  pDeviceInfo->nativeDataFormats[0].channels = 0;
17542 
17543  ppPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ((deviceType == ma_device_type_playback) ? ma_JackPortIsInput : ma_JackPortIsOutput));
17544  if (ppPorts == NULL) {
17545  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pClient);
17546  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17547  }
17548 
17549  while (ppPorts[pDeviceInfo->nativeDataFormats[0].channels] != NULL) {
17550  pDeviceInfo->nativeDataFormats[0].channels += 1;
17551  }
17552 
17553  pDeviceInfo->nativeDataFormats[0].flags = 0;
17554  pDeviceInfo->nativeDataFormatCount = 1;
17555 
17556  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppPorts);
17557  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pClient);
17558 
17559  (void)pContext;
17560  return MA_SUCCESS;
17561 }
17562 
17563 
17564 static ma_result ma_device_uninit__jack(ma_device* pDevice)
17565 {
17566  ma_context* pContext;
17567 
17568  MA_ASSERT(pDevice != NULL);
17569 
17570  pContext = pDevice->pContext;
17571  MA_ASSERT(pContext != NULL);
17572 
17573  if (pDevice->jack.pClient != NULL) {
17574  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pDevice->jack.pClient);
17575  }
17576 
17577  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17578  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferCapture, &pDevice->pContext->allocationCallbacks);
17579  }
17580 
17581  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
17582  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferPlayback, &pDevice->pContext->allocationCallbacks);
17583  }
17584 
17585  return MA_SUCCESS;
17586 }
17587 
17588 static void ma_device__jack_shutdown_callback(void* pUserData)
17589 {
17590  /* JACK died. Stop the device. */
17591  ma_device* pDevice = (ma_device*)pUserData;
17592  MA_ASSERT(pDevice != NULL);
17593 
17594  ma_device_stop(pDevice);
17595 }
17596 
17597 static int ma_device__jack_buffer_size_callback(ma_jack_nframes_t frameCount, void* pUserData)
17598 {
17599  ma_device* pDevice = (ma_device*)pUserData;
17600  MA_ASSERT(pDevice != NULL);
17601 
17602  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17603  size_t newBufferSize = frameCount * (pDevice->capture.internalChannels * ma_get_bytes_per_sample(pDevice->capture.internalFormat));
17604  float* pNewBuffer = (float*)ma__calloc_from_callbacks(newBufferSize, &pDevice->pContext->allocationCallbacks);
17605  if (pNewBuffer == NULL) {
17606  return MA_OUT_OF_MEMORY;
17607  }
17608 
17609  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferCapture, &pDevice->pContext->allocationCallbacks);
17610 
17611  pDevice->jack.pIntermediaryBufferCapture = pNewBuffer;
17612  pDevice->playback.internalPeriodSizeInFrames = frameCount;
17613  }
17614 
17615  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
17616  size_t newBufferSize = frameCount * (pDevice->playback.internalChannels * ma_get_bytes_per_sample(pDevice->playback.internalFormat));
17617  float* pNewBuffer = (float*)ma__calloc_from_callbacks(newBufferSize, &pDevice->pContext->allocationCallbacks);
17618  if (pNewBuffer == NULL) {
17619  return MA_OUT_OF_MEMORY;
17620  }
17621 
17622  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferPlayback, &pDevice->pContext->allocationCallbacks);
17623 
17624  pDevice->jack.pIntermediaryBufferPlayback = pNewBuffer;
17625  pDevice->playback.internalPeriodSizeInFrames = frameCount;
17626  }
17627 
17628  return 0;
17629 }
17630 
17631 static int ma_device__jack_process_callback(ma_jack_nframes_t frameCount, void* pUserData)
17632 {
17633  ma_device* pDevice;
17634  ma_context* pContext;
17635  ma_uint32 iChannel;
17636 
17637  pDevice = (ma_device*)pUserData;
17638  MA_ASSERT(pDevice != NULL);
17639 
17640  pContext = pDevice->pContext;
17641  MA_ASSERT(pContext != NULL);
17642 
17643  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17644  /* Channels need to be interleaved. */
17645  for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
17646  const float* pSrc = (const float*)((ma_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsCapture[iChannel], frameCount);
17647  if (pSrc != NULL) {
17648  float* pDst = pDevice->jack.pIntermediaryBufferCapture + iChannel;
17649  ma_jack_nframes_t iFrame;
17650  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
17651  *pDst = *pSrc;
17652 
17653  pDst += pDevice->capture.internalChannels;
17654  pSrc += 1;
17655  }
17656  }
17657  }
17658 
17659  ma_device_handle_backend_data_callback(pDevice, NULL, pDevice->jack.pIntermediaryBufferCapture, frameCount);
17660  }
17661 
17662  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
17663  ma_device_handle_backend_data_callback(pDevice, pDevice->jack.pIntermediaryBufferPlayback, NULL, frameCount);
17664 
17665  /* Channels need to be deinterleaved. */
17666  for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
17667  float* pDst = (float*)((ma_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[iChannel], frameCount);
17668  if (pDst != NULL) {
17669  const float* pSrc = pDevice->jack.pIntermediaryBufferPlayback + iChannel;
17670  ma_jack_nframes_t iFrame;
17671  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
17672  *pDst = *pSrc;
17673 
17674  pDst += 1;
17675  pSrc += pDevice->playback.internalChannels;
17676  }
17677  }
17678  }
17679  }
17680 
17681  return 0;
17682 }
17683 
17684 static ma_result ma_device_init__jack(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
17685 {
17686  ma_result result;
17687  ma_uint32 periodSizeInFrames;
17688 
17689  MA_ASSERT(pConfig != NULL);
17690  MA_ASSERT(pDevice != NULL);
17691 
17692  if (pConfig->deviceType == ma_device_type_loopback) {
17694  }
17695 
17696  /* Only supporting default devices with JACK. */
17697  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->pDeviceID != NULL && pDescriptorPlayback->pDeviceID->jack != 0) ||
17698  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->pDeviceID != NULL && pDescriptorCapture->pDeviceID->jack != 0)) {
17699  return MA_NO_DEVICE;
17700  }
17701 
17702  /* No exclusive mode with the JACK backend. */
17703  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
17704  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
17706  }
17707 
17708  /* Open the client. */
17709  result = ma_context_open_client__jack(pDevice->pContext, (ma_jack_client_t**)&pDevice->jack.pClient);
17710  if (result != MA_SUCCESS) {
17711  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to open client.", result);
17712  }
17713 
17714  /* Callbacks. */
17715  if (((ma_jack_set_process_callback_proc)pDevice->pContext->jack.jack_set_process_callback)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_process_callback, pDevice) != 0) {
17716  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to set process callback.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17717  }
17718  if (((ma_jack_set_buffer_size_callback_proc)pDevice->pContext->jack.jack_set_buffer_size_callback)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_buffer_size_callback, pDevice) != 0) {
17719  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to set buffer size callback.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17720  }
17721 
17722  ((ma_jack_on_shutdown_proc)pDevice->pContext->jack.jack_on_shutdown)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_shutdown_callback, pDevice);
17723 
17724 
17725  /* The buffer size in frames can change. */
17726  periodSizeInFrames = ((ma_jack_get_buffer_size_proc)pDevice->pContext->jack.jack_get_buffer_size)((ma_jack_client_t*)pDevice->jack.pClient);
17727 
17728  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
17729  const char** ppPorts;
17730 
17731  pDescriptorCapture->format = ma_format_f32;
17732  pDescriptorCapture->channels = 0;
17733  pDescriptorCapture->sampleRate = ((ma_jack_get_sample_rate_proc)pDevice->pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
17734  ma_get_standard_channel_map(ma_standard_channel_map_alsa, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
17735 
17736  ppPorts = ((ma_jack_get_ports_proc)pDevice->pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsOutput);
17737  if (ppPorts == NULL) {
17738  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17739  }
17740 
17741  while (ppPorts[pDescriptorCapture->channels] != NULL) {
17742  char name[64];
17743  ma_strcpy_s(name, sizeof(name), "capture");
17744  ma_itoa_s((int)pDescriptorCapture->channels, name+7, sizeof(name)-7, 10); /* 7 = length of "capture" */
17745 
17746  pDevice->jack.pPortsCapture[pDescriptorCapture->channels] = ((ma_jack_port_register_proc)pDevice->pContext->jack.jack_port_register)((ma_jack_client_t*)pDevice->jack.pClient, name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsInput, 0);
17747  if (pDevice->jack.pPortsCapture[pDescriptorCapture->channels] == NULL) {
17748  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
17749  ma_device_uninit__jack(pDevice);
17750  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17751  }
17752 
17753  pDescriptorCapture->channels += 1;
17754  }
17755 
17756  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
17757 
17758  pDescriptorCapture->periodSizeInFrames = periodSizeInFrames;
17759  pDescriptorCapture->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */
17760 
17761  pDevice->jack.pIntermediaryBufferCapture = (float*)ma__calloc_from_callbacks(pDescriptorCapture->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels), &pDevice->pContext->allocationCallbacks);
17762  if (pDevice->jack.pIntermediaryBufferCapture == NULL) {
17763  ma_device_uninit__jack(pDevice);
17764  return MA_OUT_OF_MEMORY;
17765  }
17766  }
17767 
17768  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
17769  const char** ppPorts;
17770 
17771  pDescriptorPlayback->format = ma_format_f32;
17772  pDescriptorPlayback->channels = 0;
17773  pDescriptorPlayback->sampleRate = ((ma_jack_get_sample_rate_proc)pDevice->pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
17774  ma_get_standard_channel_map(ma_standard_channel_map_alsa, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
17775 
17776  ppPorts = ((ma_jack_get_ports_proc)pDevice->pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsInput);
17777  if (ppPorts == NULL) {
17778  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17779  }
17780 
17781  while (ppPorts[pDescriptorPlayback->channels] != NULL) {
17782  char name[64];
17783  ma_strcpy_s(name, sizeof(name), "playback");
17784  ma_itoa_s((int)pDescriptorPlayback->channels, name+8, sizeof(name)-8, 10); /* 8 = length of "playback" */
17785 
17786  pDevice->jack.pPortsPlayback[pDescriptorPlayback->channels] = ((ma_jack_port_register_proc)pDevice->pContext->jack.jack_port_register)((ma_jack_client_t*)pDevice->jack.pClient, name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsOutput, 0);
17787  if (pDevice->jack.pPortsPlayback[pDescriptorPlayback->channels] == NULL) {
17788  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
17789  ma_device_uninit__jack(pDevice);
17790  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17791  }
17792 
17793  pDescriptorPlayback->channels += 1;
17794  }
17795 
17796  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
17797 
17798  pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
17799  pDescriptorPlayback->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */
17800 
17801  pDevice->jack.pIntermediaryBufferPlayback = (float*)ma__calloc_from_callbacks(pDescriptorPlayback->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels), &pDevice->pContext->allocationCallbacks);
17802  if (pDevice->jack.pIntermediaryBufferPlayback == NULL) {
17803  ma_device_uninit__jack(pDevice);
17804  return MA_OUT_OF_MEMORY;
17805  }
17806  }
17807 
17808  return MA_SUCCESS;
17809 }
17810 
17811 
17812 static ma_result ma_device_start__jack(ma_device* pDevice)
17813 {
17814  ma_context* pContext = pDevice->pContext;
17815  int resultJACK;
17816  size_t i;
17817 
17818  resultJACK = ((ma_jack_activate_proc)pContext->jack.jack_activate)((ma_jack_client_t*)pDevice->jack.pClient);
17819  if (resultJACK != 0) {
17820  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to activate the JACK client.", MA_FAILED_TO_START_BACKEND_DEVICE);
17821  }
17822 
17823  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17824  const char** ppServerPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsOutput);
17825  if (ppServerPorts == NULL) {
17826  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17827  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to retrieve physical ports.", MA_ERROR);
17828  }
17829 
17830  for (i = 0; ppServerPorts[i] != NULL; ++i) {
17831  const char* pServerPort = ppServerPorts[i];
17832  const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsCapture[i]);
17833 
17834  resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pServerPort, pClientPort);
17835  if (resultJACK != 0) {
17836  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
17837  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17838  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to connect ports.", MA_ERROR);
17839  }
17840  }
17841 
17842  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
17843  }
17844 
17845  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
17846  const char** ppServerPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient, NULL, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsPhysical | ma_JackPortIsInput);
17847  if (ppServerPorts == NULL) {
17848  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17849  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to retrieve physical ports.", MA_ERROR);
17850  }
17851 
17852  for (i = 0; ppServerPorts[i] != NULL; ++i) {
17853  const char* pServerPort = ppServerPorts[i];
17854  const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[i]);
17855 
17856  resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pClientPort, pServerPort);
17857  if (resultJACK != 0) {
17858  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
17859  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17860  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to connect ports.", MA_ERROR);
17861  }
17862  }
17863 
17864  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
17865  }
17866 
17867  return MA_SUCCESS;
17868 }
17869 
17870 static ma_result ma_device_stop__jack(ma_device* pDevice)
17871 {
17872  ma_context* pContext = pDevice->pContext;
17873  ma_stop_proc onStop;
17874 
17875  if (((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient) != 0) {
17876  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] An error occurred when deactivating the JACK client.", MA_ERROR);
17877  }
17878 
17879  onStop = pDevice->onStop;
17880  if (onStop) {
17881  onStop(pDevice);
17882  }
17883 
17884  return MA_SUCCESS;
17885 }
17886 
17887 
17888 static ma_result ma_context_uninit__jack(ma_context* pContext)
17889 {
17890  MA_ASSERT(pContext != NULL);
17891  MA_ASSERT(pContext->backend == ma_backend_jack);
17892 
17893  ma_free(pContext->jack.pClientName, &pContext->allocationCallbacks);
17894  pContext->jack.pClientName = NULL;
17895 
17896 #ifndef MA_NO_RUNTIME_LINKING
17897  ma_dlclose(pContext, pContext->jack.jackSO);
17898 #endif
17899 
17900  return MA_SUCCESS;
17901 }
17902 
17903 static ma_result ma_context_init__jack(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
17904 {
17905 #ifndef MA_NO_RUNTIME_LINKING
17906  const char* libjackNames[] = {
17907 #ifdef MA_WIN32
17908  "libjack.dll",
17909  "libjack64.dll"
17910 #else
17911  "libjack.so",
17912  "libjack.so.0"
17913 #endif
17914  };
17915  size_t i;
17916 
17917  for (i = 0; i < ma_countof(libjackNames); ++i) {
17918  pContext->jack.jackSO = ma_dlopen(pContext, libjackNames[i]);
17919  if (pContext->jack.jackSO != NULL) {
17920  break;
17921  }
17922  }
17923 
17924  if (pContext->jack.jackSO == NULL) {
17925  return MA_NO_BACKEND;
17926  }
17927 
17928  pContext->jack.jack_client_open = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_open");
17929  pContext->jack.jack_client_close = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_close");
17930  pContext->jack.jack_client_name_size = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_name_size");
17931  pContext->jack.jack_set_process_callback = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_set_process_callback");
17932  pContext->jack.jack_set_buffer_size_callback = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_set_buffer_size_callback");
17933  pContext->jack.jack_on_shutdown = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_on_shutdown");
17934  pContext->jack.jack_get_sample_rate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_sample_rate");
17935  pContext->jack.jack_get_buffer_size = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_buffer_size");
17936  pContext->jack.jack_get_ports = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_ports");
17937  pContext->jack.jack_activate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_activate");
17938  pContext->jack.jack_deactivate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_deactivate");
17939  pContext->jack.jack_connect = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_connect");
17940  pContext->jack.jack_port_register = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_register");
17941  pContext->jack.jack_port_name = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_name");
17942  pContext->jack.jack_port_get_buffer = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_get_buffer");
17943  pContext->jack.jack_free = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_free");
17944 #else
17945  /*
17946  This strange assignment system is here just to ensure type safety of miniaudio's function pointer
17947  types. If anything differs slightly the compiler should throw a warning.
17948  */
17949  ma_jack_client_open_proc _jack_client_open = jack_client_open;
17950  ma_jack_client_close_proc _jack_client_close = jack_client_close;
17951  ma_jack_client_name_size_proc _jack_client_name_size = jack_client_name_size;
17952  ma_jack_set_process_callback_proc _jack_set_process_callback = jack_set_process_callback;
17953  ma_jack_set_buffer_size_callback_proc _jack_set_buffer_size_callback = jack_set_buffer_size_callback;
17954  ma_jack_on_shutdown_proc _jack_on_shutdown = jack_on_shutdown;
17955  ma_jack_get_sample_rate_proc _jack_get_sample_rate = jack_get_sample_rate;
17956  ma_jack_get_buffer_size_proc _jack_get_buffer_size = jack_get_buffer_size;
17957  ma_jack_get_ports_proc _jack_get_ports = jack_get_ports;
17958  ma_jack_activate_proc _jack_activate = jack_activate;
17959  ma_jack_deactivate_proc _jack_deactivate = jack_deactivate;
17960  ma_jack_connect_proc _jack_connect = jack_connect;
17961  ma_jack_port_register_proc _jack_port_register = jack_port_register;
17962  ma_jack_port_name_proc _jack_port_name = jack_port_name;
17963  ma_jack_port_get_buffer_proc _jack_port_get_buffer = jack_port_get_buffer;
17964  ma_jack_free_proc _jack_free = jack_free;
17965 
17966  pContext->jack.jack_client_open = (ma_proc)_jack_client_open;
17967  pContext->jack.jack_client_close = (ma_proc)_jack_client_close;
17968  pContext->jack.jack_client_name_size = (ma_proc)_jack_client_name_size;
17969  pContext->jack.jack_set_process_callback = (ma_proc)_jack_set_process_callback;
17970  pContext->jack.jack_set_buffer_size_callback = (ma_proc)_jack_set_buffer_size_callback;
17971  pContext->jack.jack_on_shutdown = (ma_proc)_jack_on_shutdown;
17972  pContext->jack.jack_get_sample_rate = (ma_proc)_jack_get_sample_rate;
17973  pContext->jack.jack_get_buffer_size = (ma_proc)_jack_get_buffer_size;
17974  pContext->jack.jack_get_ports = (ma_proc)_jack_get_ports;
17975  pContext->jack.jack_activate = (ma_proc)_jack_activate;
17976  pContext->jack.jack_deactivate = (ma_proc)_jack_deactivate;
17977  pContext->jack.jack_connect = (ma_proc)_jack_connect;
17978  pContext->jack.jack_port_register = (ma_proc)_jack_port_register;
17979  pContext->jack.jack_port_name = (ma_proc)_jack_port_name;
17980  pContext->jack.jack_port_get_buffer = (ma_proc)_jack_port_get_buffer;
17981  pContext->jack.jack_free = (ma_proc)_jack_free;
17982 #endif
17983 
17984  if (pConfig->jack.pClientName != NULL) {
17985  pContext->jack.pClientName = ma_copy_string(pConfig->jack.pClientName, &pContext->allocationCallbacks);
17986  }
17987  pContext->jack.tryStartServer = pConfig->jack.tryStartServer;
17988 
17989  /*
17990  Getting here means the JACK library is installed, but it doesn't necessarily mean it's usable. We need to quickly test this by connecting
17991  a temporary client.
17992  */
17993  {
17994  ma_jack_client_t* pDummyClient;
17995  ma_result result = ma_context_open_client__jack(pContext, &pDummyClient);
17996  if (result != MA_SUCCESS) {
17997  ma_free(pContext->jack.pClientName, &pContext->allocationCallbacks);
17998  #ifndef MA_NO_RUNTIME_LINKING
17999  ma_dlclose(pContext, pContext->jack.jackSO);
18000  #endif
18001  return MA_NO_BACKEND;
18002  }
18003 
18004  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pDummyClient);
18005  }
18006 
18007 
18008  pCallbacks->onContextInit = ma_context_init__jack;
18009  pCallbacks->onContextUninit = ma_context_uninit__jack;
18010  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__jack;
18011  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__jack;
18012  pCallbacks->onDeviceInit = ma_device_init__jack;
18013  pCallbacks->onDeviceUninit = ma_device_uninit__jack;
18014  pCallbacks->onDeviceStart = ma_device_start__jack;
18015  pCallbacks->onDeviceStop = ma_device_stop__jack;
18016  pCallbacks->onDeviceRead = NULL; /* Not used because JACK is asynchronous. */
18017  pCallbacks->onDeviceWrite = NULL; /* Not used because JACK is asynchronous. */
18018  pCallbacks->onDeviceDataLoop = NULL; /* Not used because JACK is asynchronous. */
18019 
18020  return MA_SUCCESS;
18021 }
18022 #endif /* JACK */
18023 
18024 
18025 
18026 /******************************************************************************
18027 
18028 Core Audio Backend
18029 
18030 References
18031 ==========
18032 - Technical Note TN2091: Device input using the HAL Output Audio Unit
18033  https://developer.apple.com/library/archive/technotes/tn2091/_index.html
18034 
18035 ******************************************************************************/
18036 #ifdef MA_HAS_COREAUDIO
18037 #include <TargetConditionals.h>
18038 
18039 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1
18040  #define MA_APPLE_MOBILE
18041  #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
18042  #define MA_APPLE_TV
18043  #endif
18044  #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
18045  #define MA_APPLE_WATCH
18046  #endif
18047 #else
18048  #define MA_APPLE_DESKTOP
18049 #endif
18050 
18051 #if defined(MA_APPLE_DESKTOP)
18052 #include <CoreAudio/CoreAudio.h>
18053 #else
18054 #include <AVFoundation/AVFoundation.h>
18055 #endif
18056 
18057 #include <AudioToolbox/AudioToolbox.h>
18058 
18059 /* CoreFoundation */
18060 typedef Boolean (* ma_CFStringGetCString_proc)(CFStringRef theString, char* buffer, CFIndex bufferSize, CFStringEncoding encoding);
18061 typedef void (* ma_CFRelease_proc)(CFTypeRef cf);
18062 
18063 /* CoreAudio */
18064 #if defined(MA_APPLE_DESKTOP)
18065 typedef OSStatus (* ma_AudioObjectGetPropertyData_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* ioDataSize, void* outData);
18066 typedef OSStatus (* ma_AudioObjectGetPropertyDataSize_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* outDataSize);
18067 typedef OSStatus (* ma_AudioObjectSetPropertyData_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData);
18068 typedef OSStatus (* ma_AudioObjectAddPropertyListener_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener, void* inClientData);
18069 typedef OSStatus (* ma_AudioObjectRemovePropertyListener_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener, void* inClientData);
18070 #endif
18071 
18072 /* AudioToolbox */
18073 typedef AudioComponent (* ma_AudioComponentFindNext_proc)(AudioComponent inComponent, const AudioComponentDescription* inDesc);
18074 typedef OSStatus (* ma_AudioComponentInstanceDispose_proc)(AudioComponentInstance inInstance);
18075 typedef OSStatus (* ma_AudioComponentInstanceNew_proc)(AudioComponent inComponent, AudioComponentInstance* outInstance);
18076 typedef OSStatus (* ma_AudioOutputUnitStart_proc)(AudioUnit inUnit);
18077 typedef OSStatus (* ma_AudioOutputUnitStop_proc)(AudioUnit inUnit);
18078 typedef OSStatus (* ma_AudioUnitAddPropertyListener_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc, void* inProcUserData);
18079 typedef OSStatus (* ma_AudioUnitGetPropertyInfo_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32* outDataSize, Boolean* outWriteable);
18080 typedef OSStatus (* ma_AudioUnitGetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData, UInt32* ioDataSize);
18081 typedef OSStatus (* ma_AudioUnitSetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void* inData, UInt32 inDataSize);
18082 typedef OSStatus (* ma_AudioUnitInitialize_proc)(AudioUnit inUnit);
18083 typedef OSStatus (* ma_AudioUnitRender_proc)(AudioUnit inUnit, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData);
18084 
18085 
18086 #define MA_COREAUDIO_OUTPUT_BUS 0
18087 #define MA_COREAUDIO_INPUT_BUS 1
18088 
18089 #if defined(MA_APPLE_DESKTOP)
18090 static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_type deviceType, ma_bool32 disposePreviousAudioUnit);
18091 #endif
18092 
18093 /*
18094 Core Audio
18095 
18096 So far, Core Audio has been the worst backend to work with due to being both unintuitive and having almost no documentation
18097 apart from comments in the headers (which admittedly are quite good). For my own purposes, and for anybody out there whose
18098 needing to figure out how this darn thing works, I'm going to outline a few things here.
18099 
18100 Since miniaudio is a fairly low-level API, one of the things it needs is control over specific devices, and it needs to be
18101 able to identify whether or not it can be used as playback and/or capture. The AudioObject API is the only one I've seen
18102 that supports this level of detail. There was some public domain sample code I stumbled across that used the AudioComponent
18103 and AudioUnit APIs, but I couldn't see anything that gave low-level control over device selection and capabilities (the
18104 distinction between playback and capture in particular). Therefore, miniaudio is using the AudioObject API.
18105 
18106 Most (all?) functions in the AudioObject API take a AudioObjectID as it's input. This is the device identifier. When
18107 retrieving global information, such as the device list, you use kAudioObjectSystemObject. When retrieving device-specific
18108 data, you pass in the ID for that device. In order to retrieve device-specific IDs you need to enumerate over each of the
18109 devices. This is done using the AudioObjectGetPropertyDataSize() and AudioObjectGetPropertyData() APIs which seem to be
18110 the central APIs for retrieving information about the system and specific devices.
18111 
18112 To use the AudioObjectGetPropertyData() API you need to use the notion of a property address. A property address is a
18113 structure with three variables and is used to identify which property you are getting or setting. The first is the "selector"
18114 which is basically the specific property that you're wanting to retrieve or set. The second is the "scope", which is
18115 typically set to kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeInput for input-specific properties and
18116 kAudioObjectPropertyScopeOutput for output-specific properties. The last is the "element" which is always set to
18117 kAudioObjectPropertyElementMaster in miniaudio's case. I don't know of any cases where this would be set to anything different.
18118 
18119 Back to the earlier issue of device retrieval, you first use the AudioObjectGetPropertyDataSize() API to retrieve the size
18120 of the raw data which is just a list of AudioDeviceID's. You use the kAudioObjectSystemObject AudioObjectID, and a property
18121 address with the kAudioHardwarePropertyDevices selector and the kAudioObjectPropertyScopeGlobal scope. Once you have the
18122 size, allocate a block of memory of that size and then call AudioObjectGetPropertyData(). The data is just a list of
18123 AudioDeviceID's so just do "dataSize/sizeof(AudioDeviceID)" to know the device count.
18124 */
18125 
18126 static ma_result ma_result_from_OSStatus(OSStatus status)
18127 {
18128  switch (status)
18129  {
18130  case noErr: return MA_SUCCESS;
18131  #if defined(MA_APPLE_DESKTOP)
18132  case kAudioHardwareNotRunningError: return MA_DEVICE_NOT_STARTED;
18133  case kAudioHardwareUnspecifiedError: return MA_ERROR;
18134  case kAudioHardwareUnknownPropertyError: return MA_INVALID_ARGS;
18135  case kAudioHardwareBadPropertySizeError: return MA_INVALID_OPERATION;
18136  case kAudioHardwareIllegalOperationError: return MA_INVALID_OPERATION;
18137  case kAudioHardwareBadObjectError: return MA_INVALID_ARGS;
18138  case kAudioHardwareBadDeviceError: return MA_INVALID_ARGS;
18139  case kAudioHardwareBadStreamError: return MA_INVALID_ARGS;
18140  case kAudioHardwareUnsupportedOperationError: return MA_INVALID_OPERATION;
18141  case kAudioDeviceUnsupportedFormatError: return MA_FORMAT_NOT_SUPPORTED;
18142  case kAudioDevicePermissionsError: return MA_ACCESS_DENIED;
18143  #endif
18144  default: return MA_ERROR;
18145  }
18146 }
18147 
18148 #if 0
18149 static ma_channel ma_channel_from_AudioChannelBitmap(AudioChannelBitmap bit)
18150 {
18151  switch (bit)
18152  {
18153  case kAudioChannelBit_Left: return MA_CHANNEL_LEFT;
18154  case kAudioChannelBit_Right: return MA_CHANNEL_RIGHT;
18155  case kAudioChannelBit_Center: return MA_CHANNEL_FRONT_CENTER;
18156  case kAudioChannelBit_LFEScreen: return MA_CHANNEL_LFE;
18157  case kAudioChannelBit_LeftSurround: return MA_CHANNEL_BACK_LEFT;
18158  case kAudioChannelBit_RightSurround: return MA_CHANNEL_BACK_RIGHT;
18159  case kAudioChannelBit_LeftCenter: return MA_CHANNEL_FRONT_LEFT_CENTER;
18160  case kAudioChannelBit_RightCenter: return MA_CHANNEL_FRONT_RIGHT_CENTER;
18161  case kAudioChannelBit_CenterSurround: return MA_CHANNEL_BACK_CENTER;
18162  case kAudioChannelBit_LeftSurroundDirect: return MA_CHANNEL_SIDE_LEFT;
18163  case kAudioChannelBit_RightSurroundDirect: return MA_CHANNEL_SIDE_RIGHT;
18164  case kAudioChannelBit_TopCenterSurround: return MA_CHANNEL_TOP_CENTER;
18165  case kAudioChannelBit_VerticalHeightLeft: return MA_CHANNEL_TOP_FRONT_LEFT;
18166  case kAudioChannelBit_VerticalHeightCenter: return MA_CHANNEL_TOP_FRONT_CENTER;
18167  case kAudioChannelBit_VerticalHeightRight: return MA_CHANNEL_TOP_FRONT_RIGHT;
18168  case kAudioChannelBit_TopBackLeft: return MA_CHANNEL_TOP_BACK_LEFT;
18169  case kAudioChannelBit_TopBackCenter: return MA_CHANNEL_TOP_BACK_CENTER;
18170  case kAudioChannelBit_TopBackRight: return MA_CHANNEL_TOP_BACK_RIGHT;
18171  default: return MA_CHANNEL_NONE;
18172  }
18173 }
18174 #endif
18175 
18176 static ma_result ma_format_from_AudioStreamBasicDescription(const AudioStreamBasicDescription* pDescription, ma_format* pFormatOut)
18177 {
18178  MA_ASSERT(pDescription != NULL);
18179  MA_ASSERT(pFormatOut != NULL);
18180 
18181  *pFormatOut = ma_format_unknown; /* Safety. */
18182 
18183  /* There's a few things miniaudio doesn't support. */
18184  if (pDescription->mFormatID != kAudioFormatLinearPCM) {
18185  return MA_FORMAT_NOT_SUPPORTED;
18186  }
18187 
18188  /* We don't support any non-packed formats that are aligned high. */
18189  if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) != 0) {
18190  return MA_FORMAT_NOT_SUPPORTED;
18191  }
18192 
18193  /* Only supporting native-endian. */
18194  if ((ma_is_little_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) || (ma_is_big_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) == 0)) {
18195  return MA_FORMAT_NOT_SUPPORTED;
18196  }
18197 
18198  /* We are not currently supporting non-interleaved formats (this will be added in a future version of miniaudio). */
18199  /*if ((pDescription->mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) {
18200  return MA_FORMAT_NOT_SUPPORTED;
18201  }*/
18202 
18203  if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0) {
18204  if (pDescription->mBitsPerChannel == 32) {
18205  *pFormatOut = ma_format_f32;
18206  return MA_SUCCESS;
18207  }
18208  } else {
18209  if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) != 0) {
18210  if (pDescription->mBitsPerChannel == 16) {
18211  *pFormatOut = ma_format_s16;
18212  return MA_SUCCESS;
18213  } else if (pDescription->mBitsPerChannel == 24) {
18214  if (pDescription->mBytesPerFrame == (pDescription->mBitsPerChannel/8 * pDescription->mChannelsPerFrame)) {
18215  *pFormatOut = ma_format_s24;
18216  return MA_SUCCESS;
18217  } else {
18218  if (pDescription->mBytesPerFrame/pDescription->mChannelsPerFrame == sizeof(ma_int32)) {
18219  /* TODO: Implement ma_format_s24_32. */
18221  /*return MA_SUCCESS;*/
18222  return MA_FORMAT_NOT_SUPPORTED;
18223  }
18224  }
18225  } else if (pDescription->mBitsPerChannel == 32) {
18226  *pFormatOut = ma_format_s32;
18227  return MA_SUCCESS;
18228  }
18229  } else {
18230  if (pDescription->mBitsPerChannel == 8) {
18231  *pFormatOut = ma_format_u8;
18232  return MA_SUCCESS;
18233  }
18234  }
18235  }
18236 
18237  /* Getting here means the format is not supported. */
18238  return MA_FORMAT_NOT_SUPPORTED;
18239 }
18240 
18241 #if defined(MA_APPLE_DESKTOP)
18242 static ma_channel ma_channel_from_AudioChannelLabel(AudioChannelLabel label)
18243 {
18244  switch (label)
18245  {
18246  case kAudioChannelLabel_Unknown: return MA_CHANNEL_NONE;
18247  case kAudioChannelLabel_Unused: return MA_CHANNEL_NONE;
18248  case kAudioChannelLabel_UseCoordinates: return MA_CHANNEL_NONE;
18249  case kAudioChannelLabel_Left: return MA_CHANNEL_LEFT;
18250  case kAudioChannelLabel_Right: return MA_CHANNEL_RIGHT;
18251  case kAudioChannelLabel_Center: return MA_CHANNEL_FRONT_CENTER;
18252  case kAudioChannelLabel_LFEScreen: return MA_CHANNEL_LFE;
18253  case kAudioChannelLabel_LeftSurround: return MA_CHANNEL_BACK_LEFT;
18254  case kAudioChannelLabel_RightSurround: return MA_CHANNEL_BACK_RIGHT;
18255  case kAudioChannelLabel_LeftCenter: return MA_CHANNEL_FRONT_LEFT_CENTER;
18256  case kAudioChannelLabel_RightCenter: return MA_CHANNEL_FRONT_RIGHT_CENTER;
18257  case kAudioChannelLabel_CenterSurround: return MA_CHANNEL_BACK_CENTER;
18258  case kAudioChannelLabel_LeftSurroundDirect: return MA_CHANNEL_SIDE_LEFT;
18259  case kAudioChannelLabel_RightSurroundDirect: return MA_CHANNEL_SIDE_RIGHT;
18260  case kAudioChannelLabel_TopCenterSurround: return MA_CHANNEL_TOP_CENTER;
18261  case kAudioChannelLabel_VerticalHeightLeft: return MA_CHANNEL_TOP_FRONT_LEFT;
18262  case kAudioChannelLabel_VerticalHeightCenter: return MA_CHANNEL_TOP_FRONT_CENTER;
18263  case kAudioChannelLabel_VerticalHeightRight: return MA_CHANNEL_TOP_FRONT_RIGHT;
18264  case kAudioChannelLabel_TopBackLeft: return MA_CHANNEL_TOP_BACK_LEFT;
18265  case kAudioChannelLabel_TopBackCenter: return MA_CHANNEL_TOP_BACK_CENTER;
18266  case kAudioChannelLabel_TopBackRight: return MA_CHANNEL_TOP_BACK_RIGHT;
18267  case kAudioChannelLabel_RearSurroundLeft: return MA_CHANNEL_BACK_LEFT;
18268  case kAudioChannelLabel_RearSurroundRight: return MA_CHANNEL_BACK_RIGHT;
18269  case kAudioChannelLabel_LeftWide: return MA_CHANNEL_SIDE_LEFT;
18270  case kAudioChannelLabel_RightWide: return MA_CHANNEL_SIDE_RIGHT;
18271  case kAudioChannelLabel_LFE2: return MA_CHANNEL_LFE;
18272  case kAudioChannelLabel_LeftTotal: return MA_CHANNEL_LEFT;
18273  case kAudioChannelLabel_RightTotal: return MA_CHANNEL_RIGHT;
18274  case kAudioChannelLabel_HearingImpaired: return MA_CHANNEL_NONE;
18275  case kAudioChannelLabel_Narration: return MA_CHANNEL_MONO;
18276  case kAudioChannelLabel_Mono: return MA_CHANNEL_MONO;
18277  case kAudioChannelLabel_DialogCentricMix: return MA_CHANNEL_MONO;
18278  case kAudioChannelLabel_CenterSurroundDirect: return MA_CHANNEL_BACK_CENTER;
18279  case kAudioChannelLabel_Haptic: return MA_CHANNEL_NONE;
18280  case kAudioChannelLabel_Ambisonic_W: return MA_CHANNEL_NONE;
18281  case kAudioChannelLabel_Ambisonic_X: return MA_CHANNEL_NONE;
18282  case kAudioChannelLabel_Ambisonic_Y: return MA_CHANNEL_NONE;
18283  case kAudioChannelLabel_Ambisonic_Z: return MA_CHANNEL_NONE;
18284  case kAudioChannelLabel_MS_Mid: return MA_CHANNEL_LEFT;
18285  case kAudioChannelLabel_MS_Side: return MA_CHANNEL_RIGHT;
18286  case kAudioChannelLabel_XY_X: return MA_CHANNEL_LEFT;
18287  case kAudioChannelLabel_XY_Y: return MA_CHANNEL_RIGHT;
18288  case kAudioChannelLabel_HeadphonesLeft: return MA_CHANNEL_LEFT;
18289  case kAudioChannelLabel_HeadphonesRight: return MA_CHANNEL_RIGHT;
18290  case kAudioChannelLabel_ClickTrack: return MA_CHANNEL_NONE;
18291  case kAudioChannelLabel_ForeignLanguage: return MA_CHANNEL_NONE;
18292  case kAudioChannelLabel_Discrete: return MA_CHANNEL_NONE;
18293  case kAudioChannelLabel_Discrete_0: return MA_CHANNEL_AUX_0;
18294  case kAudioChannelLabel_Discrete_1: return MA_CHANNEL_AUX_1;
18295  case kAudioChannelLabel_Discrete_2: return MA_CHANNEL_AUX_2;
18296  case kAudioChannelLabel_Discrete_3: return MA_CHANNEL_AUX_3;
18297  case kAudioChannelLabel_Discrete_4: return MA_CHANNEL_AUX_4;
18298  case kAudioChannelLabel_Discrete_5: return MA_CHANNEL_AUX_5;
18299  case kAudioChannelLabel_Discrete_6: return MA_CHANNEL_AUX_6;
18300  case kAudioChannelLabel_Discrete_7: return MA_CHANNEL_AUX_7;
18301  case kAudioChannelLabel_Discrete_8: return MA_CHANNEL_AUX_8;
18302  case kAudioChannelLabel_Discrete_9: return MA_CHANNEL_AUX_9;
18303  case kAudioChannelLabel_Discrete_10: return MA_CHANNEL_AUX_10;
18304  case kAudioChannelLabel_Discrete_11: return MA_CHANNEL_AUX_11;
18305  case kAudioChannelLabel_Discrete_12: return MA_CHANNEL_AUX_12;
18306  case kAudioChannelLabel_Discrete_13: return MA_CHANNEL_AUX_13;
18307  case kAudioChannelLabel_Discrete_14: return MA_CHANNEL_AUX_14;
18308  case kAudioChannelLabel_Discrete_15: return MA_CHANNEL_AUX_15;
18309  case kAudioChannelLabel_Discrete_65535: return MA_CHANNEL_NONE;
18310 
18311  #if 0 /* Introduced in a later version of macOS. */
18312  case kAudioChannelLabel_HOA_ACN: return MA_CHANNEL_NONE;
18313  case kAudioChannelLabel_HOA_ACN_0: return MA_CHANNEL_AUX_0;
18314  case kAudioChannelLabel_HOA_ACN_1: return MA_CHANNEL_AUX_1;
18315  case kAudioChannelLabel_HOA_ACN_2: return MA_CHANNEL_AUX_2;
18316  case kAudioChannelLabel_HOA_ACN_3: return MA_CHANNEL_AUX_3;
18317  case kAudioChannelLabel_HOA_ACN_4: return MA_CHANNEL_AUX_4;
18318  case kAudioChannelLabel_HOA_ACN_5: return MA_CHANNEL_AUX_5;
18319  case kAudioChannelLabel_HOA_ACN_6: return MA_CHANNEL_AUX_6;
18320  case kAudioChannelLabel_HOA_ACN_7: return MA_CHANNEL_AUX_7;
18321  case kAudioChannelLabel_HOA_ACN_8: return MA_CHANNEL_AUX_8;
18322  case kAudioChannelLabel_HOA_ACN_9: return MA_CHANNEL_AUX_9;
18323  case kAudioChannelLabel_HOA_ACN_10: return MA_CHANNEL_AUX_10;
18324  case kAudioChannelLabel_HOA_ACN_11: return MA_CHANNEL_AUX_11;
18325  case kAudioChannelLabel_HOA_ACN_12: return MA_CHANNEL_AUX_12;
18326  case kAudioChannelLabel_HOA_ACN_13: return MA_CHANNEL_AUX_13;
18327  case kAudioChannelLabel_HOA_ACN_14: return MA_CHANNEL_AUX_14;
18328  case kAudioChannelLabel_HOA_ACN_15: return MA_CHANNEL_AUX_15;
18329  case kAudioChannelLabel_HOA_ACN_65024: return MA_CHANNEL_NONE;
18330  #endif
18331 
18332  default: return MA_CHANNEL_NONE;
18333  }
18334 }
18335 
18336 static ma_result ma_get_channel_map_from_AudioChannelLayout(AudioChannelLayout* pChannelLayout, ma_channel* pChannelMap, size_t channelMapCap)
18337 {
18338  MA_ASSERT(pChannelLayout != NULL);
18339 
18340  if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
18341  UInt32 iChannel;
18342  for (iChannel = 0; iChannel < pChannelLayout->mNumberChannelDescriptions && iChannel < channelMapCap; ++iChannel) {
18343  pChannelMap[iChannel] = ma_channel_from_AudioChannelLabel(pChannelLayout->mChannelDescriptions[iChannel].mChannelLabel);
18344  }
18345  } else
18346 #if 0
18347  if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
18348  /* This is the same kind of system that's used by Windows audio APIs. */
18349  UInt32 iChannel = 0;
18350  UInt32 iBit;
18351  AudioChannelBitmap bitmap = pChannelLayout->mChannelBitmap;
18352  for (iBit = 0; iBit < 32 && iChannel < channelMapCap; ++iBit) {
18353  AudioChannelBitmap bit = bitmap & (1 << iBit);
18354  if (bit != 0) {
18355  pChannelMap[iChannel++] = ma_channel_from_AudioChannelBit(bit);
18356  }
18357  }
18358  } else
18359 #endif
18360  {
18361  /*
18362  Need to use the tag to determine the channel map. For now I'm just assuming a default channel map, but later on this should
18363  be updated to determine the mapping based on the tag.
18364  */
18365  UInt32 channelCount;
18366 
18367  /* Our channel map retrieval APIs below take 32-bit integers, so we'll want to clamp the channel map capacity. */
18368  if (channelMapCap > 0xFFFFFFFF) {
18369  channelMapCap = 0xFFFFFFFF;
18370  }
18371 
18372  channelCount = ma_min(AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag), (UInt32)channelMapCap);
18373 
18374  switch (pChannelLayout->mChannelLayoutTag)
18375  {
18376  case kAudioChannelLayoutTag_Mono:
18377  case kAudioChannelLayoutTag_Stereo:
18378  case kAudioChannelLayoutTag_StereoHeadphones:
18379  case kAudioChannelLayoutTag_MatrixStereo:
18380  case kAudioChannelLayoutTag_MidSide:
18381  case kAudioChannelLayoutTag_XY:
18382  case kAudioChannelLayoutTag_Binaural:
18383  case kAudioChannelLayoutTag_Ambisonic_B_Format:
18384  {
18386  } break;
18387 
18388  case kAudioChannelLayoutTag_Octagonal:
18389  {
18390  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
18391  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
18392  } /* Intentional fallthrough. */
18393  case kAudioChannelLayoutTag_Hexagonal:
18394  {
18395  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
18396  } /* Intentional fallthrough. */
18397  case kAudioChannelLayoutTag_Pentagonal:
18398  {
18399  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
18400  } /* Intentional fallghrough. */
18401  case kAudioChannelLayoutTag_Quadraphonic:
18402  {
18403  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
18404  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
18405  pChannelMap[1] = MA_CHANNEL_RIGHT;
18406  pChannelMap[0] = MA_CHANNEL_LEFT;
18407  } break;
18408 
18409  /* TODO: Add support for more tags here. */
18410 
18411  default:
18412  {
18414  } break;
18415  }
18416  }
18417 
18418  return MA_SUCCESS;
18419 }
18420 
18421 static ma_result ma_get_device_object_ids__coreaudio(ma_context* pContext, UInt32* pDeviceCount, AudioObjectID** ppDeviceObjectIDs) /* NOTE: Free the returned buffer with ma_free(). */
18422 {
18423  AudioObjectPropertyAddress propAddressDevices;
18424  UInt32 deviceObjectsDataSize;
18425  OSStatus status;
18426  AudioObjectID* pDeviceObjectIDs;
18427 
18428  MA_ASSERT(pContext != NULL);
18429  MA_ASSERT(pDeviceCount != NULL);
18430  MA_ASSERT(ppDeviceObjectIDs != NULL);
18431 
18432  /* Safety. */
18433  *pDeviceCount = 0;
18434  *ppDeviceObjectIDs = NULL;
18435 
18436  propAddressDevices.mSelector = kAudioHardwarePropertyDevices;
18437  propAddressDevices.mScope = kAudioObjectPropertyScopeGlobal;
18438  propAddressDevices.mElement = kAudioObjectPropertyElementMaster;
18439 
18440  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(kAudioObjectSystemObject, &propAddressDevices, 0, NULL, &deviceObjectsDataSize);
18441  if (status != noErr) {
18442  return ma_result_from_OSStatus(status);
18443  }
18444 
18445  pDeviceObjectIDs = (AudioObjectID*)ma_malloc(deviceObjectsDataSize, &pContext->allocationCallbacks);
18446  if (pDeviceObjectIDs == NULL) {
18447  return MA_OUT_OF_MEMORY;
18448  }
18449 
18450  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDevices, 0, NULL, &deviceObjectsDataSize, pDeviceObjectIDs);
18451  if (status != noErr) {
18452  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
18453  return ma_result_from_OSStatus(status);
18454  }
18455 
18456  *pDeviceCount = deviceObjectsDataSize / sizeof(AudioObjectID);
18457  *ppDeviceObjectIDs = pDeviceObjectIDs;
18458 
18459  return MA_SUCCESS;
18460 }
18461 
18462 static ma_result ma_get_AudioObject_uid_as_CFStringRef(ma_context* pContext, AudioObjectID objectID, CFStringRef* pUID)
18463 {
18464  AudioObjectPropertyAddress propAddress;
18465  UInt32 dataSize;
18466  OSStatus status;
18467 
18468  MA_ASSERT(pContext != NULL);
18469 
18470  propAddress.mSelector = kAudioDevicePropertyDeviceUID;
18471  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
18472  propAddress.mElement = kAudioObjectPropertyElementMaster;
18473 
18474  dataSize = sizeof(*pUID);
18475  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0, NULL, &dataSize, pUID);
18476  if (status != noErr) {
18477  return ma_result_from_OSStatus(status);
18478  }
18479 
18480  return MA_SUCCESS;
18481 }
18482 
18483 static ma_result ma_get_AudioObject_uid(ma_context* pContext, AudioObjectID objectID, size_t bufferSize, char* bufferOut)
18484 {
18485  CFStringRef uid;
18486  ma_result result;
18487 
18488  MA_ASSERT(pContext != NULL);
18489 
18490  result = ma_get_AudioObject_uid_as_CFStringRef(pContext, objectID, &uid);
18491  if (result != MA_SUCCESS) {
18492  return result;
18493  }
18494 
18495  if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(uid, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
18496  return MA_ERROR;
18497  }
18498 
18499  ((ma_CFRelease_proc)pContext->coreaudio.CFRelease)(uid);
18500  return MA_SUCCESS;
18501 }
18502 
18503 static ma_result ma_get_AudioObject_name(ma_context* pContext, AudioObjectID objectID, size_t bufferSize, char* bufferOut)
18504 {
18505  AudioObjectPropertyAddress propAddress;
18506  CFStringRef deviceName = NULL;
18507  UInt32 dataSize;
18508  OSStatus status;
18509 
18510  MA_ASSERT(pContext != NULL);
18511 
18512  propAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
18513  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
18514  propAddress.mElement = kAudioObjectPropertyElementMaster;
18515 
18516  dataSize = sizeof(deviceName);
18517  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0, NULL, &dataSize, &deviceName);
18518  if (status != noErr) {
18519  return ma_result_from_OSStatus(status);
18520  }
18521 
18522  if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(deviceName, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
18523  return MA_ERROR;
18524  }
18525 
18526  ((ma_CFRelease_proc)pContext->coreaudio.CFRelease)(deviceName);
18527  return MA_SUCCESS;
18528 }
18529 
18530 static ma_bool32 ma_does_AudioObject_support_scope(ma_context* pContext, AudioObjectID deviceObjectID, AudioObjectPropertyScope scope)
18531 {
18532  AudioObjectPropertyAddress propAddress;
18533  UInt32 dataSize;
18534  OSStatus status;
18535  AudioBufferList* pBufferList;
18536  ma_bool32 isSupported;
18537 
18538  MA_ASSERT(pContext != NULL);
18539 
18540  /* To know whether or not a device is an input device we need ot look at the stream configuration. If it has an output channel it's a playback device. */
18541  propAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
18542  propAddress.mScope = scope;
18543  propAddress.mElement = kAudioObjectPropertyElementMaster;
18544 
18545  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
18546  if (status != noErr) {
18547  return MA_FALSE;
18548  }
18549 
18550  pBufferList = (AudioBufferList*)ma__malloc_from_callbacks(dataSize, &pContext->allocationCallbacks);
18551  if (pBufferList == NULL) {
18552  return MA_FALSE; /* Out of memory. */
18553  }
18554 
18555  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pBufferList);
18556  if (status != noErr) {
18557  ma__free_from_callbacks(pBufferList, &pContext->allocationCallbacks);
18558  return MA_FALSE;
18559  }
18560 
18561  isSupported = MA_FALSE;
18562  if (pBufferList->mNumberBuffers > 0) {
18563  isSupported = MA_TRUE;
18564  }
18565 
18566  ma__free_from_callbacks(pBufferList, &pContext->allocationCallbacks);
18567  return isSupported;
18568 }
18569 
18570 static ma_bool32 ma_does_AudioObject_support_playback(ma_context* pContext, AudioObjectID deviceObjectID)
18571 {
18572  return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeOutput);
18573 }
18574 
18575 static ma_bool32 ma_does_AudioObject_support_capture(ma_context* pContext, AudioObjectID deviceObjectID)
18576 {
18577  return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeInput);
18578 }
18579 
18580 
18581 static ma_result ma_get_AudioObject_stream_descriptions(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, UInt32* pDescriptionCount, AudioStreamRangedDescription** ppDescriptions) /* NOTE: Free the returned pointer with ma_free(). */
18582 {
18583  AudioObjectPropertyAddress propAddress;
18584  UInt32 dataSize;
18585  OSStatus status;
18586  AudioStreamRangedDescription* pDescriptions;
18587 
18588  MA_ASSERT(pContext != NULL);
18589  MA_ASSERT(pDescriptionCount != NULL);
18590  MA_ASSERT(ppDescriptions != NULL);
18591 
18592  /*
18593  TODO: Experiment with kAudioStreamPropertyAvailablePhysicalFormats instead of (or in addition to) kAudioStreamPropertyAvailableVirtualFormats. My
18594  MacBook Pro uses s24/32 format, however, which miniaudio does not currently support.
18595  */
18596  propAddress.mSelector = kAudioStreamPropertyAvailableVirtualFormats; /*kAudioStreamPropertyAvailablePhysicalFormats;*/
18597  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18598  propAddress.mElement = kAudioObjectPropertyElementMaster;
18599 
18600  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
18601  if (status != noErr) {
18602  return ma_result_from_OSStatus(status);
18603  }
18604 
18605  pDescriptions = (AudioStreamRangedDescription*)ma_malloc(dataSize, &pContext->allocationCallbacks);
18606  if (pDescriptions == NULL) {
18607  return MA_OUT_OF_MEMORY;
18608  }
18609 
18610  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pDescriptions);
18611  if (status != noErr) {
18612  ma_free(pDescriptions, &pContext->allocationCallbacks);
18613  return ma_result_from_OSStatus(status);
18614  }
18615 
18616  *pDescriptionCount = dataSize / sizeof(*pDescriptions);
18617  *ppDescriptions = pDescriptions;
18618  return MA_SUCCESS;
18619 }
18620 
18621 
18622 static ma_result ma_get_AudioObject_channel_layout(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, AudioChannelLayout** ppChannelLayout) /* NOTE: Free the returned pointer with ma_free(). */
18623 {
18624  AudioObjectPropertyAddress propAddress;
18625  UInt32 dataSize;
18626  OSStatus status;
18627  AudioChannelLayout* pChannelLayout;
18628 
18629  MA_ASSERT(pContext != NULL);
18630  MA_ASSERT(ppChannelLayout != NULL);
18631 
18632  *ppChannelLayout = NULL; /* Safety. */
18633 
18634  propAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout;
18635  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18636  propAddress.mElement = kAudioObjectPropertyElementMaster;
18637 
18638  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
18639  if (status != noErr) {
18640  return ma_result_from_OSStatus(status);
18641  }
18642 
18643  pChannelLayout = (AudioChannelLayout*)ma_malloc(dataSize, &pContext->allocationCallbacks);
18644  if (pChannelLayout == NULL) {
18645  return MA_OUT_OF_MEMORY;
18646  }
18647 
18648  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pChannelLayout);
18649  if (status != noErr) {
18650  ma_free(pChannelLayout, &pContext->allocationCallbacks);
18651  return ma_result_from_OSStatus(status);
18652  }
18653 
18654  *ppChannelLayout = pChannelLayout;
18655  return MA_SUCCESS;
18656 }
18657 
18658 static ma_result ma_get_AudioObject_channel_count(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_uint32* pChannelCount)
18659 {
18660  AudioChannelLayout* pChannelLayout;
18661  ma_result result;
18662 
18663  MA_ASSERT(pContext != NULL);
18664  MA_ASSERT(pChannelCount != NULL);
18665 
18666  *pChannelCount = 0; /* Safety. */
18667 
18668  result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
18669  if (result != MA_SUCCESS) {
18670  return result;
18671  }
18672 
18673  if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
18674  *pChannelCount = pChannelLayout->mNumberChannelDescriptions;
18675  } else if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
18676  *pChannelCount = ma_count_set_bits(pChannelLayout->mChannelBitmap);
18677  } else {
18678  *pChannelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
18679  }
18680 
18681  ma_free(pChannelLayout, &pContext->allocationCallbacks);
18682  return MA_SUCCESS;
18683 }
18684 
18685 #if 0
18686 static ma_result ma_get_AudioObject_channel_map(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_channel* pChannelMap, size_t channelMapCap)
18687 {
18688  AudioChannelLayout* pChannelLayout;
18689  ma_result result;
18690 
18691  MA_ASSERT(pContext != NULL);
18692 
18693  result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
18694  if (result != MA_SUCCESS) {
18695  return result; /* Rather than always failing here, would it be more robust to simply assume a default? */
18696  }
18697 
18698  result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, pChannelMap, channelMapCap);
18699  if (result != MA_SUCCESS) {
18700  ma_free(pChannelLayout, &pContext->allocationCallbacks);
18701  return result;
18702  }
18703 
18704  ma_free(pChannelLayout, &pContext->allocationCallbacks);
18705  return result;
18706 }
18707 #endif
18708 
18709 static ma_result ma_get_AudioObject_sample_rates(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, UInt32* pSampleRateRangesCount, AudioValueRange** ppSampleRateRanges) /* NOTE: Free the returned pointer with ma_free(). */
18710 {
18711  AudioObjectPropertyAddress propAddress;
18712  UInt32 dataSize;
18713  OSStatus status;
18714  AudioValueRange* pSampleRateRanges;
18715 
18716  MA_ASSERT(pContext != NULL);
18717  MA_ASSERT(pSampleRateRangesCount != NULL);
18718  MA_ASSERT(ppSampleRateRanges != NULL);
18719 
18720  /* Safety. */
18721  *pSampleRateRangesCount = 0;
18722  *ppSampleRateRanges = NULL;
18723 
18724  propAddress.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
18725  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18726  propAddress.mElement = kAudioObjectPropertyElementMaster;
18727 
18728  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
18729  if (status != noErr) {
18730  return ma_result_from_OSStatus(status);
18731  }
18732 
18733  pSampleRateRanges = (AudioValueRange*)ma_malloc(dataSize, &pContext->allocationCallbacks);
18734  if (pSampleRateRanges == NULL) {
18735  return MA_OUT_OF_MEMORY;
18736  }
18737 
18738  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pSampleRateRanges);
18739  if (status != noErr) {
18740  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
18741  return ma_result_from_OSStatus(status);
18742  }
18743 
18744  *pSampleRateRangesCount = dataSize / sizeof(*pSampleRateRanges);
18745  *ppSampleRateRanges = pSampleRateRanges;
18746  return MA_SUCCESS;
18747 }
18748 
18749 #if 0
18750 static ma_result ma_get_AudioObject_get_closest_sample_rate(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_uint32 sampleRateIn, ma_uint32* pSampleRateOut)
18751 {
18752  UInt32 sampleRateRangeCount;
18753  AudioValueRange* pSampleRateRanges;
18754  ma_result result;
18755 
18756  MA_ASSERT(pContext != NULL);
18757  MA_ASSERT(pSampleRateOut != NULL);
18758 
18759  *pSampleRateOut = 0; /* Safety. */
18760 
18761  result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
18762  if (result != MA_SUCCESS) {
18763  return result;
18764  }
18765 
18766  if (sampleRateRangeCount == 0) {
18767  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
18768  return MA_ERROR; /* Should never hit this case should we? */
18769  }
18770 
18771  if (sampleRateIn == 0) {
18772  /* Search in order of miniaudio's preferred priority. */
18773  UInt32 iMALSampleRate;
18774  for (iMALSampleRate = 0; iMALSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iMALSampleRate) {
18775  ma_uint32 malSampleRate = g_maStandardSampleRatePriorities[iMALSampleRate];
18776  UInt32 iCASampleRate;
18777  for (iCASampleRate = 0; iCASampleRate < sampleRateRangeCount; ++iCASampleRate) {
18778  AudioValueRange caSampleRate = pSampleRateRanges[iCASampleRate];
18779  if (caSampleRate.mMinimum <= malSampleRate && caSampleRate.mMaximum >= malSampleRate) {
18780  *pSampleRateOut = malSampleRate;
18781  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
18782  return MA_SUCCESS;
18783  }
18784  }
18785  }
18786 
18787  /*
18788  If we get here it means none of miniaudio's standard sample rates matched any of the supported sample rates from the device. In this
18789  case we just fall back to the first one reported by Core Audio.
18790  */
18791  MA_ASSERT(sampleRateRangeCount > 0);
18792 
18793  *pSampleRateOut = pSampleRateRanges[0].mMinimum;
18794  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
18795  return MA_SUCCESS;
18796  } else {
18797  /* Find the closest match to this sample rate. */
18798  UInt32 currentAbsoluteDifference = INT32_MAX;
18799  UInt32 iCurrentClosestRange = (UInt32)-1;
18800  UInt32 iRange;
18801  for (iRange = 0; iRange < sampleRateRangeCount; ++iRange) {
18802  if (pSampleRateRanges[iRange].mMinimum <= sampleRateIn && pSampleRateRanges[iRange].mMaximum >= sampleRateIn) {
18803  *pSampleRateOut = sampleRateIn;
18804  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
18805  return MA_SUCCESS;
18806  } else {
18807  UInt32 absoluteDifference;
18808  if (pSampleRateRanges[iRange].mMinimum > sampleRateIn) {
18809  absoluteDifference = pSampleRateRanges[iRange].mMinimum - sampleRateIn;
18810  } else {
18811  absoluteDifference = sampleRateIn - pSampleRateRanges[iRange].mMaximum;
18812  }
18813 
18814  if (currentAbsoluteDifference > absoluteDifference) {
18815  currentAbsoluteDifference = absoluteDifference;
18816  iCurrentClosestRange = iRange;
18817  }
18818  }
18819  }
18820 
18821  MA_ASSERT(iCurrentClosestRange != (UInt32)-1);
18822 
18823  *pSampleRateOut = pSampleRateRanges[iCurrentClosestRange].mMinimum;
18824  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
18825  return MA_SUCCESS;
18826  }
18827 
18828  /* Should never get here, but it would mean we weren't able to find any suitable sample rates. */
18829  /*ma_free(pSampleRateRanges, &pContext->allocationCallbacks);*/
18830  /*return MA_ERROR;*/
18831 }
18832 #endif
18833 
18834 static ma_result ma_get_AudioObject_closest_buffer_size_in_frames(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_uint32 bufferSizeInFramesIn, ma_uint32* pBufferSizeInFramesOut)
18835 {
18836  AudioObjectPropertyAddress propAddress;
18837  AudioValueRange bufferSizeRange;
18838  UInt32 dataSize;
18839  OSStatus status;
18840 
18841  MA_ASSERT(pContext != NULL);
18842  MA_ASSERT(pBufferSizeInFramesOut != NULL);
18843 
18844  *pBufferSizeInFramesOut = 0; /* Safety. */
18845 
18846  propAddress.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
18847  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18848  propAddress.mElement = kAudioObjectPropertyElementMaster;
18849 
18850  dataSize = sizeof(bufferSizeRange);
18851  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, &bufferSizeRange);
18852  if (status != noErr) {
18853  return ma_result_from_OSStatus(status);
18854  }
18855 
18856  /* This is just a clamp. */
18857  if (bufferSizeInFramesIn < bufferSizeRange.mMinimum) {
18858  *pBufferSizeInFramesOut = (ma_uint32)bufferSizeRange.mMinimum;
18859  } else if (bufferSizeInFramesIn > bufferSizeRange.mMaximum) {
18860  *pBufferSizeInFramesOut = (ma_uint32)bufferSizeRange.mMaximum;
18861  } else {
18862  *pBufferSizeInFramesOut = bufferSizeInFramesIn;
18863  }
18864 
18865  return MA_SUCCESS;
18866 }
18867 
18868 static ma_result ma_set_AudioObject_buffer_size_in_frames(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_uint32* pPeriodSizeInOut)
18869 {
18870  ma_result result;
18871  ma_uint32 chosenBufferSizeInFrames;
18872  AudioObjectPropertyAddress propAddress;
18873  UInt32 dataSize;
18874  OSStatus status;
18875 
18876  MA_ASSERT(pContext != NULL);
18877 
18878  result = ma_get_AudioObject_closest_buffer_size_in_frames(pContext, deviceObjectID, deviceType, *pPeriodSizeInOut, &chosenBufferSizeInFrames);
18879  if (result != MA_SUCCESS) {
18880  return result;
18881  }
18882 
18883  /* Try setting the size of the buffer... If this fails we just use whatever is currently set. */
18884  propAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
18885  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18886  propAddress.mElement = kAudioObjectPropertyElementMaster;
18887 
18888  ((ma_AudioObjectSetPropertyData_proc)pContext->coreaudio.AudioObjectSetPropertyData)(deviceObjectID, &propAddress, 0, NULL, sizeof(chosenBufferSizeInFrames), &chosenBufferSizeInFrames);
18889 
18890  /* Get the actual size of the buffer. */
18891  dataSize = sizeof(*pPeriodSizeInOut);
18892  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, &chosenBufferSizeInFrames);
18893  if (status != noErr) {
18894  return ma_result_from_OSStatus(status);
18895  }
18896 
18897  *pPeriodSizeInOut = chosenBufferSizeInFrames;
18898  return MA_SUCCESS;
18899 }
18900 
18901 static ma_result ma_find_default_AudioObjectID(ma_context* pContext, ma_device_type deviceType, AudioObjectID* pDeviceObjectID)
18902 {
18903  AudioObjectPropertyAddress propAddressDefaultDevice;
18904  UInt32 defaultDeviceObjectIDSize = sizeof(AudioObjectID);
18905  AudioObjectID defaultDeviceObjectID;
18906  OSStatus status;
18907 
18908  MA_ASSERT(pContext != NULL);
18909  MA_ASSERT(pDeviceObjectID != NULL);
18910 
18911  /* Safety. */
18912  *pDeviceObjectID = 0;
18913 
18914  propAddressDefaultDevice.mScope = kAudioObjectPropertyScopeGlobal;
18915  propAddressDefaultDevice.mElement = kAudioObjectPropertyElementMaster;
18916  if (deviceType == ma_device_type_playback) {
18917  propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
18918  } else {
18919  propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultInputDevice;
18920  }
18921 
18922  defaultDeviceObjectIDSize = sizeof(AudioObjectID);
18923  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDefaultDevice, 0, NULL, &defaultDeviceObjectIDSize, &defaultDeviceObjectID);
18924  if (status == noErr) {
18925  *pDeviceObjectID = defaultDeviceObjectID;
18926  return MA_SUCCESS;
18927  }
18928 
18929  /* If we get here it means we couldn't find the device. */
18930  return MA_NO_DEVICE;
18931 }
18932 
18933 static ma_result ma_find_AudioObjectID(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, AudioObjectID* pDeviceObjectID)
18934 {
18935  MA_ASSERT(pContext != NULL);
18936  MA_ASSERT(pDeviceObjectID != NULL);
18937 
18938  /* Safety. */
18939  *pDeviceObjectID = 0;
18940 
18941  if (pDeviceID == NULL) {
18942  /* Default device. */
18943  return ma_find_default_AudioObjectID(pContext, deviceType, pDeviceObjectID);
18944  } else {
18945  /* Explicit device. */
18946  UInt32 deviceCount;
18947  AudioObjectID* pDeviceObjectIDs;
18948  ma_result result;
18949  UInt32 iDevice;
18950 
18951  result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
18952  if (result != MA_SUCCESS) {
18953  return result;
18954  }
18955 
18956  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
18957  AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
18958 
18959  char uid[256];
18960  if (ma_get_AudioObject_uid(pContext, deviceObjectID, sizeof(uid), uid) != MA_SUCCESS) {
18961  continue;
18962  }
18963 
18964  if (deviceType == ma_device_type_playback) {
18965  if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
18966  if (strcmp(uid, pDeviceID->coreaudio) == 0) {
18967  *pDeviceObjectID = deviceObjectID;
18968  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
18969  return MA_SUCCESS;
18970  }
18971  }
18972  } else {
18973  if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
18974  if (strcmp(uid, pDeviceID->coreaudio) == 0) {
18975  *pDeviceObjectID = deviceObjectID;
18976  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
18977  return MA_SUCCESS;
18978  }
18979  }
18980  }
18981  }
18982 
18983  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
18984  }
18985 
18986  /* If we get here it means we couldn't find the device. */
18987  return MA_NO_DEVICE;
18988 }
18989 
18990 
18991 static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, const AudioStreamBasicDescription* pOrigFormat, AudioStreamBasicDescription* pFormat)
18992 {
18993  UInt32 deviceFormatDescriptionCount;
18994  AudioStreamRangedDescription* pDeviceFormatDescriptions;
18995  ma_result result;
18996  ma_uint32 desiredSampleRate;
18997  ma_uint32 desiredChannelCount;
18998  ma_format desiredFormat;
18999  AudioStreamBasicDescription bestDeviceFormatSoFar;
19000  ma_bool32 hasSupportedFormat;
19001  UInt32 iFormat;
19002 
19003  result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &deviceFormatDescriptionCount, &pDeviceFormatDescriptions);
19004  if (result != MA_SUCCESS) {
19005  return result;
19006  }
19007 
19008  desiredSampleRate = sampleRate;
19009  if (desiredSampleRate == 0) {
19010  desiredSampleRate = pOrigFormat->mSampleRate;
19011  }
19012 
19013  desiredChannelCount = channels;
19014  if (desiredChannelCount == 0) {
19015  desiredChannelCount = pOrigFormat->mChannelsPerFrame;
19016  }
19017 
19018  desiredFormat = format;
19019  if (desiredFormat == ma_format_unknown) {
19020  result = ma_format_from_AudioStreamBasicDescription(pOrigFormat, &desiredFormat);
19021  if (result != MA_SUCCESS || desiredFormat == ma_format_unknown) {
19022  desiredFormat = g_maFormatPriorities[0];
19023  }
19024  }
19025 
19026  /*
19027  If we get here it means we don't have an exact match to what the client is asking for. We'll need to find the closest one. The next
19028  loop will check for formats that have the same sample rate to what we're asking for. If there is, we prefer that one in all cases.
19029  */
19030  MA_ZERO_OBJECT(&bestDeviceFormatSoFar);
19031 
19032  hasSupportedFormat = MA_FALSE;
19033  for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
19034  ma_format format;
19035  ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format);
19036  if (formatResult == MA_SUCCESS && format != ma_format_unknown) {
19037  hasSupportedFormat = MA_TRUE;
19038  bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
19039  break;
19040  }
19041  }
19042 
19043  if (!hasSupportedFormat) {
19044  ma_free(pDeviceFormatDescriptions, &pContext->allocationCallbacks);
19045  return MA_FORMAT_NOT_SUPPORTED;
19046  }
19047 
19048 
19049  for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
19050  AudioStreamBasicDescription thisDeviceFormat = pDeviceFormatDescriptions[iFormat].mFormat;
19051  ma_format thisSampleFormat;
19052  ma_result formatResult;
19053  ma_format bestSampleFormatSoFar;
19054 
19055  /* If the format is not supported by miniaudio we need to skip this one entirely. */
19056  formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &thisSampleFormat);
19057  if (formatResult != MA_SUCCESS || thisSampleFormat == ma_format_unknown) {
19058  continue; /* The format is not supported by miniaudio. Skip. */
19059  }
19060 
19061  ma_format_from_AudioStreamBasicDescription(&bestDeviceFormatSoFar, &bestSampleFormatSoFar);
19062 
19063  /* Getting here means the format is supported by miniaudio which makes this format a candidate. */
19064  if (thisDeviceFormat.mSampleRate != desiredSampleRate) {
19065  /*
19066  The sample rate does not match, but this format could still be usable, although it's a very low priority. If the best format
19067  so far has an equal sample rate we can just ignore this one.
19068  */
19069  if (bestDeviceFormatSoFar.mSampleRate == desiredSampleRate) {
19070  continue; /* The best sample rate so far has the same sample rate as what we requested which means it's still the best so far. Skip this format. */
19071  } else {
19072  /* In this case, neither the best format so far nor this one have the same sample rate. Check the channel count next. */
19073  if (thisDeviceFormat.mChannelsPerFrame != desiredChannelCount) {
19074  /* This format has a different sample rate _and_ a different channel count. */
19075  if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
19076  continue; /* No change to the best format. */
19077  } else {
19078  /*
19079  Both this format and the best so far have different sample rates and different channel counts. Whichever has the
19080  best format is the new best.
19081  */
19082  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
19083  bestDeviceFormatSoFar = thisDeviceFormat;
19084  continue;
19085  } else {
19086  continue; /* No change to the best format. */
19087  }
19088  }
19089  } else {
19090  /* This format has a different sample rate but the desired channel count. */
19091  if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
19092  /* Both this format and the best so far have the desired channel count. Whichever has the best format is the new best. */
19093  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
19094  bestDeviceFormatSoFar = thisDeviceFormat;
19095  continue;
19096  } else {
19097  continue; /* No change to the best format for now. */
19098  }
19099  } else {
19100  /* This format has the desired channel count, but the best so far does not. We have a new best. */
19101  bestDeviceFormatSoFar = thisDeviceFormat;
19102  continue;
19103  }
19104  }
19105  }
19106  } else {
19107  /*
19108  The sample rates match which makes this format a very high priority contender. If the best format so far has a different
19109  sample rate it needs to be replaced with this one.
19110  */
19111  if (bestDeviceFormatSoFar.mSampleRate != desiredSampleRate) {
19112  bestDeviceFormatSoFar = thisDeviceFormat;
19113  continue;
19114  } else {
19115  /* In this case both this format and the best format so far have the same sample rate. Check the channel count next. */
19116  if (thisDeviceFormat.mChannelsPerFrame == desiredChannelCount) {
19117  /*
19118  In this case this format has the same channel count as what the client is requesting. If the best format so far has
19119  a different count, this one becomes the new best.
19120  */
19121  if (bestDeviceFormatSoFar.mChannelsPerFrame != desiredChannelCount) {
19122  bestDeviceFormatSoFar = thisDeviceFormat;
19123  continue;
19124  } else {
19125  /* In this case both this format and the best so far have the ideal sample rate and channel count. Check the format. */
19126  if (thisSampleFormat == desiredFormat) {
19127  bestDeviceFormatSoFar = thisDeviceFormat;
19128  break; /* Found the exact match. */
19129  } else {
19130  /* The formats are different. The new best format is the one with the highest priority format according to miniaudio. */
19131  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
19132  bestDeviceFormatSoFar = thisDeviceFormat;
19133  continue;
19134  } else {
19135  continue; /* No change to the best format for now. */
19136  }
19137  }
19138  }
19139  } else {
19140  /*
19141  In this case the channel count is different to what the client has requested. If the best so far has the same channel
19142  count as the requested count then it remains the best.
19143  */
19144  if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
19145  continue;
19146  } else {
19147  /*
19148  This is the case where both have the same sample rate (good) but different channel counts. Right now both have about
19149  the same priority, but we need to compare the format now.
19150  */
19151  if (thisSampleFormat == bestSampleFormatSoFar) {
19152  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
19153  bestDeviceFormatSoFar = thisDeviceFormat;
19154  continue;
19155  } else {
19156  continue; /* No change to the best format for now. */
19157  }
19158  }
19159  }
19160  }
19161  }
19162  }
19163  }
19164 
19165  *pFormat = bestDeviceFormatSoFar;
19166 
19167  ma_free(pDeviceFormatDescriptions, &pContext->allocationCallbacks);
19168  return MA_SUCCESS;
19169 }
19170 
19171 static ma_result ma_get_AudioUnit_channel_map(ma_context* pContext, AudioUnit audioUnit, ma_device_type deviceType, ma_channel* pChannelMap, size_t channelMapCap)
19172 {
19173  AudioUnitScope deviceScope;
19174  AudioUnitElement deviceBus;
19175  UInt32 channelLayoutSize;
19176  OSStatus status;
19177  AudioChannelLayout* pChannelLayout;
19178  ma_result result;
19179 
19180  MA_ASSERT(pContext != NULL);
19181 
19182  if (deviceType == ma_device_type_playback) {
19183  deviceScope = kAudioUnitScope_Input;
19184  deviceBus = MA_COREAUDIO_OUTPUT_BUS;
19185  } else {
19186  deviceScope = kAudioUnitScope_Output;
19187  deviceBus = MA_COREAUDIO_INPUT_BUS;
19188  }
19189 
19190  status = ((ma_AudioUnitGetPropertyInfo_proc)pContext->coreaudio.AudioUnitGetPropertyInfo)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, &channelLayoutSize, NULL);
19191  if (status != noErr) {
19192  return ma_result_from_OSStatus(status);
19193  }
19194 
19195  pChannelLayout = (AudioChannelLayout*)ma__malloc_from_callbacks(channelLayoutSize, &pContext->allocationCallbacks);
19196  if (pChannelLayout == NULL) {
19197  return MA_OUT_OF_MEMORY;
19198  }
19199 
19200  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, pChannelLayout, &channelLayoutSize);
19201  if (status != noErr) {
19202  ma__free_from_callbacks(pChannelLayout, &pContext->allocationCallbacks);
19203  return ma_result_from_OSStatus(status);
19204  }
19205 
19206  result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, pChannelMap, channelMapCap);
19207  if (result != MA_SUCCESS) {
19208  ma__free_from_callbacks(pChannelLayout, &pContext->allocationCallbacks);
19209  return result;
19210  }
19211 
19212  ma__free_from_callbacks(pChannelLayout, &pContext->allocationCallbacks);
19213  return MA_SUCCESS;
19214 }
19215 #endif /* MA_APPLE_DESKTOP */
19216 
19217 
19218 #if !defined(MA_APPLE_DESKTOP)
19219 static void ma_AVAudioSessionPortDescription_to_device_info(AVAudioSessionPortDescription* pPortDesc, ma_device_info* pInfo)
19220 {
19221  MA_ZERO_OBJECT(pInfo);
19222  ma_strncpy_s(pInfo->name, sizeof(pInfo->name), [pPortDesc.portName UTF8String], (size_t)-1);
19223  ma_strncpy_s(pInfo->id.coreaudio, sizeof(pInfo->id.coreaudio), [pPortDesc.UID UTF8String], (size_t)-1);
19224 }
19225 #endif
19226 
19227 static ma_result ma_context_enumerate_devices__coreaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
19228 {
19229 #if defined(MA_APPLE_DESKTOP)
19230  UInt32 deviceCount;
19231  AudioObjectID* pDeviceObjectIDs;
19232  AudioObjectID defaultDeviceObjectIDPlayback;
19233  AudioObjectID defaultDeviceObjectIDCapture;
19234  ma_result result;
19235  UInt32 iDevice;
19236 
19237  ma_find_default_AudioObjectID(pContext, ma_device_type_playback, &defaultDeviceObjectIDPlayback); /* OK if this fails. */
19238  ma_find_default_AudioObjectID(pContext, ma_device_type_capture, &defaultDeviceObjectIDCapture); /* OK if this fails. */
19239 
19240  result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
19241  if (result != MA_SUCCESS) {
19242  return result;
19243  }
19244 
19245  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
19246  AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
19247  ma_device_info info;
19248 
19249  MA_ZERO_OBJECT(&info);
19250  if (ma_get_AudioObject_uid(pContext, deviceObjectID, sizeof(info.id.coreaudio), info.id.coreaudio) != MA_SUCCESS) {
19251  continue;
19252  }
19253  if (ma_get_AudioObject_name(pContext, deviceObjectID, sizeof(info.name), info.name) != MA_SUCCESS) {
19254  continue;
19255  }
19256 
19257  if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
19258  if (deviceObjectID == defaultDeviceObjectIDPlayback) {
19259  info.isDefault = MA_TRUE;
19260  }
19261 
19262  if (!callback(pContext, ma_device_type_playback, &info, pUserData)) {
19263  break;
19264  }
19265  }
19266  if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
19267  if (deviceObjectID == defaultDeviceObjectIDCapture) {
19268  info.isDefault = MA_TRUE;
19269  }
19270 
19271  if (!callback(pContext, ma_device_type_capture, &info, pUserData)) {
19272  break;
19273  }
19274  }
19275  }
19276 
19277  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
19278 #else
19279  ma_device_info info;
19280  NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
19281  NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
19282 
19283  for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
19284  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, &info);
19285  if (!callback(pContext, ma_device_type_playback, &info, pUserData)) {
19286  return MA_SUCCESS;
19287  }
19288  }
19289 
19290  for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
19291  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, &info);
19292  if (!callback(pContext, ma_device_type_capture, &info, pUserData)) {
19293  return MA_SUCCESS;
19294  }
19295  }
19296 #endif
19297 
19298  return MA_SUCCESS;
19299 }
19300 
19301 static ma_result ma_context_get_device_info__coreaudio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
19302 {
19303  ma_result result;
19304 
19305  MA_ASSERT(pContext != NULL);
19306 
19307 #if defined(MA_APPLE_DESKTOP)
19308  /* Desktop */
19309  {
19310  AudioObjectID deviceObjectID;
19311  AudioObjectID defaultDeviceObjectID;
19312  UInt32 streamDescriptionCount;
19313  AudioStreamRangedDescription* pStreamDescriptions;
19314  UInt32 iStreamDescription;
19315  UInt32 sampleRateRangeCount;
19316  AudioValueRange* pSampleRateRanges;
19317 
19318  ma_find_default_AudioObjectID(pContext, deviceType, &defaultDeviceObjectID); /* OK if this fails. */
19319 
19320  result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
19321  if (result != MA_SUCCESS) {
19322  return result;
19323  }
19324 
19325  result = ma_get_AudioObject_uid(pContext, deviceObjectID, sizeof(pDeviceInfo->id.coreaudio), pDeviceInfo->id.coreaudio);
19326  if (result != MA_SUCCESS) {
19327  return result;
19328  }
19329 
19330  result = ma_get_AudioObject_name(pContext, deviceObjectID, sizeof(pDeviceInfo->name), pDeviceInfo->name);
19331  if (result != MA_SUCCESS) {
19332  return result;
19333  }
19334 
19335  if (deviceObjectID == defaultDeviceObjectID) {
19336  pDeviceInfo->isDefault = MA_TRUE;
19337  }
19338 
19339  /*
19340  There could be a large number of permutations here. Fortunately there is only a single channel count
19341  being reported which reduces this quite a bit. For sample rates we're only reporting those that are
19342  one of miniaudio's recognized "standard" rates. If there are still more formats than can fit into
19343  our fixed sized array we'll just need to truncate them. This is unlikely and will probably only happen
19344  if some driver performs software data conversion and therefore reports every possible format and
19345  sample rate.
19346  */
19347  pDeviceInfo->nativeDataFormatCount = 0;
19348 
19349  /* Formats. */
19350  {
19351  ma_format uniqueFormats[ma_format_count];
19352  ma_uint32 uniqueFormatCount = 0;
19353  ma_uint32 channels;
19354 
19355  /* Channels. */
19356  result = ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &channels);
19357  if (result != MA_SUCCESS) {
19358  return result;
19359  }
19360 
19361  /* Formats. */
19362  result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &streamDescriptionCount, &pStreamDescriptions);
19363  if (result != MA_SUCCESS) {
19364  return result;
19365  }
19366 
19367  for (iStreamDescription = 0; iStreamDescription < streamDescriptionCount; ++iStreamDescription) {
19368  ma_format format;
19369  ma_bool32 hasFormatBeenHandled = MA_FALSE;
19370  ma_uint32 iOutputFormat;
19371  ma_uint32 iSampleRate;
19372 
19373  result = ma_format_from_AudioStreamBasicDescription(&pStreamDescriptions[iStreamDescription].mFormat, &format);
19374  if (result != MA_SUCCESS) {
19375  continue;
19376  }
19377 
19378  MA_ASSERT(format != ma_format_unknown);
19379 
19380  /* Make sure the format isn't already in the output list. */
19381  for (iOutputFormat = 0; iOutputFormat < uniqueFormatCount; ++iOutputFormat) {
19382  if (uniqueFormats[iOutputFormat] == format) {
19383  hasFormatBeenHandled = MA_TRUE;
19384  break;
19385  }
19386  }
19387 
19388  /* If we've already handled this format just skip it. */
19389  if (hasFormatBeenHandled) {
19390  continue;
19391  }
19392 
19393  uniqueFormats[uniqueFormatCount] = format;
19394  uniqueFormatCount += 1;
19395 
19396  /* Sample Rates */
19397  result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
19398  if (result != MA_SUCCESS) {
19399  return result;
19400  }
19401 
19402  /*
19403  Annoyingly Core Audio reports a sample rate range. We just get all the standard rates that are
19404  between this range.
19405  */
19406  for (iSampleRate = 0; iSampleRate < sampleRateRangeCount; ++iSampleRate) {
19407  ma_uint32 iStandardSampleRate;
19408  for (iStandardSampleRate = 0; iStandardSampleRate < ma_countof(g_maStandardSampleRatePriorities); iStandardSampleRate += 1) {
19409  ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iStandardSampleRate];
19410  if (standardSampleRate >= pSampleRateRanges[iSampleRate].mMinimum && standardSampleRate <= pSampleRateRanges[iSampleRate].mMaximum) {
19411  /* We have a new data format. Add it to the list. */
19412  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
19413  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
19414  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = standardSampleRate;
19415  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
19416  pDeviceInfo->nativeDataFormatCount += 1;
19417 
19418  if (pDeviceInfo->nativeDataFormatCount >= ma_countof(pDeviceInfo->nativeDataFormats)) {
19419  break; /* No more room for any more formats. */
19420  }
19421  }
19422  }
19423  }
19424 
19425  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
19426 
19427  if (pDeviceInfo->nativeDataFormatCount >= ma_countof(pDeviceInfo->nativeDataFormats)) {
19428  break; /* No more room for any more formats. */
19429  }
19430  }
19431 
19432  ma_free(pStreamDescriptions, &pContext->allocationCallbacks);
19433  }
19434  }
19435 #else
19436  /* Mobile */
19437  {
19438  AudioComponentDescription desc;
19439  AudioComponent component;
19440  AudioUnit audioUnit;
19441  OSStatus status;
19442  AudioUnitScope formatScope;
19443  AudioUnitElement formatElement;
19444  AudioStreamBasicDescription bestFormat;
19445  UInt32 propSize;
19446 
19447  /* We want to ensure we use a consistent device name to device enumeration. */
19448  if (pDeviceID != NULL) {
19449  ma_bool32 found = MA_FALSE;
19450  if (deviceType == ma_device_type_playback) {
19451  NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
19452  for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
19453  if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
19454  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
19455  found = MA_TRUE;
19456  break;
19457  }
19458  }
19459  } else {
19460  NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
19461  for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
19462  if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
19463  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
19464  found = MA_TRUE;
19465  break;
19466  }
19467  }
19468  }
19469 
19470  if (!found) {
19471  return MA_DOES_NOT_EXIST;
19472  }
19473  } else {
19474  if (deviceType == ma_device_type_playback) {
19475  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
19476  } else {
19477  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
19478  }
19479  }
19480 
19481 
19482  /*
19483  Retrieving device information is more annoying on mobile than desktop. For simplicity I'm locking this down to whatever format is
19484  reported on a temporary I/O unit. The problem, however, is that this doesn't return a value for the sample rate which we need to
19485  retrieve from the AVAudioSession shared instance.
19486  */
19487  desc.componentType = kAudioUnitType_Output;
19488  desc.componentSubType = kAudioUnitSubType_RemoteIO;
19489  desc.componentManufacturer = kAudioUnitManufacturer_Apple;
19490  desc.componentFlags = 0;
19491  desc.componentFlagsMask = 0;
19492 
19493  component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc);
19494  if (component == NULL) {
19496  }
19497 
19498  status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)(component, &audioUnit);
19499  if (status != noErr) {
19500  return ma_result_from_OSStatus(status);
19501  }
19502 
19503  formatScope = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
19504  formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
19505 
19506  propSize = sizeof(bestFormat);
19507  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
19508  if (status != noErr) {
19509  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
19510  return ma_result_from_OSStatus(status);
19511  }
19512 
19513  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
19514  audioUnit = NULL;
19515 
19516  /* Only a single format is being reported for iOS. */
19517  pDeviceInfo->nativeDataFormatCount = 1;
19518 
19519  result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pDeviceInfo->nativeDataFormats[0].format);
19520  if (result != MA_SUCCESS) {
19521  return result;
19522  }
19523 
19524  pDeviceInfo->nativeDataFormats[0].channels = bestFormat.mChannelsPerFrame;
19525 
19526  /*
19527  It looks like Apple are wanting to push the whole AVAudioSession thing. Thus, we need to use that to determine device settings. To do
19528  this we just get the shared instance and inspect.
19529  */
19530  @autoreleasepool {
19531  AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
19532  MA_ASSERT(pAudioSession != NULL);
19533 
19534  pDeviceInfo->nativeDataFormats[0].sampleRate = (ma_uint32)pAudioSession.sampleRate;
19535  }
19536  }
19537 #endif
19538 
19539  (void)pDeviceInfo; /* Unused. */
19540  return MA_SUCCESS;
19541 }
19542 
19543 static AudioBufferList* ma_allocate_AudioBufferList__coreaudio(ma_uint32 sizeInFrames, ma_format format, ma_uint32 channels, ma_stream_layout layout, const ma_allocation_callbacks* pAllocationCallbacks)
19544 {
19545  AudioBufferList* pBufferList;
19546  UInt32 audioBufferSizeInBytes;
19547  size_t allocationSize;
19548 
19549  MA_ASSERT(sizeInFrames > 0);
19550  MA_ASSERT(format != ma_format_unknown);
19551  MA_ASSERT(channels > 0);
19552 
19553  allocationSize = sizeof(AudioBufferList) - sizeof(AudioBuffer); /* Subtract sizeof(AudioBuffer) because that part is dynamically sized. */
19554  if (layout == ma_stream_layout_interleaved) {
19555  /* Interleaved case. This is the simple case because we just have one buffer. */
19556  allocationSize += sizeof(AudioBuffer) * 1;
19557  } else {
19558  /* Non-interleaved case. This is the more complex case because there's more than one buffer. */
19559  allocationSize += sizeof(AudioBuffer) * channels;
19560  }
19561 
19562  allocationSize += sizeInFrames * ma_get_bytes_per_frame(format, channels);
19563 
19564  pBufferList = (AudioBufferList*)ma__malloc_from_callbacks(allocationSize, pAllocationCallbacks);
19565  if (pBufferList == NULL) {
19566  return NULL;
19567  }
19568 
19569  audioBufferSizeInBytes = (UInt32)(sizeInFrames * ma_get_bytes_per_sample(format));
19570 
19571  if (layout == ma_stream_layout_interleaved) {
19572  pBufferList->mNumberBuffers = 1;
19573  pBufferList->mBuffers[0].mNumberChannels = channels;
19574  pBufferList->mBuffers[0].mDataByteSize = audioBufferSizeInBytes * channels;
19575  pBufferList->mBuffers[0].mData = (ma_uint8*)pBufferList + sizeof(AudioBufferList);
19576  } else {
19577  ma_uint32 iBuffer;
19578  pBufferList->mNumberBuffers = channels;
19579  for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
19580  pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
19581  pBufferList->mBuffers[iBuffer].mDataByteSize = audioBufferSizeInBytes;
19582  pBufferList->mBuffers[iBuffer].mData = (ma_uint8*)pBufferList + ((sizeof(AudioBufferList) - sizeof(AudioBuffer)) + (sizeof(AudioBuffer) * channels)) + (audioBufferSizeInBytes * iBuffer);
19583  }
19584  }
19585 
19586  return pBufferList;
19587 }
19588 
19589 static ma_result ma_device_realloc_AudioBufferList__coreaudio(ma_device* pDevice, ma_uint32 sizeInFrames, ma_format format, ma_uint32 channels, ma_stream_layout layout)
19590 {
19591  MA_ASSERT(pDevice != NULL);
19592  MA_ASSERT(format != ma_format_unknown);
19593  MA_ASSERT(channels > 0);
19594 
19595  /* Only resize the buffer if necessary. */
19596  if (pDevice->coreaudio.audioBufferCapInFrames < sizeInFrames) {
19597  AudioBufferList* pNewAudioBufferList;
19598 
19599  pNewAudioBufferList = ma_allocate_AudioBufferList__coreaudio(sizeInFrames, format, channels, layout, &pDevice->pContext->allocationCallbacks);
19600  if (pNewAudioBufferList != NULL) {
19601  return MA_OUT_OF_MEMORY;
19602  }
19603 
19604  /* At this point we'll have a new AudioBufferList and we can free the old one. */
19605  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
19606  pDevice->coreaudio.pAudioBufferList = pNewAudioBufferList;
19607  pDevice->coreaudio.audioBufferCapInFrames = sizeInFrames;
19608  }
19609 
19610  /* Getting here means the capacity of the audio is fine. */
19611  return MA_SUCCESS;
19612 }
19613 
19614 
19615 static OSStatus ma_on_output__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pActionFlags, const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufferList)
19616 {
19617  ma_device* pDevice = (ma_device*)pUserData;
19618  ma_stream_layout layout;
19619 
19620  MA_ASSERT(pDevice != NULL);
19621 
19622  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "INFO: Output Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pBufferList->mNumberBuffers);
19623 
19624  /* We need to check whether or not we are outputting interleaved or non-interleaved samples. The way we do this is slightly different for each type. */
19626  if (pBufferList->mBuffers[0].mNumberChannels != pDevice->playback.internalChannels) {
19628  }
19629 
19630  if (layout == ma_stream_layout_interleaved) {
19631  /* For now we can assume everything is interleaved. */
19632  UInt32 iBuffer;
19633  for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
19634  if (pBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->playback.internalChannels) {
19635  ma_uint32 frameCountForThisBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
19636  if (frameCountForThisBuffer > 0) {
19637  ma_device_handle_backend_data_callback(pDevice, pBufferList->mBuffers[iBuffer].mData, NULL, frameCountForThisBuffer);
19638  }
19639 
19640  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pBufferList->mBuffers[iBuffer].mNumberChannels, pBufferList->mBuffers[iBuffer].mDataByteSize);
19641  } else {
19642  /*
19643  This case is where the number of channels in the output buffer do not match our internal channels. It could mean that it's
19644  not interleaved, in which case we can't handle right now since miniaudio does not yet support non-interleaved streams. We just
19645  output silence here.
19646  */
19647  MA_ZERO_MEMORY(pBufferList->mBuffers[iBuffer].mData, pBufferList->mBuffers[iBuffer].mDataByteSize);
19648  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " WARNING: Outputting silence. frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pBufferList->mBuffers[iBuffer].mNumberChannels, pBufferList->mBuffers[iBuffer].mDataByteSize);
19649  }
19650  }
19651  } else {
19652  /* This is the deinterleaved case. We need to update each buffer in groups of internalChannels. This assumes each buffer is the same size. */
19653  MA_ASSERT(pDevice->playback.internalChannels <= MA_MAX_CHANNELS); /* This should heve been validated at initialization time. */
19654 
19655  /*
19656  For safety we'll check that the internal channels is a multiple of the buffer count. If it's not it means something
19657  very strange has happened and we're not going to support it.
19658  */
19659  if ((pBufferList->mNumberBuffers % pDevice->playback.internalChannels) == 0) {
19660  ma_uint8 tempBuffer[4096];
19661  UInt32 iBuffer;
19662 
19663  for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; iBuffer += pDevice->playback.internalChannels) {
19664  ma_uint32 frameCountPerBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / ma_get_bytes_per_sample(pDevice->playback.internalFormat);
19665  ma_uint32 framesRemaining = frameCountPerBuffer;
19666 
19667  while (framesRemaining > 0) {
19668  void* ppDeinterleavedBuffers[MA_MAX_CHANNELS];
19669  ma_uint32 iChannel;
19670  ma_uint32 framesToRead = sizeof(tempBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
19671  if (framesToRead > framesRemaining) {
19672  framesToRead = framesRemaining;
19673  }
19674 
19675  ma_device_handle_backend_data_callback(pDevice, tempBuffer, NULL, framesToRead);
19676 
19677  for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
19678  ppDeinterleavedBuffers[iChannel] = (void*)ma_offset_ptr(pBufferList->mBuffers[iBuffer+iChannel].mData, (frameCountPerBuffer - framesRemaining) * ma_get_bytes_per_sample(pDevice->playback.internalFormat));
19679  }
19680 
19681  ma_deinterleave_pcm_frames(pDevice->playback.internalFormat, pDevice->playback.internalChannels, framesToRead, tempBuffer, ppDeinterleavedBuffers);
19682 
19683  framesRemaining -= framesToRead;
19684  }
19685  }
19686  }
19687  }
19688 
19689  (void)pActionFlags;
19690  (void)pTimeStamp;
19691  (void)busNumber;
19692  (void)frameCount;
19693 
19694  return noErr;
19695 }
19696 
19697 static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pActionFlags, const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pUnusedBufferList)
19698 {
19699  ma_device* pDevice = (ma_device*)pUserData;
19700  AudioBufferList* pRenderedBufferList;
19701  ma_result result;
19702  ma_stream_layout layout;
19703  ma_uint32 iBuffer;
19704  OSStatus status;
19705 
19706  MA_ASSERT(pDevice != NULL);
19707 
19708  pRenderedBufferList = (AudioBufferList*)pDevice->coreaudio.pAudioBufferList;
19709  MA_ASSERT(pRenderedBufferList);
19710 
19711  /* We need to check whether or not we are outputting interleaved or non-interleaved samples. The way we do this is slightly different for each type. */
19713  if (pRenderedBufferList->mBuffers[0].mNumberChannels != pDevice->capture.internalChannels) {
19715  }
19716 
19717  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "INFO: Input Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pRenderedBufferList->mNumberBuffers);
19718 
19719  /*
19720  There has been a situation reported where frame count passed into this function is greater than the capacity of
19721  our capture buffer. There doesn't seem to be a reliable way to determine what the maximum frame count will be,
19722  so we need to instead resort to dynamically reallocating our buffer to ensure it's large enough to capture the
19723  number of frames requested by this callback.
19724  */
19725  result = ma_device_realloc_AudioBufferList__coreaudio(pDevice, frameCount, pDevice->capture.internalFormat, pDevice->capture.internalChannels, layout);
19726  if (result != MA_SUCCESS) {
19727  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Failed to allocate AudioBufferList for capture.");
19728  return noErr;
19729  }
19730 
19731  /*
19732  When you call AudioUnitRender(), Core Audio tries to be helpful by setting the mDataByteSize to the number of bytes
19733  that were actually rendered. The problem with this is that the next call can fail with -50 due to the size no longer
19734  being set to the capacity of the buffer, but instead the size in bytes of the previous render. This will cause a
19735  problem when a future call to this callback specifies a larger number of frames.
19736 
19737  To work around this we need to explicitly set the size of each buffer to their respective size in bytes.
19738  */
19739  for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
19740  pRenderedBufferList->mBuffers[iBuffer].mDataByteSize = pDevice->coreaudio.audioBufferCapInFrames * ma_get_bytes_per_sample(pDevice->capture.internalFormat) * pRenderedBufferList->mBuffers[iBuffer].mNumberChannels;
19741  }
19742 
19743  status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList);
19744  if (status != noErr) {
19745  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " ERROR: AudioUnitRender() failed with %d\n", status);
19746  return status;
19747  }
19748 
19749  if (layout == ma_stream_layout_interleaved) {
19750  for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
19751  if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->capture.internalChannels) {
19752  ma_device_handle_backend_data_callback(pDevice, NULL, pRenderedBufferList->mBuffers[iBuffer].mData, frameCount);
19753  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " mDataByteSize=%d\n", pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
19754  } else {
19755  /*
19756  This case is where the number of channels in the output buffer do not match our internal channels. It could mean that it's
19757  not interleaved, in which case we can't handle right now since miniaudio does not yet support non-interleaved streams.
19758  */
19759  ma_uint8 silentBuffer[4096];
19760  ma_uint32 framesRemaining;
19761 
19762  MA_ZERO_MEMORY(silentBuffer, sizeof(silentBuffer));
19763 
19764  framesRemaining = frameCount;
19765  while (framesRemaining > 0) {
19766  ma_uint32 framesToSend = sizeof(silentBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
19767  if (framesToSend > framesRemaining) {
19768  framesToSend = framesRemaining;
19769  }
19770 
19771  ma_device_handle_backend_data_callback(pDevice, NULL, silentBuffer, framesToSend);
19772 
19773  framesRemaining -= framesToSend;
19774  }
19775 
19776  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " WARNING: Outputting silence. frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pRenderedBufferList->mBuffers[iBuffer].mNumberChannels, pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
19777  }
19778  }
19779  } else {
19780  /* This is the deinterleaved case. We need to interleave the audio data before sending it to the client. This assumes each buffer is the same size. */
19781  MA_ASSERT(pDevice->capture.internalChannels <= MA_MAX_CHANNELS); /* This should have been validated at initialization time. */
19782 
19783  /*
19784  For safety we'll check that the internal channels is a multiple of the buffer count. If it's not it means something
19785  very strange has happened and we're not going to support it.
19786  */
19787  if ((pRenderedBufferList->mNumberBuffers % pDevice->capture.internalChannels) == 0) {
19788  ma_uint8 tempBuffer[4096];
19789  for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; iBuffer += pDevice->capture.internalChannels) {
19790  ma_uint32 framesRemaining = frameCount;
19791  while (framesRemaining > 0) {
19792  void* ppDeinterleavedBuffers[MA_MAX_CHANNELS];
19793  ma_uint32 iChannel;
19794  ma_uint32 framesToSend = sizeof(tempBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
19795  if (framesToSend > framesRemaining) {
19796  framesToSend = framesRemaining;
19797  }
19798 
19799  for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
19800  ppDeinterleavedBuffers[iChannel] = (void*)ma_offset_ptr(pRenderedBufferList->mBuffers[iBuffer+iChannel].mData, (frameCount - framesRemaining) * ma_get_bytes_per_sample(pDevice->capture.internalFormat));
19801  }
19802 
19803  ma_interleave_pcm_frames(pDevice->capture.internalFormat, pDevice->capture.internalChannels, framesToSend, (const void**)ppDeinterleavedBuffers, tempBuffer);
19804  ma_device_handle_backend_data_callback(pDevice, NULL, tempBuffer, framesToSend);
19805 
19806  framesRemaining -= framesToSend;
19807  }
19808  }
19809  }
19810  }
19811 
19812  (void)pActionFlags;
19813  (void)pTimeStamp;
19814  (void)busNumber;
19815  (void)frameCount;
19816  (void)pUnusedBufferList;
19817 
19818  return noErr;
19819 }
19820 
19821 static void on_start_stop__coreaudio(void* pUserData, AudioUnit audioUnit, AudioUnitPropertyID propertyID, AudioUnitScope scope, AudioUnitElement element)
19822 {
19823  ma_device* pDevice = (ma_device*)pUserData;
19824  MA_ASSERT(pDevice != NULL);
19825 
19826  /* Don't do anything if it looks like we're just reinitializing due to a device switch. */
19827  if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isSwitchingPlaybackDevice) ||
19828  ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isSwitchingCaptureDevice)) {
19829  return;
19830  }
19831 
19832  /*
19833  There's been a report of a deadlock here when triggered by ma_device_uninit(). It looks like
19834  AudioUnitGetProprty (called below) and AudioComponentInstanceDispose (called in ma_device_uninit)
19835  can try waiting on the same lock. I'm going to try working around this by not calling any Core
19836  Audio APIs in the callback when the device has been stopped or uninitialized.
19837  */
19839  ma_stop_proc onStop = pDevice->onStop;
19840  if (onStop) {
19841  onStop(pDevice);
19842  }
19843 
19844  ma_event_signal(&pDevice->coreaudio.stopEvent);
19845  } else {
19846  UInt32 isRunning;
19847  UInt32 isRunningSize = sizeof(isRunning);
19848  OSStatus status = ((ma_AudioUnitGetProperty_proc)pDevice->pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioOutputUnitProperty_IsRunning, scope, element, &isRunning, &isRunningSize);
19849  if (status != noErr) {
19850  return; /* Don't really know what to do in this case... just ignore it, I suppose... */
19851  }
19852 
19853  if (!isRunning) {
19854  ma_stop_proc onStop;
19855 
19856  /*
19857  The stop event is a bit annoying in Core Audio because it will be called when we automatically switch the default device. Some scenarios to consider:
19858 
19859  1) When the device is unplugged, this will be called _before_ the default device change notification.
19860  2) When the device is changed via the default device change notification, this will be called _after_ the switch.
19861 
19862  For case #1, we just check if there's a new default device available. If so, we just ignore the stop event. For case #2 we check a flag.
19863  */
19864  if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isDefaultPlaybackDevice) ||
19865  ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isDefaultCaptureDevice)) {
19866  /*
19867  It looks like the device is switching through an external event, such as the user unplugging the device or changing the default device
19868  via the operating system's sound settings. If we're re-initializing the device, we just terminate because we want the stopping of the
19869  device to be seamless to the client (we don't want them receiving the onStop event and thinking that the device has stopped when it
19870  hasn't!).
19871  */
19872  if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isSwitchingPlaybackDevice) ||
19873  ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isSwitchingCaptureDevice)) {
19874  return;
19875  }
19876 
19877  /*
19878  Getting here means the device is not reinitializing which means it may have been unplugged. From what I can see, it looks like Core Audio
19879  will try switching to the new default device seamlessly. We need to somehow find a way to determine whether or not Core Audio will most
19880  likely be successful in switching to the new device.
19881 
19882  TODO: Try to predict if Core Audio will switch devices. If not, the onStop callback needs to be posted.
19883  */
19884  return;
19885  }
19886 
19887  /* Getting here means we need to stop the device. */
19888  onStop = pDevice->onStop;
19889  if (onStop) {
19890  onStop(pDevice);
19891  }
19892  }
19893  }
19894 
19895  (void)propertyID; /* Unused. */
19896 }
19897 
19898 #if defined(MA_APPLE_DESKTOP)
19899 static ma_spinlock g_DeviceTrackingInitLock_CoreAudio = 0; /* A spinlock for mutal exclusion of the init/uninit of the global tracking data. Initialization to 0 is what we need. */
19900 static ma_uint32 g_DeviceTrackingInitCounter_CoreAudio = 0;
19901 static ma_mutex g_DeviceTrackingMutex_CoreAudio;
19902 static ma_device** g_ppTrackedDevices_CoreAudio = NULL;
19903 static ma_uint32 g_TrackedDeviceCap_CoreAudio = 0;
19904 static ma_uint32 g_TrackedDeviceCount_CoreAudio = 0;
19905 
19906 static OSStatus ma_default_device_changed__coreaudio(AudioObjectID objectID, UInt32 addressCount, const AudioObjectPropertyAddress* pAddresses, void* pUserData)
19907 {
19908  ma_device_type deviceType;
19909 
19910  /* Not sure if I really need to check this, but it makes me feel better. */
19911  if (addressCount == 0) {
19912  return noErr;
19913  }
19914 
19915  if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultOutputDevice) {
19916  deviceType = ma_device_type_playback;
19917  } else if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultInputDevice) {
19918  deviceType = ma_device_type_capture;
19919  } else {
19920  return noErr; /* Should never hit this. */
19921  }
19922 
19923  ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
19924  {
19925  ma_uint32 iDevice;
19926  for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
19927  ma_result reinitResult;
19928  ma_device* pDevice;
19929 
19930  pDevice = g_ppTrackedDevices_CoreAudio[iDevice];
19931  if (pDevice->type == deviceType || pDevice->type == ma_device_type_duplex) {
19932  if (deviceType == ma_device_type_playback) {
19933  pDevice->coreaudio.isSwitchingPlaybackDevice = MA_TRUE;
19934  reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType, MA_TRUE);
19935  pDevice->coreaudio.isSwitchingPlaybackDevice = MA_FALSE;
19936  } else {
19937  pDevice->coreaudio.isSwitchingCaptureDevice = MA_TRUE;
19938  reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType, MA_TRUE);
19939  pDevice->coreaudio.isSwitchingCaptureDevice = MA_FALSE;
19940  }
19941 
19942  if (reinitResult == MA_SUCCESS) {
19943  ma_device__post_init_setup(pDevice, deviceType);
19944 
19945  /* Restart the device if required. If this fails we need to stop the device entirely. */
19946  if (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
19947  OSStatus status;
19948  if (deviceType == ma_device_type_playback) {
19949  status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
19950  if (status != noErr) {
19951  if (pDevice->type == ma_device_type_duplex) {
19952  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
19953  }
19955  }
19956  } else if (deviceType == ma_device_type_capture) {
19957  status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
19958  if (status != noErr) {
19959  if (pDevice->type == ma_device_type_duplex) {
19960  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
19961  }
19963  }
19964  }
19965  }
19966  }
19967  }
19968  }
19969  }
19970  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
19971 
19972  /* Unused parameters. */
19973  (void)objectID;
19974  (void)pUserData;
19975 
19976  return noErr;
19977 }
19978 
19979 static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContext)
19980 {
19981  MA_ASSERT(pContext != NULL);
19982 
19983  ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
19984  {
19985  /* Don't do anything if we've already initializd device tracking. */
19986  if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
19987  AudioObjectPropertyAddress propAddress;
19988  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
19989  propAddress.mElement = kAudioObjectPropertyElementMaster;
19990 
19991  ma_mutex_init(&g_DeviceTrackingMutex_CoreAudio);
19992 
19993  propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
19994  ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
19995 
19996  propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
19997  ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
19998 
19999  }
20000  g_DeviceTrackingInitCounter_CoreAudio += 1;
20001  }
20002  ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
20003 
20004  return MA_SUCCESS;
20005 }
20006 
20007 static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pContext)
20008 {
20009  MA_ASSERT(pContext != NULL);
20010 
20011  ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
20012  {
20013  if (g_DeviceTrackingInitCounter_CoreAudio > 0)
20014  g_DeviceTrackingInitCounter_CoreAudio -= 1;
20015 
20016  if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
20017  AudioObjectPropertyAddress propAddress;
20018  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
20019  propAddress.mElement = kAudioObjectPropertyElementMaster;
20020 
20021  propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
20022  ((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
20023 
20024  propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
20025  ((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
20026 
20027  /* At this point there should be no tracked devices. If not there's an error somewhere. */
20028  if (g_ppTrackedDevices_CoreAudio != NULL) {
20029  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "You have uninitialized all contexts while an associated device is still active.", MA_INVALID_OPERATION);
20030  ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
20031  return MA_INVALID_OPERATION;
20032  }
20033 
20034  ma_mutex_uninit(&g_DeviceTrackingMutex_CoreAudio);
20035  }
20036  }
20037  ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
20038 
20039  return MA_SUCCESS;
20040 }
20041 
20042 static ma_result ma_device__track__coreaudio(ma_device* pDevice)
20043 {
20044  MA_ASSERT(pDevice != NULL);
20045 
20046  ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
20047  {
20048  /* Allocate memory if required. */
20049  if (g_TrackedDeviceCap_CoreAudio <= g_TrackedDeviceCount_CoreAudio) {
20050  ma_uint32 oldCap;
20051  ma_uint32 newCap;
20052  ma_device** ppNewDevices;
20053 
20054  oldCap = g_TrackedDeviceCap_CoreAudio;
20055  newCap = g_TrackedDeviceCap_CoreAudio * 2;
20056  if (newCap == 0) {
20057  newCap = 1;
20058  }
20059 
20060  ppNewDevices = (ma_device**)ma__realloc_from_callbacks(g_ppTrackedDevices_CoreAudio, sizeof(*g_ppTrackedDevices_CoreAudio)*newCap, sizeof(*g_ppTrackedDevices_CoreAudio)*oldCap, &pDevice->pContext->allocationCallbacks);
20061  if (ppNewDevices == NULL) {
20062  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
20063  return MA_OUT_OF_MEMORY;
20064  }
20065 
20066  g_ppTrackedDevices_CoreAudio = ppNewDevices;
20067  g_TrackedDeviceCap_CoreAudio = newCap;
20068  }
20069 
20070  g_ppTrackedDevices_CoreAudio[g_TrackedDeviceCount_CoreAudio] = pDevice;
20071  g_TrackedDeviceCount_CoreAudio += 1;
20072  }
20073  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
20074 
20075  return MA_SUCCESS;
20076 }
20077 
20078 static ma_result ma_device__untrack__coreaudio(ma_device* pDevice)
20079 {
20080  MA_ASSERT(pDevice != NULL);
20081 
20082  ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
20083  {
20084  ma_uint32 iDevice;
20085  for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
20086  if (g_ppTrackedDevices_CoreAudio[iDevice] == pDevice) {
20087  /* We've found the device. We now need to remove it from the list. */
20088  ma_uint32 jDevice;
20089  for (jDevice = iDevice; jDevice < g_TrackedDeviceCount_CoreAudio-1; jDevice += 1) {
20090  g_ppTrackedDevices_CoreAudio[jDevice] = g_ppTrackedDevices_CoreAudio[jDevice+1];
20091  }
20092 
20093  g_TrackedDeviceCount_CoreAudio -= 1;
20094 
20095  /* If there's nothing else in the list we need to free memory. */
20096  if (g_TrackedDeviceCount_CoreAudio == 0) {
20097  ma__free_from_callbacks(g_ppTrackedDevices_CoreAudio, &pDevice->pContext->allocationCallbacks);
20098  g_ppTrackedDevices_CoreAudio = NULL;
20099  g_TrackedDeviceCap_CoreAudio = 0;
20100  }
20101 
20102  break;
20103  }
20104  }
20105  }
20106  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
20107 
20108  return MA_SUCCESS;
20109 }
20110 #endif
20111 
20112 #if defined(MA_APPLE_MOBILE)
20113 @interface ma_router_change_handler:NSObject {
20114  ma_device* m_pDevice;
20115 }
20116 @end
20117 
20118 @implementation ma_router_change_handler
20119 -(id)init:(ma_device*)pDevice
20120 {
20121  self = [super init];
20122  m_pDevice = pDevice;
20123 
20124  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle_route_change:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
20125 
20126  return self;
20127 }
20128 
20129 -(void)dealloc
20130 {
20131  [self remove_handler];
20132 }
20133 
20134 -(void)remove_handler
20135 {
20136  [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionRouteChangeNotification object:nil];
20137 }
20138 
20139 -(void)handle_route_change:(NSNotification*)pNotification
20140 {
20141  AVAudioSession* pSession = [AVAudioSession sharedInstance];
20142 
20143  NSInteger reason = [[[pNotification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
20144  switch (reason)
20145  {
20146  case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
20147  {
20148  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonOldDeviceUnavailable\n");
20149  } break;
20150 
20151  case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
20152  {
20153  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonNewDeviceAvailable\n");
20154  } break;
20155 
20156  case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
20157  {
20158  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory\n");
20159  } break;
20160 
20161  case AVAudioSessionRouteChangeReasonWakeFromSleep:
20162  {
20163  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonWakeFromSleep\n");
20164  } break;
20165 
20166  case AVAudioSessionRouteChangeReasonOverride:
20167  {
20168  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonOverride\n");
20169  } break;
20170 
20171  case AVAudioSessionRouteChangeReasonCategoryChange:
20172  {
20173  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonCategoryChange\n");
20174  } break;
20175 
20176  case AVAudioSessionRouteChangeReasonUnknown:
20177  default:
20178  {
20179  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonUnknown\n");
20180  } break;
20181  }
20182 
20183  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Changing Route. inputNumberChannels=%d; outputNumberOfChannels=%d\n", (int)pSession.inputNumberOfChannels, (int)pSession.outputNumberOfChannels);
20184 
20185  /* Temporarily disabling this section of code because it appears to be causing errors. */
20186 #if 0
20187  ma_uint32 previousState = ma_device_get_state(m_pDevice);
20188 
20189  if (previousState == MA_STATE_STARTED) {
20190  ma_device_stop(m_pDevice);
20191  }
20192 
20193  if (m_pDevice->type == ma_device_type_capture || m_pDevice->type == ma_device_type_duplex) {
20194  m_pDevice->capture.internalChannels = (ma_uint32)pSession.inputNumberOfChannels;
20195  m_pDevice->capture.internalSampleRate = (ma_uint32)pSession.sampleRate;
20197  }
20198  if (m_pDevice->type == ma_device_type_playback || m_pDevice->type == ma_device_type_duplex) {
20199  m_pDevice->playback.internalChannels = (ma_uint32)pSession.outputNumberOfChannels;
20200  m_pDevice->playback.internalSampleRate = (ma_uint32)pSession.sampleRate;
20202  }
20203 
20204  if (previousState == MA_STATE_STARTED) {
20205  ma_device_start(m_pDevice);
20206  }
20207 #endif
20208 }
20209 @end
20210 #endif
20211 
20212 static ma_result ma_device_uninit__coreaudio(ma_device* pDevice)
20213 {
20214  MA_ASSERT(pDevice != NULL);
20216 
20217 #if defined(MA_APPLE_DESKTOP)
20218  /*
20219  Make sure we're no longer tracking the device. It doesn't matter if we call this for a non-default device because it'll
20220  just gracefully ignore it.
20221  */
20222  ma_device__untrack__coreaudio(pDevice);
20223 #endif
20224 #if defined(MA_APPLE_MOBILE)
20225  if (pDevice->coreaudio.pRouteChangeHandler != NULL) {
20226  ma_router_change_handler* pRouteChangeHandler = (__bridge_transfer ma_router_change_handler*)pDevice->coreaudio.pRouteChangeHandler;
20227  [pRouteChangeHandler remove_handler];
20228  }
20229 #endif
20230 
20231  if (pDevice->coreaudio.audioUnitCapture != NULL) {
20232  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20233  }
20234  if (pDevice->coreaudio.audioUnitPlayback != NULL) {
20235  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20236  }
20237 
20238  if (pDevice->coreaudio.pAudioBufferList) {
20239  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
20240  }
20241 
20242  return MA_SUCCESS;
20243 }
20244 
20245 typedef struct
20246 {
20247  ma_bool32 allowNominalSampleRateChange;
20248 
20249  /* Input. */
20250  ma_format formatIn;
20251  ma_uint32 channelsIn;
20252  ma_uint32 sampleRateIn;
20253  ma_channel channelMapIn[MA_MAX_CHANNELS];
20254  ma_uint32 periodSizeInFramesIn;
20255  ma_uint32 periodSizeInMillisecondsIn;
20256  ma_uint32 periodsIn;
20257  ma_share_mode shareMode;
20258  ma_performance_profile performanceProfile;
20259  ma_bool32 registerStopEvent;
20260 
20261  /* Output. */
20262 #if defined(MA_APPLE_DESKTOP)
20263  AudioObjectID deviceObjectID;
20264 #endif
20265  AudioComponent component;
20266  AudioUnit audioUnit;
20267  AudioBufferList* pAudioBufferList; /* Only used for input devices. */
20268  ma_format formatOut;
20269  ma_uint32 channelsOut;
20270  ma_uint32 sampleRateOut;
20271  ma_channel channelMapOut[MA_MAX_CHANNELS];
20272  ma_uint32 periodSizeInFramesOut;
20273  ma_uint32 periodsOut;
20274  char deviceName[256];
20275 } ma_device_init_internal_data__coreaudio;
20276 
20277 static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_init_internal_data__coreaudio* pData, void* pDevice_DoNotReference) /* <-- pDevice is typed as void* intentionally so as to avoid accidentally referencing it. */
20278 {
20279  ma_result result;
20280  OSStatus status;
20281  UInt32 enableIOFlag;
20282  AudioStreamBasicDescription bestFormat;
20283  UInt32 actualPeriodSizeInFrames;
20284  AURenderCallbackStruct callbackInfo;
20285 #if defined(MA_APPLE_DESKTOP)
20286  AudioObjectID deviceObjectID;
20287 #else
20288  UInt32 actualPeriodSizeInFramesSize = sizeof(actualPeriodSizeInFrames);
20289 #endif
20290 
20291  /* This API should only be used for a single device type: playback or capture. No full-duplex mode. */
20292  if (deviceType == ma_device_type_duplex) {
20293  return MA_INVALID_ARGS;
20294  }
20295 
20296  MA_ASSERT(pContext != NULL);
20297  MA_ASSERT(deviceType == ma_device_type_playback || deviceType == ma_device_type_capture);
20298 
20299 #if defined(MA_APPLE_DESKTOP)
20300  pData->deviceObjectID = 0;
20301 #endif
20302  pData->component = NULL;
20303  pData->audioUnit = NULL;
20304  pData->pAudioBufferList = NULL;
20305 
20306 #if defined(MA_APPLE_DESKTOP)
20307  result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
20308  if (result != MA_SUCCESS) {
20309  return result;
20310  }
20311 
20312  pData->deviceObjectID = deviceObjectID;
20313 #endif
20314 
20315  /* Core audio doesn't really use the notion of a period so we can leave this unmodified, but not too over the top. */
20316  pData->periodsOut = pData->periodsIn;
20317  if (pData->periodsOut == 0) {
20318  pData->periodsOut = MA_DEFAULT_PERIODS;
20319  }
20320  if (pData->periodsOut > 16) {
20321  pData->periodsOut = 16;
20322  }
20323 
20324 
20325  /* Audio unit. */
20326  status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)((AudioComponent)pContext->coreaudio.component, (AudioUnit*)&pData->audioUnit);
20327  if (status != noErr) {
20328  return ma_result_from_OSStatus(status);
20329  }
20330 
20331 
20332  /* The input/output buses need to be explicitly enabled and disabled. We set the flag based on the output unit first, then we just swap it for input. */
20333  enableIOFlag = 1;
20334  if (deviceType == ma_device_type_capture) {
20335  enableIOFlag = 0;
20336  }
20337 
20338  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &enableIOFlag, sizeof(enableIOFlag));
20339  if (status != noErr) {
20340  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20341  return ma_result_from_OSStatus(status);
20342  }
20343 
20344  enableIOFlag = (enableIOFlag == 0) ? 1 : 0;
20345  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &enableIOFlag, sizeof(enableIOFlag));
20346  if (status != noErr) {
20347  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20348  return ma_result_from_OSStatus(status);
20349  }
20350 
20351 
20352  /* Set the device to use with this audio unit. This is only used on desktop since we are using defaults on mobile. */
20353 #if defined(MA_APPLE_DESKTOP)
20354  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceObjectID, sizeof(deviceObjectID));
20355  if (status != noErr) {
20356  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20357  return ma_result_from_OSStatus(result);
20358  }
20359 #else
20360  /*
20361  For some reason it looks like Apple is only allowing selection of the input device. There does not appear to be any way to change
20362  the default output route. I have no idea why this is like this, but for now we'll only be able to configure capture devices.
20363  */
20364  if (pDeviceID != NULL) {
20365  if (deviceType == ma_device_type_capture) {
20366  ma_bool32 found = MA_FALSE;
20367  NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
20368  for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
20369  if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
20370  [[AVAudioSession sharedInstance] setPreferredInput:pPortDesc error:nil];
20371  found = MA_TRUE;
20372  break;
20373  }
20374  }
20375 
20376  if (found == MA_FALSE) {
20377  return MA_DOES_NOT_EXIST;
20378  }
20379  }
20380  }
20381 #endif
20382 
20383  /*
20384  Format. This is the hardest part of initialization because there's a few variables to take into account.
20385  1) The format must be supported by the device.
20386  2) The format must be supported miniaudio.
20387  3) There's a priority that miniaudio prefers.
20388 
20389  Ideally we would like to use a format that's as close to the hardware as possible so we can get as close to a passthrough as possible. The
20390  most important property is the sample rate. miniaudio can do format conversion for any sample rate and channel count, but cannot do the same
20391  for the sample data format. If the sample data format is not supported by miniaudio it must be ignored completely.
20392 
20393  On mobile platforms this is a bit different. We just force the use of whatever the audio unit's current format is set to.
20394  */
20395  {
20396  AudioStreamBasicDescription origFormat;
20397  UInt32 origFormatSize = sizeof(origFormat);
20398  AudioUnitScope formatScope = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
20399  AudioUnitElement formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
20400 
20401  if (deviceType == ma_device_type_playback) {
20402  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &origFormat, &origFormatSize);
20403  } else {
20404  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &origFormat, &origFormatSize);
20405  }
20406  if (status != noErr) {
20407  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20408  return ma_result_from_OSStatus(status);
20409  }
20410 
20411  #if defined(MA_APPLE_DESKTOP)
20412  result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, &origFormat, &bestFormat);
20413  if (result != MA_SUCCESS) {
20414  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20415  return result;
20416  }
20417 
20418  /*
20419  Technical Note TN2091: Device input using the HAL Output Audio Unit
20420  https://developer.apple.com/library/archive/technotes/tn2091/_index.html
20421 
20422  This documentation says the following:
20423 
20424  The internal AudioConverter can handle any *simple* conversion. Typically, this means that a client can specify ANY
20425  variant of the PCM formats. Consequently, the device's sample rate should match the desired sample rate. If sample rate
20426  conversion is needed, it can be accomplished by buffering the input and converting the data on a separate thread with
20427  another AudioConverter.
20428 
20429  The important part here is the mention that it can handle *simple* conversions, which does *not* include sample rate. We
20430  therefore want to ensure the sample rate stays consistent. This document is specifically for input, but I'm going to play it
20431  safe and apply the same rule to output as well.
20432 
20433  I have tried going against the documentation by setting the sample rate anyway, but this just results in AudioUnitRender()
20434  returning a result code of -10863. I have also tried changing the format directly on the input scope on the input bus, but
20435  this just results in `ca_require: IsStreamFormatWritable(inScope, inElement) NotWritable` when trying to set the format.
20436 
20437  Something that does seem to work, however, has been setting the nominal sample rate on the deivce object. The problem with
20438  this, however, is that it actually changes the sample rate at the operating system level and not just the application. This
20439  could be intrusive to the user, however, so I don't think it's wise to make this the default. Instead I'm making this a
20440  configuration option. When the `coreaudio.allowNominalSampleRateChange` config option is set to true, changing the sample
20441  rate will be allowed. Otherwise it'll be fixed to the current sample rate. To check the system-defined sample rate, run
20442  the Audio MIDI Setup program that comes installed on macOS and observe how the sample rate changes as the sample rate is
20443  changed by miniaudio.
20444  */
20445  if (pData->allowNominalSampleRateChange) {
20446  AudioValueRange sampleRateRange;
20447  AudioObjectPropertyAddress propAddress;
20448 
20449  sampleRateRange.mMinimum = bestFormat.mSampleRate;
20450  sampleRateRange.mMaximum = bestFormat.mSampleRate;
20451 
20452  propAddress.mSelector = kAudioDevicePropertyNominalSampleRate;
20453  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
20454  propAddress.mElement = kAudioObjectPropertyElementMaster;
20455 
20456  status = ((ma_AudioObjectSetPropertyData_proc)pContext->coreaudio.AudioObjectSetPropertyData)(deviceObjectID, &propAddress, 0, NULL, sizeof(sampleRateRange), &sampleRateRange);
20457  if (status != noErr) {
20458  bestFormat.mSampleRate = origFormat.mSampleRate;
20459  }
20460  } else {
20461  bestFormat.mSampleRate = origFormat.mSampleRate;
20462  }
20463 
20464  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
20465  if (status != noErr) {
20466  /* We failed to set the format, so fall back to the current format of the audio unit. */
20467  bestFormat = origFormat;
20468  }
20469  #else
20470  bestFormat = origFormat;
20471 
20472  /*
20473  Sample rate is a little different here because for some reason kAudioUnitProperty_StreamFormat returns 0... Oh well. We need to instead try
20474  setting the sample rate to what the user has requested and then just see the results of it. Need to use some Objective-C here for this since
20475  it depends on Apple's AVAudioSession API. To do this we just get the shared AVAudioSession instance and then set it. Note that from what I
20476  can tell, it looks like the sample rate is shared between playback and capture for everything.
20477  */
20478  @autoreleasepool {
20479  AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
20480  MA_ASSERT(pAudioSession != NULL);
20481 
20482  [pAudioSession setPreferredSampleRate:(double)pData->sampleRateIn error:nil];
20483  bestFormat.mSampleRate = pAudioSession.sampleRate;
20484 
20485  /*
20486  I've had a report that the channel count returned by AudioUnitGetProperty above is inconsistent with
20487  AVAudioSession outputNumberOfChannels. I'm going to try using the AVAudioSession values instead.
20488  */
20489  if (deviceType == ma_device_type_playback) {
20490  bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.outputNumberOfChannels;
20491  }
20492  if (deviceType == ma_device_type_capture) {
20493  bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.inputNumberOfChannels;
20494  }
20495  }
20496 
20497  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
20498  if (status != noErr) {
20499  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20500  return ma_result_from_OSStatus(status);
20501  }
20502  #endif
20503 
20504  result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pData->formatOut);
20505  if (result != MA_SUCCESS) {
20506  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20507  return result;
20508  }
20509 
20510  if (pData->formatOut == ma_format_unknown) {
20511  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20512  return MA_FORMAT_NOT_SUPPORTED;
20513  }
20514 
20515  pData->channelsOut = bestFormat.mChannelsPerFrame;
20516  pData->sampleRateOut = bestFormat.mSampleRate;
20517  }
20518 
20519  /* Clamp the channel count for safety. */
20520  if (pData->channelsOut > MA_MAX_CHANNELS) {
20521  pData->channelsOut = MA_MAX_CHANNELS;
20522  }
20523 
20524  /*
20525  Internal channel map. This is weird in my testing. If I use the AudioObject to get the
20526  channel map, the channel descriptions are set to "Unknown" for some reason. To work around
20527  this it looks like retrieving it from the AudioUnit will work. However, and this is where
20528  it gets weird, it doesn't seem to work with capture devices, nor at all on iOS... Therefore
20529  I'm going to fall back to a default assumption in these cases.
20530  */
20531 #if defined(MA_APPLE_DESKTOP)
20532  result = ma_get_AudioUnit_channel_map(pContext, pData->audioUnit, deviceType, pData->channelMapOut, pData->channelsOut);
20533  if (result != MA_SUCCESS) {
20534  #if 0
20535  /* Try falling back to the channel map from the AudioObject. */
20536  result = ma_get_AudioObject_channel_map(pContext, deviceObjectID, deviceType, pData->channelMapOut, pData->channelsOut);
20537  if (result != MA_SUCCESS) {
20538  return result;
20539  }
20540  #else
20541  /* Fall back to default assumptions. */
20542  ma_get_standard_channel_map(ma_standard_channel_map_default, pData->channelsOut, pData->channelMapOut);
20543  #endif
20544  }
20545 #else
20546  /* TODO: Figure out how to get the channel map using AVAudioSession. */
20547  ma_get_standard_channel_map(ma_standard_channel_map_default, pData->channelsOut, pData->channelMapOut);
20548 #endif
20549 
20550 
20551  /* Buffer size. Not allowing this to be configurable on iOS. */
20552  if (pData->periodSizeInFramesIn == 0) {
20553  if (pData->periodSizeInMillisecondsIn == 0) {
20554  if (pData->performanceProfile == ma_performance_profile_low_latency) {
20556  } else {
20558  }
20559  } else {
20560  actualPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pData->periodSizeInMillisecondsIn, pData->sampleRateOut);
20561  }
20562  } else {
20563  actualPeriodSizeInFrames = pData->periodSizeInFramesIn;
20564  }
20565 
20566 #if defined(MA_APPLE_DESKTOP)
20567  result = ma_set_AudioObject_buffer_size_in_frames(pContext, deviceObjectID, deviceType, &actualPeriodSizeInFrames);
20568  if (result != MA_SUCCESS) {
20569  return result;
20570  }
20571 #else
20572  /*
20573  I don't know how to configure buffer sizes on iOS so for now we're not allowing it to be configured. Instead we're
20574  just going to set it to the value of kAudioUnitProperty_MaximumFramesPerSlice.
20575  */
20576  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualPeriodSizeInFrames, &actualPeriodSizeInFramesSize);
20577  if (status != noErr) {
20578  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20579  return ma_result_from_OSStatus(status);
20580  }
20581 #endif
20582 
20583 
20584  /*
20585  During testing I discovered that the buffer size can be too big. You'll get an error like this:
20586 
20587  kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=4096, mMaxFramesPerSlice=512
20588 
20589  Note how inFramesToProcess is smaller than mMaxFramesPerSlice. To fix, we need to set kAudioUnitProperty_MaximumFramesPerSlice to that
20590  of the size of our buffer, or do it the other way around and set our buffer size to the kAudioUnitProperty_MaximumFramesPerSlice.
20591  */
20592  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualPeriodSizeInFrames, sizeof(actualPeriodSizeInFrames));
20593  if (status != noErr) {
20594  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20595  return ma_result_from_OSStatus(status);
20596  }
20597 
20598  pData->periodSizeInFramesOut = (ma_uint32)actualPeriodSizeInFrames;
20599 
20600  /* We need a buffer list if this is an input device. We render into this in the input callback. */
20601  if (deviceType == ma_device_type_capture) {
20602  ma_bool32 isInterleaved = (bestFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
20603  AudioBufferList* pBufferList;
20604 
20605  pBufferList = ma_allocate_AudioBufferList__coreaudio(pData->periodSizeInFramesOut, pData->formatOut, pData->channelsOut, (isInterleaved) ? ma_stream_layout_interleaved : ma_stream_layout_deinterleaved, &pContext->allocationCallbacks);
20606  if (pBufferList == NULL) {
20607  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20608  return MA_OUT_OF_MEMORY;
20609  }
20610 
20611  pData->pAudioBufferList = pBufferList;
20612  }
20613 
20614  /* Callbacks. */
20615  callbackInfo.inputProcRefCon = pDevice_DoNotReference;
20616  if (deviceType == ma_device_type_playback) {
20617  callbackInfo.inputProc = ma_on_output__coreaudio;
20618  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &callbackInfo, sizeof(callbackInfo));
20619  if (status != noErr) {
20620  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20621  return ma_result_from_OSStatus(status);
20622  }
20623  } else {
20624  callbackInfo.inputProc = ma_on_input__coreaudio;
20625  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callbackInfo, sizeof(callbackInfo));
20626  if (status != noErr) {
20627  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20628  return ma_result_from_OSStatus(status);
20629  }
20630  }
20631 
20632  /* We need to listen for stop events. */
20633  if (pData->registerStopEvent) {
20634  status = ((ma_AudioUnitAddPropertyListener_proc)pContext->coreaudio.AudioUnitAddPropertyListener)(pData->audioUnit, kAudioOutputUnitProperty_IsRunning, on_start_stop__coreaudio, pDevice_DoNotReference);
20635  if (status != noErr) {
20636  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20637  return ma_result_from_OSStatus(status);
20638  }
20639  }
20640 
20641  /* Initialize the audio unit. */
20642  status = ((ma_AudioUnitInitialize_proc)pContext->coreaudio.AudioUnitInitialize)(pData->audioUnit);
20643  if (status != noErr) {
20644  ma__free_from_callbacks(pData->pAudioBufferList, &pContext->allocationCallbacks);
20645  pData->pAudioBufferList = NULL;
20646  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20647  return ma_result_from_OSStatus(status);
20648  }
20649 
20650  /* Grab the name. */
20651 #if defined(MA_APPLE_DESKTOP)
20652  ma_get_AudioObject_name(pContext, deviceObjectID, sizeof(pData->deviceName), pData->deviceName);
20653 #else
20654  if (deviceType == ma_device_type_playback) {
20655  ma_strcpy_s(pData->deviceName, sizeof(pData->deviceName), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
20656  } else {
20657  ma_strcpy_s(pData->deviceName, sizeof(pData->deviceName), MA_DEFAULT_CAPTURE_DEVICE_NAME);
20658  }
20659 #endif
20660 
20661  return result;
20662 }
20663 
20664 #if defined(MA_APPLE_DESKTOP)
20665 static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_type deviceType, ma_bool32 disposePreviousAudioUnit)
20666 {
20667  ma_device_init_internal_data__coreaudio data;
20668  ma_result result;
20669 
20670  /* This should only be called for playback or capture, not duplex. */
20671  if (deviceType == ma_device_type_duplex) {
20672  return MA_INVALID_ARGS;
20673  }
20674 
20675  data.allowNominalSampleRateChange = MA_FALSE; /* Don't change the nominal sample rate when switching devices. */
20676 
20677  if (deviceType == ma_device_type_capture) {
20678  data.formatIn = pDevice->capture.format;
20679  data.channelsIn = pDevice->capture.channels;
20680  data.sampleRateIn = pDevice->sampleRate;
20681  MA_COPY_MEMORY(data.channelMapIn, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
20682  data.shareMode = pDevice->capture.shareMode;
20683  data.performanceProfile = pDevice->coreaudio.originalPerformanceProfile;
20684  data.registerStopEvent = MA_TRUE;
20685 
20686  if (disposePreviousAudioUnit) {
20687  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20688  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20689  }
20690  if (pDevice->coreaudio.pAudioBufferList) {
20691  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
20692  }
20693  } else if (deviceType == ma_device_type_playback) {
20694  data.formatIn = pDevice->playback.format;
20695  data.channelsIn = pDevice->playback.channels;
20696  data.sampleRateIn = pDevice->sampleRate;
20697  MA_COPY_MEMORY(data.channelMapIn, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
20698  data.shareMode = pDevice->playback.shareMode;
20699  data.performanceProfile = pDevice->coreaudio.originalPerformanceProfile;
20700  data.registerStopEvent = (pDevice->type != ma_device_type_duplex);
20701 
20702  if (disposePreviousAudioUnit) {
20703  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20704  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20705  }
20706  }
20707  data.periodSizeInFramesIn = pDevice->coreaudio.originalPeriodSizeInFrames;
20708  data.periodSizeInMillisecondsIn = pDevice->coreaudio.originalPeriodSizeInMilliseconds;
20709  data.periodsIn = pDevice->coreaudio.originalPeriods;
20710 
20711  /* Need at least 3 periods for duplex. */
20712  if (data.periodsIn < 3 && pDevice->type == ma_device_type_duplex) {
20713  data.periodsIn = 3;
20714  }
20715 
20716  result = ma_device_init_internal__coreaudio(pDevice->pContext, deviceType, NULL, &data, (void*)pDevice);
20717  if (result != MA_SUCCESS) {
20718  return result;
20719  }
20720 
20721  if (deviceType == ma_device_type_capture) {
20722  #if defined(MA_APPLE_DESKTOP)
20723  pDevice->coreaudio.deviceObjectIDCapture = (ma_uint32)data.deviceObjectID;
20724  #endif
20725  pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
20726  pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
20727  pDevice->coreaudio.audioBufferCapInFrames = data.periodSizeInFramesOut;
20728 
20729  pDevice->capture.internalFormat = data.formatOut;
20730  pDevice->capture.internalChannels = data.channelsOut;
20731  pDevice->capture.internalSampleRate = data.sampleRateOut;
20732  MA_COPY_MEMORY(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
20733  pDevice->capture.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
20734  pDevice->capture.internalPeriods = data.periodsOut;
20735  } else if (deviceType == ma_device_type_playback) {
20736  #if defined(MA_APPLE_DESKTOP)
20737  pDevice->coreaudio.deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
20738  #endif
20739  pDevice->coreaudio.audioUnitPlayback = (ma_ptr)data.audioUnit;
20740 
20741  pDevice->playback.internalFormat = data.formatOut;
20742  pDevice->playback.internalChannels = data.channelsOut;
20743  pDevice->playback.internalSampleRate = data.sampleRateOut;
20744  MA_COPY_MEMORY(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
20745  pDevice->playback.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
20746  pDevice->playback.internalPeriods = data.periodsOut;
20747  }
20748 
20749  return MA_SUCCESS;
20750 }
20751 #endif /* MA_APPLE_DESKTOP */
20752 
20753 static ma_result ma_device_init__coreaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
20754 {
20755  ma_result result;
20756 
20757  MA_ASSERT(pDevice != NULL);
20758  MA_ASSERT(pConfig != NULL);
20759 
20760  if (pConfig->deviceType == ma_device_type_loopback) {
20762  }
20763 
20764  /* No exclusive mode with the Core Audio backend for now. */
20765  if (((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive) ||
20766  ((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive)) {
20768  }
20769 
20770  /* Capture needs to be initialized first. */
20771  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
20772  ma_device_init_internal_data__coreaudio data;
20773  data.allowNominalSampleRateChange = pConfig->coreaudio.allowNominalSampleRateChange;
20774  data.formatIn = pDescriptorCapture->format;
20775  data.channelsIn = pDescriptorCapture->channels;
20776  data.sampleRateIn = pDescriptorCapture->sampleRate;
20777  MA_COPY_MEMORY(data.channelMapIn, pDescriptorCapture->channelMap, sizeof(pDescriptorCapture->channelMap));
20778  data.periodSizeInFramesIn = pDescriptorCapture->periodSizeInFrames;
20779  data.periodSizeInMillisecondsIn = pDescriptorCapture->periodSizeInMilliseconds;
20780  data.periodsIn = pDescriptorCapture->periodCount;
20781  data.shareMode = pDescriptorCapture->shareMode;
20782  data.performanceProfile = pConfig->performanceProfile;
20783  data.registerStopEvent = MA_TRUE;
20784 
20785  /* Need at least 3 periods for duplex. */
20786  if (data.periodsIn < 3 && pConfig->deviceType == ma_device_type_duplex) {
20787  data.periodsIn = 3;
20788  }
20789 
20790  result = ma_device_init_internal__coreaudio(pDevice->pContext, ma_device_type_capture, pDescriptorCapture->pDeviceID, &data, (void*)pDevice);
20791  if (result != MA_SUCCESS) {
20792  return result;
20793  }
20794 
20795  pDevice->coreaudio.isDefaultCaptureDevice = (pConfig->capture.pDeviceID == NULL);
20796  #if defined(MA_APPLE_DESKTOP)
20797  pDevice->coreaudio.deviceObjectIDCapture = (ma_uint32)data.deviceObjectID;
20798  #endif
20799  pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
20800  pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
20801  pDevice->coreaudio.audioBufferCapInFrames = data.periodSizeInFramesOut;
20802  pDevice->coreaudio.originalPeriodSizeInFrames = pDescriptorCapture->periodSizeInFrames;
20803  pDevice->coreaudio.originalPeriodSizeInMilliseconds = pDescriptorCapture->periodSizeInMilliseconds;
20804  pDevice->coreaudio.originalPeriods = pDescriptorCapture->periodCount;
20805  pDevice->coreaudio.originalPerformanceProfile = pConfig->performanceProfile;
20806 
20807  pDescriptorCapture->format = data.formatOut;
20808  pDescriptorCapture->channels = data.channelsOut;
20809  pDescriptorCapture->sampleRate = data.sampleRateOut;
20810  MA_COPY_MEMORY(pDescriptorCapture->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
20811  pDescriptorCapture->periodSizeInFrames = data.periodSizeInFramesOut;
20812  pDescriptorCapture->periodCount = data.periodsOut;
20813 
20814  #if defined(MA_APPLE_DESKTOP)
20815  /*
20816  If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly
20817  switch the device in the background.
20818  */
20819  if (pConfig->capture.pDeviceID == NULL) {
20820  ma_device__track__coreaudio(pDevice);
20821  }
20822  #endif
20823  }
20824 
20825  /* Playback. */
20826  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
20827  ma_device_init_internal_data__coreaudio data;
20828  data.allowNominalSampleRateChange = pConfig->coreaudio.allowNominalSampleRateChange;
20829  data.formatIn = pDescriptorPlayback->format;
20830  data.channelsIn = pDescriptorPlayback->channels;
20831  data.sampleRateIn = pDescriptorPlayback->sampleRate;
20832  MA_COPY_MEMORY(data.channelMapIn, pDescriptorPlayback->channelMap, sizeof(pDescriptorPlayback->channelMap));
20833  data.shareMode = pDescriptorPlayback->shareMode;
20834  data.performanceProfile = pConfig->performanceProfile;
20835 
20836  /* In full-duplex mode we want the playback buffer to be the same size as the capture buffer. */
20837  if (pConfig->deviceType == ma_device_type_duplex) {
20838  data.periodSizeInFramesIn = pDescriptorCapture->periodSizeInFrames;
20839  data.periodsIn = pDescriptorCapture->periodCount;
20840  data.registerStopEvent = MA_FALSE;
20841  } else {
20842  data.periodSizeInFramesIn = pDescriptorPlayback->periodSizeInFrames;
20843  data.periodSizeInMillisecondsIn = pDescriptorPlayback->periodSizeInMilliseconds;
20844  data.periodsIn = pDescriptorPlayback->periodCount;
20845  data.registerStopEvent = MA_TRUE;
20846  }
20847 
20848  result = ma_device_init_internal__coreaudio(pDevice->pContext, ma_device_type_playback, pDescriptorPlayback->pDeviceID, &data, (void*)pDevice);
20849  if (result != MA_SUCCESS) {
20850  if (pConfig->deviceType == ma_device_type_duplex) {
20851  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20852  if (pDevice->coreaudio.pAudioBufferList) {
20853  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
20854  }
20855  }
20856  return result;
20857  }
20858 
20859  pDevice->coreaudio.isDefaultPlaybackDevice = (pConfig->playback.pDeviceID == NULL);
20860  #if defined(MA_APPLE_DESKTOP)
20861  pDevice->coreaudio.deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
20862  #endif
20863  pDevice->coreaudio.audioUnitPlayback = (ma_ptr)data.audioUnit;
20864  pDevice->coreaudio.originalPeriodSizeInFrames = pDescriptorPlayback->periodSizeInFrames;
20865  pDevice->coreaudio.originalPeriodSizeInMilliseconds = pDescriptorPlayback->periodSizeInMilliseconds;
20866  pDevice->coreaudio.originalPeriods = pDescriptorPlayback->periodCount;
20867  pDevice->coreaudio.originalPerformanceProfile = pConfig->performanceProfile;
20868 
20869  pDescriptorPlayback->format = data.formatOut;
20870  pDescriptorPlayback->channels = data.channelsOut;
20871  pDescriptorPlayback->sampleRate = data.sampleRateOut;
20872  MA_COPY_MEMORY(pDescriptorPlayback->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
20873  pDescriptorPlayback->periodSizeInFrames = data.periodSizeInFramesOut;
20874  pDescriptorPlayback->periodCount = data.periodsOut;
20875 
20876  #if defined(MA_APPLE_DESKTOP)
20877  /*
20878  If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly
20879  switch the device in the background.
20880  */
20881  if (pDescriptorPlayback->pDeviceID == NULL && (pConfig->deviceType != ma_device_type_duplex || pDescriptorCapture->pDeviceID != NULL)) {
20882  ma_device__track__coreaudio(pDevice);
20883  }
20884  #endif
20885  }
20886 
20887 
20888 
20889  /*
20890  When stopping the device, a callback is called on another thread. We need to wait for this callback
20891  before returning from ma_device_stop(). This event is used for this.
20892  */
20893  ma_event_init(&pDevice->coreaudio.stopEvent);
20894 
20895  /*
20896  We need to detect when a route has changed so we can update the data conversion pipeline accordingly. This is done
20897  differently on non-Desktop Apple platforms.
20898  */
20899 #if defined(MA_APPLE_MOBILE)
20900  pDevice->coreaudio.pRouteChangeHandler = (__bridge_retained void*)[[ma_router_change_handler alloc] init:pDevice];
20901 #endif
20902 
20903  return MA_SUCCESS;
20904 }
20905 
20906 
20907 static ma_result ma_device_start__coreaudio(ma_device* pDevice)
20908 {
20909  MA_ASSERT(pDevice != NULL);
20910 
20911  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
20912  OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20913  if (status != noErr) {
20914  return ma_result_from_OSStatus(status);
20915  }
20916  }
20917 
20918  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
20919  OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20920  if (status != noErr) {
20921  if (pDevice->type == ma_device_type_duplex) {
20922  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20923  }
20924  return ma_result_from_OSStatus(status);
20925  }
20926  }
20927 
20928  return MA_SUCCESS;
20929 }
20930 
20931 static ma_result ma_device_stop__coreaudio(ma_device* pDevice)
20932 {
20933  MA_ASSERT(pDevice != NULL);
20934 
20935  /* It's not clear from the documentation whether or not AudioOutputUnitStop() actually drains the device or not. */
20936 
20937  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
20938  OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20939  if (status != noErr) {
20940  return ma_result_from_OSStatus(status);
20941  }
20942  }
20943 
20944  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
20945  OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20946  if (status != noErr) {
20947  return ma_result_from_OSStatus(status);
20948  }
20949  }
20950 
20951  /* We need to wait for the callback to finish before returning. */
20952  ma_event_wait(&pDevice->coreaudio.stopEvent);
20953  return MA_SUCCESS;
20954 }
20955 
20956 
20957 static ma_result ma_context_uninit__coreaudio(ma_context* pContext)
20958 {
20959  MA_ASSERT(pContext != NULL);
20960  MA_ASSERT(pContext->backend == ma_backend_coreaudio);
20961 
20962 #if defined(MA_APPLE_MOBILE)
20963  if (!pContext->coreaudio.noAudioSessionDeactivate) {
20964  if (![[AVAudioSession sharedInstance] setActive:false error:nil]) {
20965  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to deactivate audio session.", MA_FAILED_TO_INIT_BACKEND);
20966  }
20967  }
20968 #endif
20969 
20970 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
20971  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
20972  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
20973  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
20974 #endif
20975 
20976 #if !defined(MA_APPLE_MOBILE)
20977  ma_context__uninit_device_tracking__coreaudio(pContext);
20978 #endif
20979 
20980  (void)pContext;
20981  return MA_SUCCESS;
20982 }
20983 
20984 #if defined(MA_APPLE_MOBILE)
20985 static AVAudioSessionCategory ma_to_AVAudioSessionCategory(ma_ios_session_category category)
20986 {
20987  /* The "default" and "none" categories are treated different and should not be used as an input into this function. */
20990 
20991  switch (category) {
20992  case ma_ios_session_category_ambient: return AVAudioSessionCategoryAmbient;
20993  case ma_ios_session_category_solo_ambient: return AVAudioSessionCategorySoloAmbient;
20994  case ma_ios_session_category_playback: return AVAudioSessionCategoryPlayback;
20995  case ma_ios_session_category_record: return AVAudioSessionCategoryRecord;
20996  case ma_ios_session_category_play_and_record: return AVAudioSessionCategoryPlayAndRecord;
20997  case ma_ios_session_category_multi_route: return AVAudioSessionCategoryMultiRoute;
20998  case ma_ios_session_category_none: return AVAudioSessionCategoryAmbient;
20999  case ma_ios_session_category_default: return AVAudioSessionCategoryAmbient;
21000  default: return AVAudioSessionCategoryAmbient;
21001  }
21002 }
21003 #endif
21004 
21005 static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
21006 {
21007 #if !defined(MA_APPLE_MOBILE)
21008  ma_result result;
21009 #endif
21010 
21011  MA_ASSERT(pConfig != NULL);
21012  MA_ASSERT(pContext != NULL);
21013 
21014 #if defined(MA_APPLE_MOBILE)
21015  @autoreleasepool {
21016  AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
21017  AVAudioSessionCategoryOptions options = pConfig->coreaudio.sessionCategoryOptions;
21018 
21019  MA_ASSERT(pAudioSession != NULL);
21020 
21022  /*
21023  I'm going to use trial and error to determine our default session category. First we'll try PlayAndRecord. If that fails
21024  we'll try Playback and if that fails we'll try record. If all of these fail we'll just not set the category.
21025  */
21026  #if !defined(MA_APPLE_TV) && !defined(MA_APPLE_WATCH)
21027  options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
21028  #endif
21029 
21030  if ([pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord withOptions:options error:nil]) {
21031  /* Using PlayAndRecord */
21032  } else if ([pAudioSession setCategory: AVAudioSessionCategoryPlayback withOptions:options error:nil]) {
21033  /* Using Playback */
21034  } else if ([pAudioSession setCategory: AVAudioSessionCategoryRecord withOptions:options error:nil]) {
21035  /* Using Record */
21036  } else {
21037  /* Leave as default? */
21038  }
21039  } else {
21041  if (![pAudioSession setCategory: ma_to_AVAudioSessionCategory(pConfig->coreaudio.sessionCategory) withOptions:options error:nil]) {
21042  return MA_INVALID_OPERATION; /* Failed to set session category. */
21043  }
21044  }
21045  }
21046 
21047  if (!pConfig->coreaudio.noAudioSessionActivate) {
21048  if (![pAudioSession setActive:true error:nil]) {
21049  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to activate audio session.", MA_FAILED_TO_INIT_BACKEND);
21050  }
21051  }
21052  }
21053 #endif
21054 
21055 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
21056  pContext->coreaudio.hCoreFoundation = ma_dlopen(pContext, "CoreFoundation.framework/CoreFoundation");
21057  if (pContext->coreaudio.hCoreFoundation == NULL) {
21058  return MA_API_NOT_FOUND;
21059  }
21060 
21061  pContext->coreaudio.CFStringGetCString = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFStringGetCString");
21062  pContext->coreaudio.CFRelease = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFRelease");
21063 
21064 
21065  pContext->coreaudio.hCoreAudio = ma_dlopen(pContext, "CoreAudio.framework/CoreAudio");
21066  if (pContext->coreaudio.hCoreAudio == NULL) {
21067  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
21068  return MA_API_NOT_FOUND;
21069  }
21070 
21071  pContext->coreaudio.AudioObjectGetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyData");
21072  pContext->coreaudio.AudioObjectGetPropertyDataSize = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyDataSize");
21073  pContext->coreaudio.AudioObjectSetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectSetPropertyData");
21074  pContext->coreaudio.AudioObjectAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectAddPropertyListener");
21075  pContext->coreaudio.AudioObjectRemovePropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectRemovePropertyListener");
21076 
21077  /*
21078  It looks like Apple has moved some APIs from AudioUnit into AudioToolbox on more recent versions of macOS. They are still
21079  defined in AudioUnit, but just in case they decide to remove them from there entirely I'm going to implement a fallback.
21080  The way it'll work is that it'll first try AudioUnit, and if the required symbols are not present there we'll fall back to
21081  AudioToolbox.
21082  */
21083  pContext->coreaudio.hAudioUnit = ma_dlopen(pContext, "AudioUnit.framework/AudioUnit");
21084  if (pContext->coreaudio.hAudioUnit == NULL) {
21085  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
21086  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
21087  return MA_API_NOT_FOUND;
21088  }
21089 
21090  if (ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentFindNext") == NULL) {
21091  /* Couldn't find the required symbols in AudioUnit, so fall back to AudioToolbox. */
21092  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
21093  pContext->coreaudio.hAudioUnit = ma_dlopen(pContext, "AudioToolbox.framework/AudioToolbox");
21094  if (pContext->coreaudio.hAudioUnit == NULL) {
21095  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
21096  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
21097  return MA_API_NOT_FOUND;
21098  }
21099  }
21100 
21101  pContext->coreaudio.AudioComponentFindNext = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentFindNext");
21102  pContext->coreaudio.AudioComponentInstanceDispose = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceDispose");
21103  pContext->coreaudio.AudioComponentInstanceNew = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceNew");
21104  pContext->coreaudio.AudioOutputUnitStart = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStart");
21105  pContext->coreaudio.AudioOutputUnitStop = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStop");
21106  pContext->coreaudio.AudioUnitAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitAddPropertyListener");
21107  pContext->coreaudio.AudioUnitGetPropertyInfo = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetPropertyInfo");
21108  pContext->coreaudio.AudioUnitGetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetProperty");
21109  pContext->coreaudio.AudioUnitSetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitSetProperty");
21110  pContext->coreaudio.AudioUnitInitialize = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitInitialize");
21111  pContext->coreaudio.AudioUnitRender = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitRender");
21112 #else
21113  pContext->coreaudio.CFStringGetCString = (ma_proc)CFStringGetCString;
21114  pContext->coreaudio.CFRelease = (ma_proc)CFRelease;
21115 
21116  #if defined(MA_APPLE_DESKTOP)
21117  pContext->coreaudio.AudioObjectGetPropertyData = (ma_proc)AudioObjectGetPropertyData;
21118  pContext->coreaudio.AudioObjectGetPropertyDataSize = (ma_proc)AudioObjectGetPropertyDataSize;
21119  pContext->coreaudio.AudioObjectSetPropertyData = (ma_proc)AudioObjectSetPropertyData;
21120  pContext->coreaudio.AudioObjectAddPropertyListener = (ma_proc)AudioObjectAddPropertyListener;
21121  pContext->coreaudio.AudioObjectRemovePropertyListener = (ma_proc)AudioObjectRemovePropertyListener;
21122  #endif
21123 
21124  pContext->coreaudio.AudioComponentFindNext = (ma_proc)AudioComponentFindNext;
21125  pContext->coreaudio.AudioComponentInstanceDispose = (ma_proc)AudioComponentInstanceDispose;
21126  pContext->coreaudio.AudioComponentInstanceNew = (ma_proc)AudioComponentInstanceNew;
21127  pContext->coreaudio.AudioOutputUnitStart = (ma_proc)AudioOutputUnitStart;
21128  pContext->coreaudio.AudioOutputUnitStop = (ma_proc)AudioOutputUnitStop;
21129  pContext->coreaudio.AudioUnitAddPropertyListener = (ma_proc)AudioUnitAddPropertyListener;
21130  pContext->coreaudio.AudioUnitGetPropertyInfo = (ma_proc)AudioUnitGetPropertyInfo;
21131  pContext->coreaudio.AudioUnitGetProperty = (ma_proc)AudioUnitGetProperty;
21132  pContext->coreaudio.AudioUnitSetProperty = (ma_proc)AudioUnitSetProperty;
21133  pContext->coreaudio.AudioUnitInitialize = (ma_proc)AudioUnitInitialize;
21134  pContext->coreaudio.AudioUnitRender = (ma_proc)AudioUnitRender;
21135 #endif
21136 
21137  /* Audio component. */
21138  {
21139  AudioComponentDescription desc;
21140  desc.componentType = kAudioUnitType_Output;
21141  #if defined(MA_APPLE_DESKTOP)
21142  desc.componentSubType = kAudioUnitSubType_HALOutput;
21143  #else
21144  desc.componentSubType = kAudioUnitSubType_RemoteIO;
21145  #endif
21146  desc.componentManufacturer = kAudioUnitManufacturer_Apple;
21147  desc.componentFlags = 0;
21148  desc.componentFlagsMask = 0;
21149 
21150  pContext->coreaudio.component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc);
21151  if (pContext->coreaudio.component == NULL) {
21152  #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
21153  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
21154  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
21155  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
21156  #endif
21158  }
21159  }
21160 
21161 #if !defined(MA_APPLE_MOBILE)
21162  result = ma_context__init_device_tracking__coreaudio(pContext);
21163  if (result != MA_SUCCESS) {
21164  #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
21165  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
21166  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
21167  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
21168  #endif
21169  return result;
21170  }
21171 #endif
21172 
21173  pContext->coreaudio.noAudioSessionDeactivate = pConfig->coreaudio.noAudioSessionDeactivate;
21174 
21175  pCallbacks->onContextInit = ma_context_init__coreaudio;
21176  pCallbacks->onContextUninit = ma_context_uninit__coreaudio;
21177  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__coreaudio;
21178  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__coreaudio;
21179  pCallbacks->onDeviceInit = ma_device_init__coreaudio;
21180  pCallbacks->onDeviceUninit = ma_device_uninit__coreaudio;
21181  pCallbacks->onDeviceStart = ma_device_start__coreaudio;
21182  pCallbacks->onDeviceStop = ma_device_stop__coreaudio;
21183  pCallbacks->onDeviceRead = NULL;
21184  pCallbacks->onDeviceWrite = NULL;
21185  pCallbacks->onDeviceDataLoop = NULL;
21186 
21187  return MA_SUCCESS;
21188 }
21189 #endif /* Core Audio */
21190 
21191 
21192 
21193 /******************************************************************************
21194 
21195 sndio Backend
21196 
21197 ******************************************************************************/
21198 #ifdef MA_HAS_SNDIO
21199 #include <fcntl.h>
21200 
21201 /*
21202 Only supporting OpenBSD. This did not work very well at all on FreeBSD when I tried it. Not sure if this is due
21203 to miniaudio's implementation or if it's some kind of system configuration issue, but basically the default device
21204 just doesn't emit any sound, or at times you'll hear tiny pieces. I will consider enabling this when there's
21205 demand for it or if I can get it tested and debugged more thoroughly.
21206 */
21207 #if 0
21208 #if defined(__NetBSD__) || defined(__OpenBSD__)
21209 #include <sys/audioio.h>
21210 #endif
21211 #if defined(__FreeBSD__) || defined(__DragonFly__)
21212 #include <sys/soundcard.h>
21213 #endif
21214 #endif
21215 
21216 #define MA_SIO_DEVANY "default"
21217 #define MA_SIO_PLAY 1
21218 #define MA_SIO_REC 2
21219 #define MA_SIO_NENC 8
21220 #define MA_SIO_NCHAN 8
21221 #define MA_SIO_NRATE 16
21222 #define MA_SIO_NCONF 4
21223 
21224 struct ma_sio_hdl; /* <-- Opaque */
21225 
21226 struct ma_sio_par
21227 {
21228  unsigned int bits;
21229  unsigned int bps;
21230  unsigned int sig;
21231  unsigned int le;
21232  unsigned int msb;
21233  unsigned int rchan;
21234  unsigned int pchan;
21235  unsigned int rate;
21236  unsigned int bufsz;
21237  unsigned int xrun;
21238  unsigned int round;
21239  unsigned int appbufsz;
21240  int __pad[3];
21241  unsigned int __magic;
21242 };
21243 
21244 struct ma_sio_enc
21245 {
21246  unsigned int bits;
21247  unsigned int bps;
21248  unsigned int sig;
21249  unsigned int le;
21250  unsigned int msb;
21251 };
21252 
21253 struct ma_sio_conf
21254 {
21255  unsigned int enc;
21256  unsigned int rchan;
21257  unsigned int pchan;
21258  unsigned int rate;
21259 };
21260 
21261 struct ma_sio_cap
21262 {
21263  struct ma_sio_enc enc[MA_SIO_NENC];
21264  unsigned int rchan[MA_SIO_NCHAN];
21265  unsigned int pchan[MA_SIO_NCHAN];
21266  unsigned int rate[MA_SIO_NRATE];
21267  int __pad[7];
21268  unsigned int nconf;
21269  struct ma_sio_conf confs[MA_SIO_NCONF];
21270 };
21271 
21272 typedef struct ma_sio_hdl* (* ma_sio_open_proc) (const char*, unsigned int, int);
21273 typedef void (* ma_sio_close_proc) (struct ma_sio_hdl*);
21274 typedef int (* ma_sio_setpar_proc) (struct ma_sio_hdl*, struct ma_sio_par*);
21275 typedef int (* ma_sio_getpar_proc) (struct ma_sio_hdl*, struct ma_sio_par*);
21276 typedef int (* ma_sio_getcap_proc) (struct ma_sio_hdl*, struct ma_sio_cap*);
21277 typedef size_t (* ma_sio_write_proc) (struct ma_sio_hdl*, const void*, size_t);
21278 typedef size_t (* ma_sio_read_proc) (struct ma_sio_hdl*, void*, size_t);
21279 typedef int (* ma_sio_start_proc) (struct ma_sio_hdl*);
21280 typedef int (* ma_sio_stop_proc) (struct ma_sio_hdl*);
21281 typedef int (* ma_sio_initpar_proc)(struct ma_sio_par*);
21282 
21283 static ma_uint32 ma_get_standard_sample_rate_priority_index__sndio(ma_uint32 sampleRate) /* Lower = higher priority */
21284 {
21285  ma_uint32 i;
21286  for (i = 0; i < ma_countof(g_maStandardSampleRatePriorities); ++i) {
21287  if (g_maStandardSampleRatePriorities[i] == sampleRate) {
21288  return i;
21289  }
21290  }
21291 
21292  return (ma_uint32)-1;
21293 }
21294 
21295 static ma_format ma_format_from_sio_enc__sndio(unsigned int bits, unsigned int bps, unsigned int sig, unsigned int le, unsigned int msb)
21296 {
21297  /* We only support native-endian right now. */
21298  if ((ma_is_little_endian() && le == 0) || (ma_is_big_endian() && le == 1)) {
21299  return ma_format_unknown;
21300  }
21301 
21302  if (bits == 8 && bps == 1 && sig == 0) {
21303  return ma_format_u8;
21304  }
21305  if (bits == 16 && bps == 2 && sig == 1) {
21306  return ma_format_s16;
21307  }
21308  if (bits == 24 && bps == 3 && sig == 1) {
21309  return ma_format_s24;
21310  }
21311  if (bits == 24 && bps == 4 && sig == 1 && msb == 0) {
21312  /*return ma_format_s24_32;*/
21313  }
21314  if (bits == 32 && bps == 4 && sig == 1) {
21315  return ma_format_s32;
21316  }
21317 
21318  return ma_format_unknown;
21319 }
21320 
21321 static ma_format ma_find_best_format_from_sio_cap__sndio(struct ma_sio_cap* caps)
21322 {
21323  ma_format bestFormat;
21324  unsigned int iConfig;
21325 
21326  MA_ASSERT(caps != NULL);
21327 
21328  bestFormat = ma_format_unknown;
21329  for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
21330  unsigned int iEncoding;
21331  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
21332  unsigned int bits;
21333  unsigned int bps;
21334  unsigned int sig;
21335  unsigned int le;
21336  unsigned int msb;
21337  ma_format format;
21338 
21339  if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
21340  continue;
21341  }
21342 
21343  bits = caps->enc[iEncoding].bits;
21344  bps = caps->enc[iEncoding].bps;
21345  sig = caps->enc[iEncoding].sig;
21346  le = caps->enc[iEncoding].le;
21347  msb = caps->enc[iEncoding].msb;
21348  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
21349  if (format == ma_format_unknown) {
21350  continue; /* Format not supported. */
21351  }
21352 
21353  if (bestFormat == ma_format_unknown) {
21354  bestFormat = format;
21355  } else {
21356  if (ma_get_format_priority_index(bestFormat) > ma_get_format_priority_index(format)) { /* <-- Lower = better. */
21357  bestFormat = format;
21358  }
21359  }
21360  }
21361  }
21362 
21363  return bestFormat;
21364 }
21365 
21366 static ma_uint32 ma_find_best_channels_from_sio_cap__sndio(struct ma_sio_cap* caps, ma_device_type deviceType, ma_format requiredFormat)
21367 {
21368  ma_uint32 maxChannels;
21369  unsigned int iConfig;
21370 
21371  MA_ASSERT(caps != NULL);
21372  MA_ASSERT(requiredFormat != ma_format_unknown);
21373 
21374  /* Just pick whatever configuration has the most channels. */
21375  maxChannels = 0;
21376  for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
21377  /* The encoding should be of requiredFormat. */
21378  unsigned int iEncoding;
21379  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
21380  unsigned int iChannel;
21381  unsigned int bits;
21382  unsigned int bps;
21383  unsigned int sig;
21384  unsigned int le;
21385  unsigned int msb;
21386  ma_format format;
21387 
21388  if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
21389  continue;
21390  }
21391 
21392  bits = caps->enc[iEncoding].bits;
21393  bps = caps->enc[iEncoding].bps;
21394  sig = caps->enc[iEncoding].sig;
21395  le = caps->enc[iEncoding].le;
21396  msb = caps->enc[iEncoding].msb;
21397  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
21398  if (format != requiredFormat) {
21399  continue;
21400  }
21401 
21402  /* Getting here means the format is supported. Iterate over each channel count and grab the biggest one. */
21403  for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
21404  unsigned int chan = 0;
21405  unsigned int channels;
21406 
21407  if (deviceType == ma_device_type_playback) {
21408  chan = caps->confs[iConfig].pchan;
21409  } else {
21410  chan = caps->confs[iConfig].rchan;
21411  }
21412 
21413  if ((chan & (1UL << iChannel)) == 0) {
21414  continue;
21415  }
21416 
21417  if (deviceType == ma_device_type_playback) {
21418  channels = caps->pchan[iChannel];
21419  } else {
21420  channels = caps->rchan[iChannel];
21421  }
21422 
21423  if (maxChannels < channels) {
21424  maxChannels = channels;
21425  }
21426  }
21427  }
21428  }
21429 
21430  return maxChannels;
21431 }
21432 
21433 static ma_uint32 ma_find_best_sample_rate_from_sio_cap__sndio(struct ma_sio_cap* caps, ma_device_type deviceType, ma_format requiredFormat, ma_uint32 requiredChannels)
21434 {
21435  ma_uint32 firstSampleRate;
21436  ma_uint32 bestSampleRate;
21437  unsigned int iConfig;
21438 
21439  MA_ASSERT(caps != NULL);
21440  MA_ASSERT(requiredFormat != ma_format_unknown);
21441  MA_ASSERT(requiredChannels > 0);
21442  MA_ASSERT(requiredChannels <= MA_MAX_CHANNELS);
21443 
21444  firstSampleRate = 0; /* <-- If the device does not support a standard rate we'll fall back to the first one that's found. */
21445  bestSampleRate = 0;
21446 
21447  for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
21448  /* The encoding should be of requiredFormat. */
21449  unsigned int iEncoding;
21450  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
21451  unsigned int iChannel;
21452  unsigned int bits;
21453  unsigned int bps;
21454  unsigned int sig;
21455  unsigned int le;
21456  unsigned int msb;
21457  ma_format format;
21458 
21459  if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
21460  continue;
21461  }
21462 
21463  bits = caps->enc[iEncoding].bits;
21464  bps = caps->enc[iEncoding].bps;
21465  sig = caps->enc[iEncoding].sig;
21466  le = caps->enc[iEncoding].le;
21467  msb = caps->enc[iEncoding].msb;
21468  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
21469  if (format != requiredFormat) {
21470  continue;
21471  }
21472 
21473  /* Getting here means the format is supported. Iterate over each channel count and grab the biggest one. */
21474  for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
21475  unsigned int chan = 0;
21476  unsigned int channels;
21477  unsigned int iRate;
21478 
21479  if (deviceType == ma_device_type_playback) {
21480  chan = caps->confs[iConfig].pchan;
21481  } else {
21482  chan = caps->confs[iConfig].rchan;
21483  }
21484 
21485  if ((chan & (1UL << iChannel)) == 0) {
21486  continue;
21487  }
21488 
21489  if (deviceType == ma_device_type_playback) {
21490  channels = caps->pchan[iChannel];
21491  } else {
21492  channels = caps->rchan[iChannel];
21493  }
21494 
21495  if (channels != requiredChannels) {
21496  continue;
21497  }
21498 
21499  /* Getting here means we have found a compatible encoding/channel pair. */
21500  for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
21501  ma_uint32 rate = (ma_uint32)caps->rate[iRate];
21502  ma_uint32 ratePriority;
21503 
21504  if (firstSampleRate == 0) {
21505  firstSampleRate = rate;
21506  }
21507 
21508  /* Disregard this rate if it's not a standard one. */
21509  ratePriority = ma_get_standard_sample_rate_priority_index__sndio(rate);
21510  if (ratePriority == (ma_uint32)-1) {
21511  continue;
21512  }
21513 
21514  if (ma_get_standard_sample_rate_priority_index__sndio(bestSampleRate) > ratePriority) { /* Lower = better. */
21515  bestSampleRate = rate;
21516  }
21517  }
21518  }
21519  }
21520  }
21521 
21522  /* If a standard sample rate was not found just fall back to the first one that was iterated. */
21523  if (bestSampleRate == 0) {
21524  bestSampleRate = firstSampleRate;
21525  }
21526 
21527  return bestSampleRate;
21528 }
21529 
21530 
21531 static ma_result ma_context_enumerate_devices__sndio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
21532 {
21533  ma_bool32 isTerminating = MA_FALSE;
21534  struct ma_sio_hdl* handle;
21535 
21536  MA_ASSERT(pContext != NULL);
21537  MA_ASSERT(callback != NULL);
21538 
21539  /* sndio doesn't seem to have a good device enumeration API, so I'm therefore only enumerating over default devices for now. */
21540 
21541  /* Playback. */
21542  if (!isTerminating) {
21543  handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_PLAY, 0);
21544  if (handle != NULL) {
21545  /* Supports playback. */
21546  ma_device_info deviceInfo;
21547  MA_ZERO_OBJECT(&deviceInfo);
21548  ma_strcpy_s(deviceInfo.id.sndio, sizeof(deviceInfo.id.sndio), MA_SIO_DEVANY);
21549  ma_strcpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
21550 
21551  isTerminating = !callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
21552 
21553  ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
21554  }
21555  }
21556 
21557  /* Capture. */
21558  if (!isTerminating) {
21559  handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_REC, 0);
21560  if (handle != NULL) {
21561  /* Supports capture. */
21562  ma_device_info deviceInfo;
21563  MA_ZERO_OBJECT(&deviceInfo);
21564  ma_strcpy_s(deviceInfo.id.sndio, sizeof(deviceInfo.id.sndio), "default");
21565  ma_strcpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME);
21566 
21567  isTerminating = !callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
21568 
21569  ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
21570  }
21571  }
21572 
21573  return MA_SUCCESS;
21574 }
21575 
21576 static ma_result ma_context_get_device_info__sndio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
21577 {
21578  char devid[256];
21579  struct ma_sio_hdl* handle;
21580  struct ma_sio_cap caps;
21581  unsigned int iConfig;
21582 
21583  MA_ASSERT(pContext != NULL);
21584 
21585  /* We need to open the device before we can get information about it. */
21586  if (pDeviceID == NULL) {
21587  ma_strcpy_s(devid, sizeof(devid), MA_SIO_DEVANY);
21588  ma_strcpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), (deviceType == ma_device_type_playback) ? MA_DEFAULT_PLAYBACK_DEVICE_NAME : MA_DEFAULT_CAPTURE_DEVICE_NAME);
21589  } else {
21590  ma_strcpy_s(devid, sizeof(devid), pDeviceID->sndio);
21591  ma_strcpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), devid);
21592  }
21593 
21594  handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(devid, (deviceType == ma_device_type_playback) ? MA_SIO_PLAY : MA_SIO_REC, 0);
21595  if (handle == NULL) {
21596  return MA_NO_DEVICE;
21597  }
21598 
21599  if (((ma_sio_getcap_proc)pContext->sndio.sio_getcap)(handle, &caps) == 0) {
21600  return MA_ERROR;
21601  }
21602 
21603  pDeviceInfo->nativeDataFormatCount = 0;
21604 
21605  for (iConfig = 0; iConfig < caps.nconf; iConfig += 1) {
21606  /*
21607  The main thing we care about is that the encoding is supported by miniaudio. If it is, we want to give
21608  preference to some formats over others.
21609  */
21610  unsigned int iEncoding;
21611  unsigned int iChannel;
21612  unsigned int iRate;
21613 
21614  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
21615  unsigned int bits;
21616  unsigned int bps;
21617  unsigned int sig;
21618  unsigned int le;
21619  unsigned int msb;
21620  ma_format format;
21621 
21622  if ((caps.confs[iConfig].enc & (1UL << iEncoding)) == 0) {
21623  continue;
21624  }
21625 
21626  bits = caps.enc[iEncoding].bits;
21627  bps = caps.enc[iEncoding].bps;
21628  sig = caps.enc[iEncoding].sig;
21629  le = caps.enc[iEncoding].le;
21630  msb = caps.enc[iEncoding].msb;
21631  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
21632  if (format == ma_format_unknown) {
21633  continue; /* Format not supported. */
21634  }
21635 
21636 
21637  /* Channels. */
21638  for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
21639  unsigned int chan = 0;
21640  unsigned int channels;
21641 
21642  if (deviceType == ma_device_type_playback) {
21643  chan = caps.confs[iConfig].pchan;
21644  } else {
21645  chan = caps.confs[iConfig].rchan;
21646  }
21647 
21648  if ((chan & (1UL << iChannel)) == 0) {
21649  continue;
21650  }
21651 
21652  if (deviceType == ma_device_type_playback) {
21653  channels = caps.pchan[iChannel];
21654  } else {
21655  channels = caps.rchan[iChannel];
21656  }
21657 
21658 
21659  /* Sample Rates. */
21660  for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
21661  if ((caps.confs[iConfig].rate & (1UL << iRate)) != 0) {
21662  ma_device_info_add_native_data_format(pDeviceInfo, format, channels, caps.rate[iRate], 0);
21663  }
21664  }
21665  }
21666  }
21667  }
21668 
21669  ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
21670  return MA_SUCCESS;
21671 }
21672 
21673 static ma_result ma_device_uninit__sndio(ma_device* pDevice)
21674 {
21675  MA_ASSERT(pDevice != NULL);
21676 
21677  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
21678  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)pDevice->sndio.handleCapture);
21679  }
21680 
21681  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
21682  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
21683  }
21684 
21685  return MA_SUCCESS;
21686 }
21687 
21688 static ma_result ma_device_init_handle__sndio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
21689 {
21690  const char* pDeviceName;
21691  ma_ptr handle;
21692  int openFlags = 0;
21693  struct ma_sio_cap caps;
21694  struct ma_sio_par par;
21695  const ma_device_id* pDeviceID;
21696  ma_format format;
21697  ma_uint32 channels;
21698  ma_uint32 sampleRate;
21699  ma_format internalFormat;
21700  ma_uint32 internalChannels;
21701  ma_uint32 internalSampleRate;
21702  ma_uint32 internalPeriodSizeInFrames;
21703  ma_uint32 internalPeriods;
21704 
21705  MA_ASSERT(pConfig != NULL);
21706  MA_ASSERT(deviceType != ma_device_type_duplex);
21707  MA_ASSERT(pDevice != NULL);
21708 
21709  if (deviceType == ma_device_type_capture) {
21710  openFlags = MA_SIO_REC;
21711  } else {
21712  openFlags = MA_SIO_PLAY;
21713  }
21714 
21715  pDeviceID = pDescriptor->pDeviceID;
21716  format = pDescriptor->format;
21717  channels = pDescriptor->channels;
21718  sampleRate = pDescriptor->sampleRate;
21719 
21720  pDeviceName = MA_SIO_DEVANY;
21721  if (pDeviceID != NULL) {
21722  pDeviceName = pDeviceID->sndio;
21723  }
21724 
21725  handle = (ma_ptr)((ma_sio_open_proc)pDevice->pContext->sndio.sio_open)(pDeviceName, openFlags, 0);
21726  if (handle == NULL) {
21727  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to open device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
21728  }
21729 
21730  /* We need to retrieve the device caps to determine the most appropriate format to use. */
21731  if (((ma_sio_getcap_proc)pDevice->pContext->sndio.sio_getcap)((struct ma_sio_hdl*)handle, &caps) == 0) {
21732  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)handle);
21733  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to retrieve device caps.", MA_ERROR);
21734  }
21735 
21736  /*
21737  Note: sndio reports a huge range of available channels. This is inconvenient for us because there's no real
21738  way, as far as I can tell, to get the _actual_ channel count of the device. I'm therefore restricting this
21739  to the requested channels, regardless of whether or not the default channel count is requested.
21740 
21741  For hardware devices, I'm suspecting only a single channel count will be reported and we can safely use the
21742  value returned by ma_find_best_channels_from_sio_cap__sndio().
21743  */
21744  if (deviceType == ma_device_type_capture) {
21745  if (format == ma_format_unknown) {
21746  format = ma_find_best_format_from_sio_cap__sndio(&caps);
21747  }
21748 
21749  if (channels == 0) {
21750  if (strlen(pDeviceName) > strlen("rsnd/") && strncmp(pDeviceName, "rsnd/", strlen("rsnd/")) == 0) {
21751  channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType, format);
21752  } else {
21753  channels = MA_DEFAULT_CHANNELS;
21754  }
21755  }
21756  } else {
21757  if (format == ma_format_unknown) {
21758  format = ma_find_best_format_from_sio_cap__sndio(&caps);
21759  }
21760 
21761  if (channels == 0) {
21762  if (strlen(pDeviceName) > strlen("rsnd/") && strncmp(pDeviceName, "rsnd/", strlen("rsnd/")) == 0) {
21763  channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType, format);
21764  } else {
21765  channels = MA_DEFAULT_CHANNELS;
21766  }
21767  }
21768  }
21769 
21770  if (sampleRate == 0) {
21771  sampleRate = ma_find_best_sample_rate_from_sio_cap__sndio(&caps, pConfig->deviceType, format, channels);
21772  }
21773 
21774 
21775  ((ma_sio_initpar_proc)pDevice->pContext->sndio.sio_initpar)(&par);
21776  par.msb = 0;
21777  par.le = ma_is_little_endian();
21778 
21779  switch (format) {
21780  case ma_format_u8:
21781  {
21782  par.bits = 8;
21783  par.bps = 1;
21784  par.sig = 0;
21785  } break;
21786 
21787  case ma_format_s24:
21788  {
21789  par.bits = 24;
21790  par.bps = 3;
21791  par.sig = 1;
21792  } break;
21793 
21794  case ma_format_s32:
21795  {
21796  par.bits = 32;
21797  par.bps = 4;
21798  par.sig = 1;
21799  } break;
21800 
21801  case ma_format_s16:
21802  case ma_format_f32:
21803  case ma_format_unknown:
21804  default:
21805  {
21806  par.bits = 16;
21807  par.bps = 2;
21808  par.sig = 1;
21809  } break;
21810  }
21811 
21812  if (deviceType == ma_device_type_capture) {
21813  par.rchan = channels;
21814  } else {
21815  par.pchan = channels;
21816  }
21817 
21818  par.rate = sampleRate;
21819 
21820  internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, par.rate, pConfig->performanceProfile);
21821 
21822  par.round = internalPeriodSizeInFrames;
21823  par.appbufsz = par.round * pDescriptor->periodCount;
21824 
21825  if (((ma_sio_setpar_proc)pDevice->pContext->sndio.sio_setpar)((struct ma_sio_hdl*)handle, &par) == 0) {
21826  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)handle);
21827  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to set buffer size.", MA_FORMAT_NOT_SUPPORTED);
21828  }
21829 
21830  if (((ma_sio_getpar_proc)pDevice->pContext->sndio.sio_getpar)((struct ma_sio_hdl*)handle, &par) == 0) {
21831  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)handle);
21832  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to retrieve buffer size.", MA_FORMAT_NOT_SUPPORTED);
21833  }
21834 
21835  internalFormat = ma_format_from_sio_enc__sndio(par.bits, par.bps, par.sig, par.le, par.msb);
21836  internalChannels = (deviceType == ma_device_type_capture) ? par.rchan : par.pchan;
21837  internalSampleRate = par.rate;
21838  internalPeriods = par.appbufsz / par.round;
21839  internalPeriodSizeInFrames = par.round;
21840 
21841  if (deviceType == ma_device_type_capture) {
21842  pDevice->sndio.handleCapture = handle;
21843  } else {
21844  pDevice->sndio.handlePlayback = handle;
21845  }
21846 
21847  pDescriptor->format = internalFormat;
21848  pDescriptor->channels = internalChannels;
21849  pDescriptor->sampleRate = internalSampleRate;
21851  pDescriptor->periodSizeInFrames = internalPeriodSizeInFrames;
21852  pDescriptor->periodCount = internalPeriods;
21853 
21854  #ifdef MA_DEBUG_OUTPUT
21855  {
21856  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "DEVICE INFO\n");
21857  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Format: %s\n", ma_get_format_name(internalFormat));
21858  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Channels: %d\n", internalChannels);
21859  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Sample Rate: %d\n", internalSampleRate);
21860  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Period Size: %d\n", internalPeriodSizeInFrames);
21861  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Periods: %d\n", internalPeriods);
21862  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " appbufsz: %d\n", par.appbufsz);
21863  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " round: %d\n", par.round);
21864  }
21865  #endif
21866 
21867  return MA_SUCCESS;
21868 }
21869 
21870 static ma_result ma_device_init__sndio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
21871 {
21872  MA_ASSERT(pDevice != NULL);
21873 
21874  MA_ZERO_OBJECT(&pDevice->sndio);
21875 
21876  if (pConfig->deviceType == ma_device_type_loopback) {
21878  }
21879 
21880  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
21881  ma_result result = ma_device_init_handle__sndio(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
21882  if (result != MA_SUCCESS) {
21883  return result;
21884  }
21885  }
21886 
21887  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
21888  ma_result result = ma_device_init_handle__sndio(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
21889  if (result != MA_SUCCESS) {
21890  return result;
21891  }
21892  }
21893 
21894  return MA_SUCCESS;
21895 }
21896 
21897 static ma_result ma_device_start__sndio(ma_device* pDevice)
21898 {
21899  MA_ASSERT(pDevice != NULL);
21900 
21901  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
21902  ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((struct ma_sio_hdl*)pDevice->sndio.handleCapture);
21903  }
21904 
21905  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
21906  ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback); /* <-- Doesn't actually playback until data is written. */
21907  }
21908 
21909  return MA_SUCCESS;
21910 }
21911 
21912 static ma_result ma_device_stop__sndio(ma_device* pDevice)
21913 {
21914  MA_ASSERT(pDevice != NULL);
21915 
21916  /*
21917  From the documentation:
21918 
21919  The sio_stop() function puts the audio subsystem in the same state as before sio_start() is called. It stops recording, drains the play buffer and then
21920  stops playback. If samples to play are queued but playback hasn't started yet then playback is forced immediately; playback will actually stop once the
21921  buffer is drained. In no case are samples in the play buffer discarded.
21922 
21923  Therefore, sio_stop() performs all of the necessary draining for us.
21924  */
21925 
21926  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
21927  ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((struct ma_sio_hdl*)pDevice->sndio.handleCapture);
21928  }
21929 
21930  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
21931  ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
21932  }
21933 
21934  return MA_SUCCESS;
21935 }
21936 
21937 static ma_result ma_device_write__sndio(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
21938 {
21939  int result;
21940 
21941  if (pFramesWritten != NULL) {
21942  *pFramesWritten = 0;
21943  }
21944 
21945  result = ((ma_sio_write_proc)pDevice->pContext->sndio.sio_write)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
21946  if (result == 0) {
21947  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to send data from the client to the device.", MA_IO_ERROR);
21948  }
21949 
21950  if (pFramesWritten != NULL) {
21951  *pFramesWritten = frameCount;
21952  }
21953 
21954  return MA_SUCCESS;
21955 }
21956 
21957 static ma_result ma_device_read__sndio(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
21958 {
21959  int result;
21960 
21961  if (pFramesRead != NULL) {
21962  *pFramesRead = 0;
21963  }
21964 
21965  result = ((ma_sio_read_proc)pDevice->pContext->sndio.sio_read)((struct ma_sio_hdl*)pDevice->sndio.handleCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
21966  if (result == 0) {
21967  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to read data from the device to be sent to the device.", MA_IO_ERROR);
21968  }
21969 
21970  if (pFramesRead != NULL) {
21971  *pFramesRead = frameCount;
21972  }
21973 
21974  return MA_SUCCESS;
21975 }
21976 
21977 static ma_result ma_context_uninit__sndio(ma_context* pContext)
21978 {
21979  MA_ASSERT(pContext != NULL);
21980  MA_ASSERT(pContext->backend == ma_backend_sndio);
21981 
21982  (void)pContext;
21983  return MA_SUCCESS;
21984 }
21985 
21986 static ma_result ma_context_init__sndio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
21987 {
21988 #ifndef MA_NO_RUNTIME_LINKING
21989  const char* libsndioNames[] = {
21990  "libsndio.so"
21991  };
21992  size_t i;
21993 
21994  for (i = 0; i < ma_countof(libsndioNames); ++i) {
21995  pContext->sndio.sndioSO = ma_dlopen(pContext, libsndioNames[i]);
21996  if (pContext->sndio.sndioSO != NULL) {
21997  break;
21998  }
21999  }
22000 
22001  if (pContext->sndio.sndioSO == NULL) {
22002  return MA_NO_BACKEND;
22003  }
22004 
22005  pContext->sndio.sio_open = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_open");
22006  pContext->sndio.sio_close = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_close");
22007  pContext->sndio.sio_setpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_setpar");
22008  pContext->sndio.sio_getpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_getpar");
22009  pContext->sndio.sio_getcap = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_getcap");
22010  pContext->sndio.sio_write = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_write");
22011  pContext->sndio.sio_read = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_read");
22012  pContext->sndio.sio_start = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_start");
22013  pContext->sndio.sio_stop = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_stop");
22014  pContext->sndio.sio_initpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_initpar");
22015 #else
22016  pContext->sndio.sio_open = sio_open;
22017  pContext->sndio.sio_close = sio_close;
22018  pContext->sndio.sio_setpar = sio_setpar;
22019  pContext->sndio.sio_getpar = sio_getpar;
22020  pContext->sndio.sio_getcap = sio_getcap;
22021  pContext->sndio.sio_write = sio_write;
22022  pContext->sndio.sio_read = sio_read;
22023  pContext->sndio.sio_start = sio_start;
22024  pContext->sndio.sio_stop = sio_stop;
22025  pContext->sndio.sio_initpar = sio_initpar;
22026 #endif
22027 
22028  pCallbacks->onContextInit = ma_context_init__sndio;
22029  pCallbacks->onContextUninit = ma_context_uninit__sndio;
22030  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__sndio;
22031  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__sndio;
22032  pCallbacks->onDeviceInit = ma_device_init__sndio;
22033  pCallbacks->onDeviceUninit = ma_device_uninit__sndio;
22034  pCallbacks->onDeviceStart = ma_device_start__sndio;
22035  pCallbacks->onDeviceStop = ma_device_stop__sndio;
22036  pCallbacks->onDeviceRead = ma_device_read__sndio;
22037  pCallbacks->onDeviceWrite = ma_device_write__sndio;
22038  pCallbacks->onDeviceDataLoop = NULL;
22039 
22040  (void)pConfig;
22041  return MA_SUCCESS;
22042 }
22043 #endif /* sndio */
22044 
22045 
22046 
22047 /******************************************************************************
22048 
22049 audio(4) Backend
22050 
22051 ******************************************************************************/
22052 #ifdef MA_HAS_AUDIO4
22053 #include <fcntl.h>
22054 #include <poll.h>
22055 #include <errno.h>
22056 #include <sys/stat.h>
22057 #include <sys/types.h>
22058 #include <sys/ioctl.h>
22059 #include <sys/audioio.h>
22060 
22061 #if defined(__OpenBSD__)
22062  #include <sys/param.h>
22063  #if defined(OpenBSD) && OpenBSD >= 201709
22064  #define MA_AUDIO4_USE_NEW_API
22065  #endif
22066 #endif
22067 
22068 static void ma_construct_device_id__audio4(char* id, size_t idSize, const char* base, int deviceIndex)
22069 {
22070  size_t baseLen;
22071 
22072  MA_ASSERT(id != NULL);
22073  MA_ASSERT(idSize > 0);
22074  MA_ASSERT(deviceIndex >= 0);
22075 
22076  baseLen = strlen(base);
22077  MA_ASSERT(idSize > baseLen);
22078 
22079  ma_strcpy_s(id, idSize, base);
22080  ma_itoa_s(deviceIndex, id+baseLen, idSize-baseLen, 10);
22081 }
22082 
22083 static ma_result ma_extract_device_index_from_id__audio4(const char* id, const char* base, int* pIndexOut)
22084 {
22085  size_t idLen;
22086  size_t baseLen;
22087  const char* deviceIndexStr;
22088 
22089  MA_ASSERT(id != NULL);
22090  MA_ASSERT(base != NULL);
22091  MA_ASSERT(pIndexOut != NULL);
22092 
22093  idLen = strlen(id);
22094  baseLen = strlen(base);
22095  if (idLen <= baseLen) {
22096  return MA_ERROR; /* Doesn't look like the id starts with the base. */
22097  }
22098 
22099  if (strncmp(id, base, baseLen) != 0) {
22100  return MA_ERROR; /* ID does not begin with base. */
22101  }
22102 
22103  deviceIndexStr = id + baseLen;
22104  if (deviceIndexStr[0] == '\0') {
22105  return MA_ERROR; /* No index specified in the ID. */
22106  }
22107 
22108  if (pIndexOut) {
22109  *pIndexOut = atoi(deviceIndexStr);
22110  }
22111 
22112  return MA_SUCCESS;
22113 }
22114 
22115 
22116 #if !defined(MA_AUDIO4_USE_NEW_API) /* Old API */
22117 static ma_format ma_format_from_encoding__audio4(unsigned int encoding, unsigned int precision)
22118 {
22119  if (precision == 8 && (encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR_LE || encoding == AUDIO_ENCODING_ULINEAR_BE)) {
22120  return ma_format_u8;
22121  } else {
22122  if (ma_is_little_endian() && encoding == AUDIO_ENCODING_SLINEAR_LE) {
22123  if (precision == 16) {
22124  return ma_format_s16;
22125  } else if (precision == 24) {
22126  return ma_format_s24;
22127  } else if (precision == 32) {
22128  return ma_format_s32;
22129  }
22130  } else if (ma_is_big_endian() && encoding == AUDIO_ENCODING_SLINEAR_BE) {
22131  if (precision == 16) {
22132  return ma_format_s16;
22133  } else if (precision == 24) {
22134  return ma_format_s24;
22135  } else if (precision == 32) {
22136  return ma_format_s32;
22137  }
22138  }
22139  }
22140 
22141  return ma_format_unknown; /* Encoding not supported. */
22142 }
22143 
22144 static void ma_encoding_from_format__audio4(ma_format format, unsigned int* pEncoding, unsigned int* pPrecision)
22145 {
22146  MA_ASSERT(pEncoding != NULL);
22147  MA_ASSERT(pPrecision != NULL);
22148 
22149  switch (format)
22150  {
22151  case ma_format_u8:
22152  {
22153  *pEncoding = AUDIO_ENCODING_ULINEAR;
22154  *pPrecision = 8;
22155  } break;
22156 
22157  case ma_format_s24:
22158  {
22159  *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
22160  *pPrecision = 24;
22161  } break;
22162 
22163  case ma_format_s32:
22164  {
22165  *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
22166  *pPrecision = 32;
22167  } break;
22168 
22169  case ma_format_s16:
22170  case ma_format_f32:
22171  case ma_format_unknown:
22172  default:
22173  {
22174  *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
22175  *pPrecision = 16;
22176  } break;
22177  }
22178 }
22179 
22180 static ma_format ma_format_from_prinfo__audio4(struct audio_prinfo* prinfo)
22181 {
22182  return ma_format_from_encoding__audio4(prinfo->encoding, prinfo->precision);
22183 }
22184 
22185 static ma_format ma_best_format_from_fd__audio4(int fd, ma_format preferredFormat)
22186 {
22187  audio_encoding_t encoding;
22188  ma_uint32 iFormat;
22189  int counter = 0;
22190 
22191  /* First check to see if the preferred format is supported. */
22192  if (preferredFormat != ma_format_unknown) {
22193  counter = 0;
22194  for (;;) {
22195  MA_ZERO_OBJECT(&encoding);
22196  encoding.index = counter;
22197  if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
22198  break;
22199  }
22200 
22201  if (preferredFormat == ma_format_from_encoding__audio4(encoding.encoding, encoding.precision)) {
22202  return preferredFormat; /* Found the preferred format. */
22203  }
22204 
22205  /* Getting here means this encoding does not match our preferred format so we need to more on to the next encoding. */
22206  counter += 1;
22207  }
22208  }
22209 
22210  /* Getting here means our preferred format is not supported, so fall back to our standard priorities. */
22211  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); iFormat += 1) {
22212  ma_format format = g_maFormatPriorities[iFormat];
22213 
22214  counter = 0;
22215  for (;;) {
22216  MA_ZERO_OBJECT(&encoding);
22217  encoding.index = counter;
22218  if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
22219  break;
22220  }
22221 
22222  if (format == ma_format_from_encoding__audio4(encoding.encoding, encoding.precision)) {
22223  return format; /* Found a workable format. */
22224  }
22225 
22226  /* Getting here means this encoding does not match our preferred format so we need to more on to the next encoding. */
22227  counter += 1;
22228  }
22229  }
22230 
22231  /* Getting here means not appropriate format was found. */
22232  return ma_format_unknown;
22233 }
22234 #else
22235 static ma_format ma_format_from_swpar__audio4(struct audio_swpar* par)
22236 {
22237  if (par->bits == 8 && par->bps == 1 && par->sig == 0) {
22238  return ma_format_u8;
22239  }
22240  if (par->bits == 16 && par->bps == 2 && par->sig == 1 && par->le == ma_is_little_endian()) {
22241  return ma_format_s16;
22242  }
22243  if (par->bits == 24 && par->bps == 3 && par->sig == 1 && par->le == ma_is_little_endian()) {
22244  return ma_format_s24;
22245  }
22246  if (par->bits == 32 && par->bps == 4 && par->sig == 1 && par->le == ma_is_little_endian()) {
22247  return ma_format_f32;
22248  }
22249 
22250  /* Format not supported. */
22251  return ma_format_unknown;
22252 }
22253 #endif
22254 
22255 static ma_result ma_context_get_device_info_from_fd__audio4(ma_context* pContext, ma_device_type deviceType, int fd, ma_device_info* pDeviceInfo)
22256 {
22257  audio_device_t fdDevice;
22258 
22259  MA_ASSERT(pContext != NULL);
22260  MA_ASSERT(fd >= 0);
22261  MA_ASSERT(pDeviceInfo != NULL);
22262 
22263  (void)pContext;
22264  (void)deviceType;
22265 
22266  if (ioctl(fd, AUDIO_GETDEV, &fdDevice) < 0) {
22267  return MA_ERROR; /* Failed to retrieve device info. */
22268  }
22269 
22270  /* Name. */
22271  ma_strcpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), fdDevice.name);
22272 
22273  #if !defined(MA_AUDIO4_USE_NEW_API)
22274  {
22275  audio_info_t fdInfo;
22276  int counter = 0;
22277  ma_uint32 channels;
22278  ma_uint32 sampleRate;
22279 
22280  if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
22281  return MA_ERROR;
22282  }
22283 
22284  if (deviceType == ma_device_type_playback) {
22285  channels = fdInfo.play.channels;
22286  sampleRate = fdInfo.play.sample_rate;
22287  } else {
22288  channels = fdInfo.record.channels;
22289  sampleRate = fdInfo.record.sample_rate;
22290  }
22291 
22292  /* Supported formats. We get this by looking at the encodings. */
22293  pDeviceInfo->nativeDataFormatCount = 0;
22294  for (;;) {
22295  audio_encoding_t encoding;
22296  ma_format format;
22297 
22298  MA_ZERO_OBJECT(&encoding);
22299  encoding.index = counter;
22300  if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
22301  break;
22302  }
22303 
22304  format = ma_format_from_encoding__audio4(encoding.encoding, encoding.precision);
22305  if (format != ma_format_unknown) {
22306  ma_device_info_add_native_data_format(pDeviceInfo, format, channels, sampleRate, 0);
22307  }
22308 
22309  counter += 1;
22310  }
22311  }
22312  #else
22313  {
22314  struct audio_swpar fdPar;
22315  ma_format format;
22316  ma_uint32 channels;
22317  ma_uint32 sampleRate;
22318 
22319  if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
22320  return MA_ERROR;
22321  }
22322 
22323  format = ma_format_from_swpar__audio4(&fdPar);
22324  if (format == ma_format_unknown) {
22325  return MA_FORMAT_NOT_SUPPORTED;
22326  }
22327 
22328  if (deviceType == ma_device_type_playback) {
22329  channels = fdPar.pchan;
22330  } else {
22331  channels = fdPar.rchan;
22332  }
22333 
22334  sampleRate = fdPar.rate;
22335 
22336  pDeviceInfo->nativeDataFormatCount = 0;
22337  ma_device_info_add_native_data_format(pDeviceInfo, format, channels, sampleRate, 0);
22338  }
22339  #endif
22340 
22341  return MA_SUCCESS;
22342 }
22343 
22344 static ma_result ma_context_enumerate_devices__audio4(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
22345 {
22346  const int maxDevices = 64;
22347  char devpath[256];
22348  int iDevice;
22349 
22350  MA_ASSERT(pContext != NULL);
22351  MA_ASSERT(callback != NULL);
22352 
22353  /*
22354  Every device will be named "/dev/audioN", with a "/dev/audioctlN" equivalent. We use the "/dev/audioctlN"
22355  version here since we can open it even when another process has control of the "/dev/audioN" device.
22356  */
22357  for (iDevice = 0; iDevice < maxDevices; ++iDevice) {
22358  struct stat st;
22359  int fd;
22360  ma_bool32 isTerminating = MA_FALSE;
22361 
22362  ma_strcpy_s(devpath, sizeof(devpath), "/dev/audioctl");
22363  ma_itoa_s(iDevice, devpath+strlen(devpath), sizeof(devpath)-strlen(devpath), 10);
22364 
22365  if (stat(devpath, &st) < 0) {
22366  break;
22367  }
22368 
22369  /* The device exists, but we need to check if it's usable as playback and/or capture. */
22370 
22371  /* Playback. */
22372  if (!isTerminating) {
22373  fd = open(devpath, O_RDONLY, 0);
22374  if (fd >= 0) {
22375  /* Supports playback. */
22376  ma_device_info deviceInfo;
22377  MA_ZERO_OBJECT(&deviceInfo);
22378  ma_construct_device_id__audio4(deviceInfo.id.audio4, sizeof(deviceInfo.id.audio4), "/dev/audio", iDevice);
22379  if (ma_context_get_device_info_from_fd__audio4(pContext, ma_device_type_playback, fd, &deviceInfo) == MA_SUCCESS) {
22380  isTerminating = !callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
22381  }
22382 
22383  close(fd);
22384  }
22385  }
22386 
22387  /* Capture. */
22388  if (!isTerminating) {
22389  fd = open(devpath, O_WRONLY, 0);
22390  if (fd >= 0) {
22391  /* Supports capture. */
22392  ma_device_info deviceInfo;
22393  MA_ZERO_OBJECT(&deviceInfo);
22394  ma_construct_device_id__audio4(deviceInfo.id.audio4, sizeof(deviceInfo.id.audio4), "/dev/audio", iDevice);
22395  if (ma_context_get_device_info_from_fd__audio4(pContext, ma_device_type_capture, fd, &deviceInfo) == MA_SUCCESS) {
22396  isTerminating = !callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
22397  }
22398 
22399  close(fd);
22400  }
22401  }
22402 
22403  if (isTerminating) {
22404  break;
22405  }
22406  }
22407 
22408  return MA_SUCCESS;
22409 }
22410 
22411 static ma_result ma_context_get_device_info__audio4(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
22412 {
22413  int fd = -1;
22414  int deviceIndex = -1;
22415  char ctlid[256];
22416  ma_result result;
22417 
22418  MA_ASSERT(pContext != NULL);
22419 
22420  /*
22421  We need to open the "/dev/audioctlN" device to get the info. To do this we need to extract the number
22422  from the device ID which will be in "/dev/audioN" format.
22423  */
22424  if (pDeviceID == NULL) {
22425  /* Default device. */
22426  ma_strcpy_s(ctlid, sizeof(ctlid), "/dev/audioctl");
22427  } else {
22428  /* Specific device. We need to convert from "/dev/audioN" to "/dev/audioctlN". */
22429  result = ma_extract_device_index_from_id__audio4(pDeviceID->audio4, "/dev/audio", &deviceIndex);
22430  if (result != MA_SUCCESS) {
22431  return result;
22432  }
22433 
22434  ma_construct_device_id__audio4(ctlid, sizeof(ctlid), "/dev/audioctl", deviceIndex);
22435  }
22436 
22437  fd = open(ctlid, (deviceType == ma_device_type_playback) ? O_WRONLY : O_RDONLY, 0);
22438  if (fd == -1) {
22439  return MA_NO_DEVICE;
22440  }
22441 
22442  if (deviceIndex == -1) {
22443  ma_strcpy_s(pDeviceInfo->id.audio4, sizeof(pDeviceInfo->id.audio4), "/dev/audio");
22444  } else {
22445  ma_construct_device_id__audio4(pDeviceInfo->id.audio4, sizeof(pDeviceInfo->id.audio4), "/dev/audio", deviceIndex);
22446  }
22447 
22448  result = ma_context_get_device_info_from_fd__audio4(pContext, deviceType, fd, pDeviceInfo);
22449 
22450  close(fd);
22451  return result;
22452 }
22453 
22454 static ma_result ma_device_uninit__audio4(ma_device* pDevice)
22455 {
22456  MA_ASSERT(pDevice != NULL);
22457 
22458  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
22459  close(pDevice->audio4.fdCapture);
22460  }
22461 
22462  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
22463  close(pDevice->audio4.fdPlayback);
22464  }
22465 
22466  return MA_SUCCESS;
22467 }
22468 
22469 static ma_result ma_device_init_fd__audio4(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
22470 {
22471  const char* pDefaultDeviceNames[] = {
22472  "/dev/audio",
22473  "/dev/audio0"
22474  };
22475  int fd;
22476  int fdFlags = 0;
22477  ma_format internalFormat;
22478  ma_uint32 internalChannels;
22479  ma_uint32 internalSampleRate;
22480  ma_uint32 internalPeriodSizeInFrames;
22481  ma_uint32 internalPeriods;
22482 
22483  MA_ASSERT(pConfig != NULL);
22484  MA_ASSERT(deviceType != ma_device_type_duplex);
22485  MA_ASSERT(pDevice != NULL);
22486 
22487  /* The first thing to do is open the file. */
22488  if (deviceType == ma_device_type_capture) {
22489  fdFlags = O_RDONLY;
22490  } else {
22491  fdFlags = O_WRONLY;
22492  }
22493  /*fdFlags |= O_NONBLOCK;*/
22494 
22495  if (pDescriptor->pDeviceID == NULL) {
22496  /* Default device. */
22497  size_t iDevice;
22498  for (iDevice = 0; iDevice < ma_countof(pDefaultDeviceNames); ++iDevice) {
22499  fd = open(pDefaultDeviceNames[iDevice], fdFlags, 0);
22500  if (fd != -1) {
22501  break;
22502  }
22503  }
22504  } else {
22505  /* Specific device. */
22506  fd = open(pDescriptor->pDeviceID->audio4, fdFlags, 0);
22507  }
22508 
22509  if (fd == -1) {
22510  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to open device.", ma_result_from_errno(errno));
22511  }
22512 
22513  #if !defined(MA_AUDIO4_USE_NEW_API) /* Old API */
22514  {
22515  audio_info_t fdInfo;
22516 
22517  /*
22518  The documentation is a little bit unclear to me as to how it handles formats. It says the
22519  following:
22520 
22521  Regardless of formats supported by underlying driver, the audio driver accepts the
22522  following formats.
22523 
22524  By then the next sentence says this:
22525 
22526  `encoding` and `precision` are one of the values obtained by AUDIO_GETENC.
22527 
22528  It sounds like a direct contradiction to me. I'm going to play this safe any only use the
22529  best sample format returned by AUDIO_GETENC. If the requested format is supported we'll
22530  use that, but otherwise we'll just use our standard format priorities to pick an
22531  appropriate one.
22532  */
22533  AUDIO_INITINFO(&fdInfo);
22534 
22535  /* We get the driver to do as much of the data conversion as possible. */
22536  if (deviceType == ma_device_type_capture) {
22537  fdInfo.mode = AUMODE_RECORD;
22538  ma_encoding_from_format__audio4(ma_best_format_from_fd__audio4(fd, pDescriptor->format), &fdInfo.record.encoding, &fdInfo.record.precision);
22539 
22540  if (pDescriptor->channels != 0) {
22541  fdInfo.record.channels = ma_clamp(pDescriptor->channels, 1, 12); /* From the documentation: `channels` ranges from 1 to 12. */
22542  }
22543 
22544  if (pDescriptor->sampleRate != 0) {
22545  fdInfo.record.sample_rate = ma_clamp(pDescriptor->sampleRate, 1000, 192000); /* From the documentation: `frequency` ranges from 1000Hz to 192000Hz. (They mean `sample_rate` instead of `frequency`.) */
22546  }
22547  } else {
22548  fdInfo.mode = AUMODE_PLAY;
22549  ma_encoding_from_format__audio4(ma_best_format_from_fd__audio4(fd, pDescriptor->format), &fdInfo.play.encoding, &fdInfo.play.precision);
22550 
22551  if (pDescriptor->channels != 0) {
22552  fdInfo.play.channels = ma_clamp(pDescriptor->channels, 1, 12); /* From the documentation: `channels` ranges from 1 to 12. */
22553  }
22554 
22555  if (pDescriptor->sampleRate != 0) {
22556  fdInfo.play.sample_rate = ma_clamp(pDescriptor->sampleRate, 1000, 192000); /* From the documentation: `frequency` ranges from 1000Hz to 192000Hz. (They mean `sample_rate` instead of `frequency`.) */
22557  }
22558  }
22559 
22560  if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
22561  close(fd);
22562  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to set device format. AUDIO_SETINFO failed.", MA_FORMAT_NOT_SUPPORTED);
22563  }
22564 
22565  if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
22566  close(fd);
22567  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] AUDIO_GETINFO failed.", MA_FORMAT_NOT_SUPPORTED);
22568  }
22569 
22570  if (deviceType == ma_device_type_capture) {
22571  internalFormat = ma_format_from_prinfo__audio4(&fdInfo.record);
22572  internalChannels = fdInfo.record.channels;
22573  internalSampleRate = fdInfo.record.sample_rate;
22574  } else {
22575  internalFormat = ma_format_from_prinfo__audio4(&fdInfo.play);
22576  internalChannels = fdInfo.play.channels;
22577  internalSampleRate = fdInfo.play.sample_rate;
22578  }
22579 
22580  if (internalFormat == ma_format_unknown) {
22581  close(fd);
22582  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] The device's internal device format is not supported by miniaudio. The device is unusable.", MA_FORMAT_NOT_SUPPORTED);
22583  }
22584 
22585  /* Buffer. */
22586  {
22587  ma_uint32 internalPeriodSizeInBytes;
22588 
22589  internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, internalSampleRate, pConfig->performanceProfile);
22590 
22591  internalPeriodSizeInBytes = internalPeriodSizeInFrames * ma_get_bytes_per_frame(internalFormat, internalChannels);
22592  if (internalPeriodSizeInBytes < 16) {
22593  internalPeriodSizeInBytes = 16;
22594  }
22595 
22596  internalPeriods = pDescriptor->periodCount;
22597  if (internalPeriods < 2) {
22598  internalPeriods = 2;
22599  }
22600 
22601  /* What miniaudio calls a period, audio4 calls a block. */
22602  AUDIO_INITINFO(&fdInfo);
22603  fdInfo.hiwat = internalPeriods;
22604  fdInfo.lowat = internalPeriods-1;
22605  fdInfo.blocksize = internalPeriodSizeInBytes;
22606  if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
22607  close(fd);
22608  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to set internal buffer size. AUDIO_SETINFO failed.", MA_FORMAT_NOT_SUPPORTED);
22609  }
22610 
22611  internalPeriods = fdInfo.hiwat;
22612  internalPeriodSizeInFrames = fdInfo.blocksize / ma_get_bytes_per_frame(internalFormat, internalChannels);
22613  }
22614  }
22615  #else
22616  {
22617  struct audio_swpar fdPar;
22618 
22619  /* We need to retrieve the format of the device so we can know the channel count and sample rate. Then we can calculate the buffer size. */
22620  if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
22621  close(fd);
22622  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to retrieve initial device parameters.", MA_FORMAT_NOT_SUPPORTED);
22623  }
22624 
22625  internalFormat = ma_format_from_swpar__audio4(&fdPar);
22626  internalChannels = (deviceType == ma_device_type_capture) ? fdPar.rchan : fdPar.pchan;
22627  internalSampleRate = fdPar.rate;
22628 
22629  if (internalFormat == ma_format_unknown) {
22630  close(fd);
22631  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] The device's internal device format is not supported by miniaudio. The device is unusable.", MA_FORMAT_NOT_SUPPORTED);
22632  }
22633 
22634  /* Buffer. */
22635  {
22636  ma_uint32 internalPeriodSizeInBytes;
22637 
22638  internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, internalSampleRate, pConfig->performanceProfile);
22639 
22640  /* What miniaudio calls a period, audio4 calls a block. */
22641  internalPeriodSizeInBytes = internalPeriodSizeInFrames * ma_get_bytes_per_frame(internalFormat, internalChannels);
22642  if (internalPeriodSizeInBytes < 16) {
22643  internalPeriodSizeInBytes = 16;
22644  }
22645 
22646  fdPar.nblks = pDescriptor->periodCount;
22647  fdPar.round = internalPeriodSizeInBytes;
22648 
22649  if (ioctl(fd, AUDIO_SETPAR, &fdPar) < 0) {
22650  close(fd);
22651  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to set device parameters.", MA_FORMAT_NOT_SUPPORTED);
22652  }
22653 
22654  if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
22655  close(fd);
22656  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to retrieve actual device parameters.", MA_FORMAT_NOT_SUPPORTED);
22657  }
22658  }
22659 
22660  internalFormat = ma_format_from_swpar__audio4(&fdPar);
22661  internalChannels = (deviceType == ma_device_type_capture) ? fdPar.rchan : fdPar.pchan;
22662  internalSampleRate = fdPar.rate;
22663  internalPeriods = fdPar.nblks;
22664  internalPeriodSizeInFrames = fdPar.round / ma_get_bytes_per_frame(internalFormat, internalChannels);
22665  }
22666  #endif
22667 
22668  if (internalFormat == ma_format_unknown) {
22669  close(fd);
22670  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] The device's internal device format is not supported by miniaudio. The device is unusable.", MA_FORMAT_NOT_SUPPORTED);
22671  }
22672 
22673  if (deviceType == ma_device_type_capture) {
22674  pDevice->audio4.fdCapture = fd;
22675  } else {
22676  pDevice->audio4.fdPlayback = fd;
22677  }
22678 
22679  pDescriptor->format = internalFormat;
22680  pDescriptor->channels = internalChannels;
22681  pDescriptor->sampleRate = internalSampleRate;
22683  pDescriptor->periodSizeInFrames = internalPeriodSizeInFrames;
22684  pDescriptor->periodCount = internalPeriods;
22685 
22686  return MA_SUCCESS;
22687 }
22688 
22689 static ma_result ma_device_init__audio4(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
22690 {
22691  MA_ASSERT(pDevice != NULL);
22692 
22693  MA_ZERO_OBJECT(&pDevice->audio4);
22694 
22695  if (pConfig->deviceType == ma_device_type_loopback) {
22697  }
22698 
22699  pDevice->audio4.fdCapture = -1;
22700  pDevice->audio4.fdPlayback = -1;
22701 
22702  /*
22703  The version of the operating system dictates whether or not the device is exclusive or shared. NetBSD
22704  introduced in-kernel mixing which means it's shared. All other BSD flavours are exclusive as far as
22705  I'm aware.
22706  */
22707 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 800000000
22708  /* NetBSD 8.0+ */
22709  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
22710  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
22712  }
22713 #else
22714  /* All other flavors. */
22715 #endif
22716 
22717  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
22718  ma_result result = ma_device_init_fd__audio4(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
22719  if (result != MA_SUCCESS) {
22720  return result;
22721  }
22722  }
22723 
22724  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
22725  ma_result result = ma_device_init_fd__audio4(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
22726  if (result != MA_SUCCESS) {
22727  if (pConfig->deviceType == ma_device_type_duplex) {
22728  close(pDevice->audio4.fdCapture);
22729  }
22730  return result;
22731  }
22732  }
22733 
22734  return MA_SUCCESS;
22735 }
22736 
22737 static ma_result ma_device_start__audio4(ma_device* pDevice)
22738 {
22739  MA_ASSERT(pDevice != NULL);
22740 
22741  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
22742  if (pDevice->audio4.fdCapture == -1) {
22743  return MA_INVALID_ARGS;
22744  }
22745  }
22746 
22747  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
22748  if (pDevice->audio4.fdPlayback == -1) {
22749  return MA_INVALID_ARGS;
22750  }
22751  }
22752 
22753  return MA_SUCCESS;
22754 }
22755 
22756 static ma_result ma_device_stop_fd__audio4(ma_device* pDevice, int fd)
22757 {
22758  if (fd == -1) {
22759  return MA_INVALID_ARGS;
22760  }
22761 
22762 #if !defined(MA_AUDIO4_USE_NEW_API)
22763  if (ioctl(fd, AUDIO_FLUSH, 0) < 0) {
22764  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to stop device. AUDIO_FLUSH failed.", ma_result_from_errno(errno));
22765  }
22766 #else
22767  if (ioctl(fd, AUDIO_STOP, 0) < 0) {
22768  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to stop device. AUDIO_STOP failed.", ma_result_from_errno(errno));
22769  }
22770 #endif
22771 
22772  return MA_SUCCESS;
22773 }
22774 
22775 static ma_result ma_device_stop__audio4(ma_device* pDevice)
22776 {
22777  MA_ASSERT(pDevice != NULL);
22778 
22779  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
22780  ma_result result;
22781 
22782  result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdCapture);
22783  if (result != MA_SUCCESS) {
22784  return result;
22785  }
22786  }
22787 
22788  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
22789  ma_result result;
22790 
22791  /* Drain the device first. If this fails we'll just need to flush without draining. Unfortunately draining isn't available on newer version of OpenBSD. */
22792  #if !defined(MA_AUDIO4_USE_NEW_API)
22793  ioctl(pDevice->audio4.fdPlayback, AUDIO_DRAIN, 0);
22794  #endif
22795 
22796  /* Here is where the device is stopped immediately. */
22797  result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdPlayback);
22798  if (result != MA_SUCCESS) {
22799  return result;
22800  }
22801  }
22802 
22803  return MA_SUCCESS;
22804 }
22805 
22806 static ma_result ma_device_write__audio4(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
22807 {
22808  int result;
22809 
22810  if (pFramesWritten != NULL) {
22811  *pFramesWritten = 0;
22812  }
22813 
22814  result = write(pDevice->audio4.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
22815  if (result < 0) {
22816  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to write data to the device.", ma_result_from_errno(errno));
22817  }
22818 
22819  if (pFramesWritten != NULL) {
22820  *pFramesWritten = (ma_uint32)result / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22821  }
22822 
22823  return MA_SUCCESS;
22824 }
22825 
22826 static ma_result ma_device_read__audio4(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
22827 {
22828  int result;
22829 
22830  if (pFramesRead != NULL) {
22831  *pFramesRead = 0;
22832  }
22833 
22834  result = read(pDevice->audio4.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
22835  if (result < 0) {
22836  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to read data from the device.", ma_result_from_errno(errno));
22837  }
22838 
22839  if (pFramesRead != NULL) {
22840  *pFramesRead = (ma_uint32)result / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22841  }
22842 
22843  return MA_SUCCESS;
22844 }
22845 
22846 static ma_result ma_context_uninit__audio4(ma_context* pContext)
22847 {
22848  MA_ASSERT(pContext != NULL);
22849  MA_ASSERT(pContext->backend == ma_backend_audio4);
22850 
22851  (void)pContext;
22852  return MA_SUCCESS;
22853 }
22854 
22855 static ma_result ma_context_init__audio4(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
22856 {
22857  MA_ASSERT(pContext != NULL);
22858 
22859  (void)pConfig;
22860 
22861  pCallbacks->onContextInit = ma_context_init__audio4;
22862  pCallbacks->onContextUninit = ma_context_uninit__audio4;
22863  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__audio4;
22864  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__audio4;
22865  pCallbacks->onDeviceInit = ma_device_init__audio4;
22866  pCallbacks->onDeviceUninit = ma_device_uninit__audio4;
22867  pCallbacks->onDeviceStart = ma_device_start__audio4;
22868  pCallbacks->onDeviceStop = ma_device_stop__audio4;
22869  pCallbacks->onDeviceRead = ma_device_read__audio4;
22870  pCallbacks->onDeviceWrite = ma_device_write__audio4;
22871  pCallbacks->onDeviceDataLoop = NULL;
22872 
22873  return MA_SUCCESS;
22874 }
22875 #endif /* audio4 */
22876 
22877 
22878 /******************************************************************************
22879 
22880 OSS Backend
22881 
22882 ******************************************************************************/
22883 #ifdef MA_HAS_OSS
22884 #include <sys/ioctl.h>
22885 #include <unistd.h>
22886 #include <fcntl.h>
22887 #include <sys/soundcard.h>
22888 
22889 #ifndef SNDCTL_DSP_HALT
22890 #define SNDCTL_DSP_HALT SNDCTL_DSP_RESET
22891 #endif
22892 
22893 #define MA_OSS_DEFAULT_DEVICE_NAME "/dev/dsp"
22894 
22895 static int ma_open_temp_device__oss()
22896 {
22897  /* The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same. */
22898  int fd = open("/dev/mixer", O_RDONLY, 0);
22899  if (fd >= 0) {
22900  return fd;
22901  }
22902 
22903  return -1;
22904 }
22905 
22906 static ma_result ma_context_open_device__oss(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_share_mode shareMode, int* pfd)
22907 {
22908  const char* deviceName;
22909  int flags;
22910 
22911  MA_ASSERT(pContext != NULL);
22912  MA_ASSERT(pfd != NULL);
22913  (void)pContext;
22914 
22915  *pfd = -1;
22916 
22917  /* This function should only be called for playback or capture, not duplex. */
22918  if (deviceType == ma_device_type_duplex) {
22919  return MA_INVALID_ARGS;
22920  }
22921 
22922  deviceName = MA_OSS_DEFAULT_DEVICE_NAME;
22923  if (pDeviceID != NULL) {
22924  deviceName = pDeviceID->oss;
22925  }
22926 
22927  flags = (deviceType == ma_device_type_playback) ? O_WRONLY : O_RDONLY;
22928  if (shareMode == ma_share_mode_exclusive) {
22929  flags |= O_EXCL;
22930  }
22931 
22932  *pfd = open(deviceName, flags, 0);
22933  if (*pfd == -1) {
22934  return ma_result_from_errno(errno);
22935  }
22936 
22937  return MA_SUCCESS;
22938 }
22939 
22940 static ma_result ma_context_enumerate_devices__oss(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
22941 {
22942  int fd;
22943  oss_sysinfo si;
22944  int result;
22945 
22946  MA_ASSERT(pContext != NULL);
22947  MA_ASSERT(callback != NULL);
22948 
22949  fd = ma_open_temp_device__oss();
22950  if (fd == -1) {
22951  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.", MA_NO_BACKEND);
22952  }
22953 
22954  result = ioctl(fd, SNDCTL_SYSINFO, &si);
22955  if (result != -1) {
22956  int iAudioDevice;
22957  for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
22958  oss_audioinfo ai;
22959  ai.dev = iAudioDevice;
22960  result = ioctl(fd, SNDCTL_AUDIOINFO, &ai);
22961  if (result != -1) {
22962  if (ai.devnode[0] != '\0') { /* <-- Can be blank, according to documentation. */
22963  ma_device_info deviceInfo;
22964  ma_bool32 isTerminating = MA_FALSE;
22965 
22966  MA_ZERO_OBJECT(&deviceInfo);
22967 
22968  /* ID */
22969  ma_strncpy_s(deviceInfo.id.oss, sizeof(deviceInfo.id.oss), ai.devnode, (size_t)-1);
22970 
22971  /*
22972  The human readable device name should be in the "ai.handle" variable, but it can
22973  sometimes be empty in which case we just fall back to "ai.name" which is less user
22974  friendly, but usually has a value.
22975  */
22976  if (ai.handle[0] != '\0') {
22977  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), ai.handle, (size_t)-1);
22978  } else {
22979  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), ai.name, (size_t)-1);
22980  }
22981 
22982  /* The device can be both playback and capture. */
22983  if (!isTerminating && (ai.caps & PCM_CAP_OUTPUT) != 0) {
22984  isTerminating = !callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
22985  }
22986  if (!isTerminating && (ai.caps & PCM_CAP_INPUT) != 0) {
22987  isTerminating = !callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
22988  }
22989 
22990  if (isTerminating) {
22991  break;
22992  }
22993  }
22994  }
22995  }
22996  } else {
22997  close(fd);
22998  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve system information for device enumeration.", MA_NO_BACKEND);
22999  }
23000 
23001  close(fd);
23002  return MA_SUCCESS;
23003 }
23004 
23005 static void ma_context_add_native_data_format__oss(ma_context* pContext, oss_audioinfo* pAudioInfo, ma_format format, ma_device_info* pDeviceInfo)
23006 {
23007  unsigned int minChannels;
23008  unsigned int maxChannels;
23009  unsigned int iRate;
23010 
23011  MA_ASSERT(pContext != NULL);
23012  MA_ASSERT(pAudioInfo != NULL);
23013  MA_ASSERT(pDeviceInfo != NULL);
23014 
23015  /* If we support all channels we just report 0. */
23016  minChannels = ma_clamp(pAudioInfo->min_channels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
23017  maxChannels = ma_clamp(pAudioInfo->max_channels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
23018 
23019  /*
23020  OSS has this annoying thing where sample rates can be reported in two ways. We prefer explicitness,
23021  which OSS has in the form of nrates/rates, however there are times where nrates can be 0, in which
23022  case we'll need to use min_rate and max_rate and report only standard rates.
23023  */
23024  if (pAudioInfo->nrates > 0) {
23025  for (iRate = 0; iRate < pAudioInfo->nrates; iRate += 1) {
23026  unsigned int rate = pAudioInfo->rates[iRate];
23027 
23028  if (minChannels == MA_MIN_CHANNELS && maxChannels == MA_MAX_CHANNELS) {
23029  ma_device_info_add_native_data_format(pDeviceInfo, format, 0, rate, 0); /* Set the channel count to 0 to indicate that all channel counts are supported. */
23030  } else {
23031  unsigned int iChannel;
23032  for (iChannel = minChannels; iChannel <= maxChannels; iChannel += 1) {
23033  ma_device_info_add_native_data_format(pDeviceInfo, format, iChannel, rate, 0);
23034  }
23035  }
23036  }
23037  } else {
23038  for (iRate = 0; iRate < ma_countof(g_maStandardSampleRatePriorities); iRate += 1) {
23039  ma_uint32 standardRate = g_maStandardSampleRatePriorities[iRate];
23040 
23041  if (standardRate >= (ma_uint32)pAudioInfo->min_rate && standardRate <= (ma_uint32)pAudioInfo->max_rate) {
23042  if (minChannels == MA_MIN_CHANNELS && maxChannels == MA_MAX_CHANNELS) {
23043  ma_device_info_add_native_data_format(pDeviceInfo, format, 0, standardRate, 0); /* Set the channel count to 0 to indicate that all channel counts are supported. */
23044  } else {
23045  unsigned int iChannel;
23046  for (iChannel = minChannels; iChannel <= maxChannels; iChannel += 1) {
23047  ma_device_info_add_native_data_format(pDeviceInfo, format, iChannel, standardRate, 0);
23048  }
23049  }
23050  }
23051  }
23052  }
23053 }
23054 
23055 static ma_result ma_context_get_device_info__oss(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
23056 {
23057  ma_bool32 foundDevice;
23058  int fdTemp;
23059  oss_sysinfo si;
23060  int result;
23061 
23062  MA_ASSERT(pContext != NULL);
23063 
23064  /* Handle the default device a little differently. */
23065  if (pDeviceID == NULL) {
23066  if (deviceType == ma_device_type_playback) {
23067  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
23068  } else {
23069  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
23070  }
23071 
23072  return MA_SUCCESS;
23073  }
23074 
23075 
23076  /* If we get here it means we are _not_ using the default device. */
23077  foundDevice = MA_FALSE;
23078 
23079  fdTemp = ma_open_temp_device__oss();
23080  if (fdTemp == -1) {
23081  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.", MA_NO_BACKEND);
23082  }
23083 
23084  result = ioctl(fdTemp, SNDCTL_SYSINFO, &si);
23085  if (result != -1) {
23086  int iAudioDevice;
23087  for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
23088  oss_audioinfo ai;
23089  ai.dev = iAudioDevice;
23090  result = ioctl(fdTemp, SNDCTL_AUDIOINFO, &ai);
23091  if (result != -1) {
23092  if (ma_strcmp(ai.devnode, pDeviceID->oss) == 0) {
23093  /* It has the same name, so now just confirm the type. */
23094  if ((deviceType == ma_device_type_playback && ((ai.caps & PCM_CAP_OUTPUT) != 0)) ||
23095  (deviceType == ma_device_type_capture && ((ai.caps & PCM_CAP_INPUT) != 0))) {
23096  unsigned int formatMask;
23097 
23098  /* ID */
23099  ma_strncpy_s(pDeviceInfo->id.oss, sizeof(pDeviceInfo->id.oss), ai.devnode, (size_t)-1);
23100 
23101  /*
23102  The human readable device name should be in the "ai.handle" variable, but it can
23103  sometimes be empty in which case we just fall back to "ai.name" which is less user
23104  friendly, but usually has a value.
23105  */
23106  if (ai.handle[0] != '\0') {
23107  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ai.handle, (size_t)-1);
23108  } else {
23109  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ai.name, (size_t)-1);
23110  }
23111 
23112 
23113  pDeviceInfo->nativeDataFormatCount = 0;
23114 
23115  if (deviceType == ma_device_type_playback) {
23116  formatMask = ai.oformats;
23117  } else {
23118  formatMask = ai.iformats;
23119  }
23120 
23121  if (((formatMask & AFMT_S16_LE) != 0 && ma_is_little_endian()) || (AFMT_S16_BE && ma_is_big_endian())) {
23122  ma_context_add_native_data_format__oss(pContext, &ai, ma_format_s16, pDeviceInfo);
23123  }
23124  if (((formatMask & AFMT_S32_LE) != 0 && ma_is_little_endian()) || (AFMT_S32_BE && ma_is_big_endian())) {
23125  ma_context_add_native_data_format__oss(pContext, &ai, ma_format_s32, pDeviceInfo);
23126  }
23127  if ((formatMask & AFMT_U8) != 0) {
23128  ma_context_add_native_data_format__oss(pContext, &ai, ma_format_u8, pDeviceInfo);
23129  }
23130 
23131  foundDevice = MA_TRUE;
23132  break;
23133  }
23134  }
23135  }
23136  }
23137  } else {
23138  close(fdTemp);
23139  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve system information for device enumeration.", MA_NO_BACKEND);
23140  }
23141 
23142 
23143  close(fdTemp);
23144 
23145  if (!foundDevice) {
23146  return MA_NO_DEVICE;
23147  }
23148 
23149  return MA_SUCCESS;
23150 }
23151 
23152 static ma_result ma_device_uninit__oss(ma_device* pDevice)
23153 {
23154  MA_ASSERT(pDevice != NULL);
23155 
23156  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
23157  close(pDevice->oss.fdCapture);
23158  }
23159 
23160  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
23161  close(pDevice->oss.fdPlayback);
23162  }
23163 
23164  return MA_SUCCESS;
23165 }
23166 
23167 static int ma_format_to_oss(ma_format format)
23168 {
23169  int ossFormat = AFMT_U8;
23170  switch (format) {
23171  case ma_format_s16: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break;
23172  case ma_format_s24: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break;
23173  case ma_format_s32: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break;
23174  case ma_format_f32: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break;
23175  case ma_format_u8:
23176  default: ossFormat = AFMT_U8; break;
23177  }
23178 
23179  return ossFormat;
23180 }
23181 
23182 static ma_format ma_format_from_oss(int ossFormat)
23183 {
23184  if (ossFormat == AFMT_U8) {
23185  return ma_format_u8;
23186  } else {
23187  if (ma_is_little_endian()) {
23188  switch (ossFormat) {
23189  case AFMT_S16_LE: return ma_format_s16;
23190  case AFMT_S32_LE: return ma_format_s32;
23191  default: return ma_format_unknown;
23192  }
23193  } else {
23194  switch (ossFormat) {
23195  case AFMT_S16_BE: return ma_format_s16;
23196  case AFMT_S32_BE: return ma_format_s32;
23197  default: return ma_format_unknown;
23198  }
23199  }
23200  }
23201 
23202  return ma_format_unknown;
23203 }
23204 
23205 static ma_result ma_device_init_fd__oss(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
23206 {
23207  ma_result result;
23208  int ossResult;
23209  int fd;
23210  const ma_device_id* pDeviceID = NULL;
23211  ma_share_mode shareMode;
23212  int ossFormat;
23213  int ossChannels;
23214  int ossSampleRate;
23215  int ossFragment;
23216 
23217  MA_ASSERT(pDevice != NULL);
23218  MA_ASSERT(pConfig != NULL);
23219  MA_ASSERT(deviceType != ma_device_type_duplex);
23220 
23221  pDeviceID = pDescriptor->pDeviceID;
23222  shareMode = pDescriptor->shareMode;
23223  ossFormat = ma_format_to_oss((pDescriptor->format != ma_format_unknown) ? pDescriptor->format : ma_format_s16); /* Use s16 by default because OSS doesn't like floating point. */
23224  ossChannels = (int)(pDescriptor->channels > 0) ? pDescriptor->channels : MA_DEFAULT_CHANNELS;
23225  ossSampleRate = (int)(pDescriptor->sampleRate > 0) ? pDescriptor->sampleRate : MA_DEFAULT_SAMPLE_RATE;
23226 
23227  result = ma_context_open_device__oss(pDevice->pContext, deviceType, pDeviceID, shareMode, &fd);
23228  if (result != MA_SUCCESS) {
23229  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", result);
23230  }
23231 
23232  /*
23233  The OSS documantation is very clear about the order we should be initializing the device's properties:
23234  1) Format
23235  2) Channels
23236  3) Sample rate.
23237  */
23238 
23239  /* Format. */
23240  ossResult = ioctl(fd, SNDCTL_DSP_SETFMT, &ossFormat);
23241  if (ossResult == -1) {
23242  close(fd);
23243  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set format.", MA_FORMAT_NOT_SUPPORTED);
23244  }
23245 
23246  /* Channels. */
23247  ossResult = ioctl(fd, SNDCTL_DSP_CHANNELS, &ossChannels);
23248  if (ossResult == -1) {
23249  close(fd);
23250  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set channel count.", MA_FORMAT_NOT_SUPPORTED);
23251  }
23252 
23253  /* Sample Rate. */
23254  ossResult = ioctl(fd, SNDCTL_DSP_SPEED, &ossSampleRate);
23255  if (ossResult == -1) {
23256  close(fd);
23257  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set sample rate.", MA_FORMAT_NOT_SUPPORTED);
23258  }
23259 
23260  /*
23261  Buffer.
23262 
23263  The documentation says that the fragment settings should be set as soon as possible, but I'm not sure if
23264  it should be done before or after format/channels/rate.
23265 
23266  OSS wants the fragment size in bytes and a power of 2. When setting, we specify the power, not the actual
23267  value.
23268  */
23269  {
23270  ma_uint32 periodSizeInFrames;
23271  ma_uint32 periodSizeInBytes;
23272  ma_uint32 ossFragmentSizePower;
23273 
23274  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, (ma_uint32)ossSampleRate, pConfig->performanceProfile);
23275 
23276  periodSizeInBytes = ma_round_to_power_of_2(periodSizeInFrames * ma_get_bytes_per_frame(ma_format_from_oss(ossFormat), ossChannels));
23277  if (periodSizeInBytes < 16) {
23278  periodSizeInBytes = 16;
23279  }
23280 
23281  ossFragmentSizePower = 4;
23282  periodSizeInBytes >>= 4;
23283  while (periodSizeInBytes >>= 1) {
23284  ossFragmentSizePower += 1;
23285  }
23286 
23287  ossFragment = (int)((pConfig->periods << 16) | ossFragmentSizePower);
23288  ossResult = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossFragment);
23289  if (ossResult == -1) {
23290  close(fd);
23291  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set fragment size and period count.", MA_FORMAT_NOT_SUPPORTED);
23292  }
23293  }
23294 
23295  /* Internal settings. */
23296  if (deviceType == ma_device_type_capture) {
23297  pDevice->oss.fdCapture = fd;
23298  } else {
23299  pDevice->oss.fdPlayback = fd;
23300  }
23301 
23302  pDescriptor->format = ma_format_from_oss(ossFormat);
23303  pDescriptor->channels = ossChannels;
23304  pDescriptor->sampleRate = ossSampleRate;
23306  pDescriptor->periodCount = (ma_uint32)(ossFragment >> 16);
23307  pDescriptor->periodSizeInFrames = (ma_uint32)(1 << (ossFragment & 0xFFFF)) / ma_get_bytes_per_frame(pDescriptor->format, pDescriptor->channels);
23308 
23309  if (pDescriptor->format == ma_format_unknown) {
23310  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] The device's internal format is not supported by miniaudio.", MA_FORMAT_NOT_SUPPORTED);
23311  }
23312 
23313  return MA_SUCCESS;
23314 }
23315 
23316 static ma_result ma_device_init__oss(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
23317 {
23318  MA_ASSERT(pDevice != NULL);
23319  MA_ASSERT(pConfig != NULL);
23320 
23321  MA_ZERO_OBJECT(&pDevice->oss);
23322 
23323  if (pConfig->deviceType == ma_device_type_loopback) {
23325  }
23326 
23327  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
23328  ma_result result = ma_device_init_fd__oss(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
23329  if (result != MA_SUCCESS) {
23330  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", result);
23331  }
23332  }
23333 
23334  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
23335  ma_result result = ma_device_init_fd__oss(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
23336  if (result != MA_SUCCESS) {
23337  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", result);
23338  }
23339  }
23340 
23341  return MA_SUCCESS;
23342 }
23343 
23344 /*
23345 Note on Starting and Stopping
23346 =============================
23347 In the past I was using SNDCTL_DSP_HALT to stop the device, however this results in issues when
23348 trying to resume the device again. If we use SNDCTL_DSP_HALT, the next write() or read() will
23349 fail. Instead what we need to do is just not write or read to and from the device when the
23350 device is not running.
23351 
23352 As a result, both the start and stop functions for OSS are just empty stubs. The starting and
23353 stopping logic is handled by ma_device_write__oss() and ma_device_read__oss(). These will check
23354 the device state, and if the device is stopped they will simply not do any kind of processing.
23355 
23356 The downside to this technique is that I've noticed a fairly lengthy delay in stopping the
23357 device, up to a second. This is on a virtual machine, and as such might just be due to the
23358 virtual drivers, but I'm not fully sure. I am not sure how to work around this problem so for
23359 the moment that's just how it's going to have to be.
23360 
23361 When starting the device, OSS will automatically start it when write() or read() is called.
23362 */
23363 static ma_result ma_device_start__oss(ma_device* pDevice)
23364 {
23365  MA_ASSERT(pDevice != NULL);
23366 
23367  /* The device is automatically started with reading and writing. */
23368  (void)pDevice;
23369 
23370  return MA_SUCCESS;
23371 }
23372 
23373 static ma_result ma_device_stop__oss(ma_device* pDevice)
23374 {
23375  MA_ASSERT(pDevice != NULL);
23376 
23377  /* See note above on why this is empty. */
23378  (void)pDevice;
23379 
23380  return MA_SUCCESS;
23381 }
23382 
23383 static ma_result ma_device_write__oss(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
23384 {
23385  int resultOSS;
23386  ma_uint32 deviceState;
23387 
23388  if (pFramesWritten != NULL) {
23389  *pFramesWritten = 0;
23390  }
23391 
23392  /* Don't do any processing if the device is stopped. */
23393  deviceState = ma_device_get_state(pDevice);
23394  if (deviceState != MA_STATE_STARTED && deviceState != MA_STATE_STARTING) {
23395  return MA_SUCCESS;
23396  }
23397 
23398  resultOSS = write(pDevice->oss.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
23399  if (resultOSS < 0) {
23400  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to send data from the client to the device.", ma_result_from_errno(errno));
23401  }
23402 
23403  if (pFramesWritten != NULL) {
23404  *pFramesWritten = (ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
23405  }
23406 
23407  return MA_SUCCESS;
23408 }
23409 
23410 static ma_result ma_device_read__oss(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
23411 {
23412  int resultOSS;
23413  ma_uint32 deviceState;
23414 
23415  if (pFramesRead != NULL) {
23416  *pFramesRead = 0;
23417  }
23418 
23419  /* Don't do any processing if the device is stopped. */
23420  deviceState = ma_device_get_state(pDevice);
23421  if (deviceState != MA_STATE_STARTED && deviceState != MA_STATE_STARTING) {
23422  return MA_SUCCESS;
23423  }
23424 
23425  resultOSS = read(pDevice->oss.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
23426  if (resultOSS < 0) {
23427  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to read data from the device to be sent to the client.", ma_result_from_errno(errno));
23428  }
23429 
23430  if (pFramesRead != NULL) {
23431  *pFramesRead = (ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
23432  }
23433 
23434  return MA_SUCCESS;
23435 }
23436 
23437 static ma_result ma_context_uninit__oss(ma_context* pContext)
23438 {
23439  MA_ASSERT(pContext != NULL);
23440  MA_ASSERT(pContext->backend == ma_backend_oss);
23441 
23442  (void)pContext;
23443  return MA_SUCCESS;
23444 }
23445 
23446 static ma_result ma_context_init__oss(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
23447 {
23448  int fd;
23449  int ossVersion;
23450  int result;
23451 
23452  MA_ASSERT(pContext != NULL);
23453 
23454  (void)pConfig;
23455 
23456  /* Try opening a temporary device first so we can get version information. This is closed at the end. */
23457  fd = ma_open_temp_device__oss();
23458  if (fd == -1) {
23459  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open temporary device for retrieving system properties.", MA_NO_BACKEND); /* Looks liks OSS isn't installed, or there are no available devices. */
23460  }
23461 
23462  /* Grab the OSS version. */
23463  ossVersion = 0;
23464  result = ioctl(fd, OSS_GETVERSION, &ossVersion);
23465  if (result == -1) {
23466  close(fd);
23467  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve OSS version.", MA_NO_BACKEND);
23468  }
23469 
23470  /* The file handle to temp device is no longer needed. Close ASAP. */
23471  close(fd);
23472 
23473  pContext->oss.versionMajor = ((ossVersion & 0xFF0000) >> 16);
23474  pContext->oss.versionMinor = ((ossVersion & 0x00FF00) >> 8);
23475 
23476  pCallbacks->onContextInit = ma_context_init__oss;
23477  pCallbacks->onContextUninit = ma_context_uninit__oss;
23478  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__oss;
23479  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__oss;
23480  pCallbacks->onDeviceInit = ma_device_init__oss;
23481  pCallbacks->onDeviceUninit = ma_device_uninit__oss;
23482  pCallbacks->onDeviceStart = ma_device_start__oss;
23483  pCallbacks->onDeviceStop = ma_device_stop__oss;
23484  pCallbacks->onDeviceRead = ma_device_read__oss;
23485  pCallbacks->onDeviceWrite = ma_device_write__oss;
23486  pCallbacks->onDeviceDataLoop = NULL;
23487 
23488  return MA_SUCCESS;
23489 }
23490 #endif /* OSS */
23491 
23492 
23493 /******************************************************************************
23494 
23495 AAudio Backend
23496 
23497 ******************************************************************************/
23498 #ifdef MA_HAS_AAUDIO
23499 
23500 /*#include <AAudio/AAudio.h>*/
23501 
23502 typedef int32_t ma_aaudio_result_t;
23503 typedef int32_t ma_aaudio_direction_t;
23504 typedef int32_t ma_aaudio_sharing_mode_t;
23505 typedef int32_t ma_aaudio_format_t;
23506 typedef int32_t ma_aaudio_stream_state_t;
23507 typedef int32_t ma_aaudio_performance_mode_t;
23508 typedef int32_t ma_aaudio_usage_t;
23509 typedef int32_t ma_aaudio_content_type_t;
23510 typedef int32_t ma_aaudio_input_preset_t;
23511 typedef int32_t ma_aaudio_data_callback_result_t;
23512 typedef struct ma_AAudioStreamBuilder_t* ma_AAudioStreamBuilder;
23513 typedef struct ma_AAudioStream_t* ma_AAudioStream;
23514 
23515 #define MA_AAUDIO_UNSPECIFIED 0
23516 
23517 /* Result codes. miniaudio only cares about the success code. */
23518 #define MA_AAUDIO_OK 0
23519 
23520 /* Directions. */
23521 #define MA_AAUDIO_DIRECTION_OUTPUT 0
23522 #define MA_AAUDIO_DIRECTION_INPUT 1
23523 
23524 /* Sharing modes. */
23525 #define MA_AAUDIO_SHARING_MODE_EXCLUSIVE 0
23526 #define MA_AAUDIO_SHARING_MODE_SHARED 1
23527 
23528 /* Formats. */
23529 #define MA_AAUDIO_FORMAT_PCM_I16 1
23530 #define MA_AAUDIO_FORMAT_PCM_FLOAT 2
23531 
23532 /* Stream states. */
23533 #define MA_AAUDIO_STREAM_STATE_UNINITIALIZED 0
23534 #define MA_AAUDIO_STREAM_STATE_UNKNOWN 1
23535 #define MA_AAUDIO_STREAM_STATE_OPEN 2
23536 #define MA_AAUDIO_STREAM_STATE_STARTING 3
23537 #define MA_AAUDIO_STREAM_STATE_STARTED 4
23538 #define MA_AAUDIO_STREAM_STATE_PAUSING 5
23539 #define MA_AAUDIO_STREAM_STATE_PAUSED 6
23540 #define MA_AAUDIO_STREAM_STATE_FLUSHING 7
23541 #define MA_AAUDIO_STREAM_STATE_FLUSHED 8
23542 #define MA_AAUDIO_STREAM_STATE_STOPPING 9
23543 #define MA_AAUDIO_STREAM_STATE_STOPPED 10
23544 #define MA_AAUDIO_STREAM_STATE_CLOSING 11
23545 #define MA_AAUDIO_STREAM_STATE_CLOSED 12
23546 #define MA_AAUDIO_STREAM_STATE_DISCONNECTED 13
23547 
23548 /* Performance modes. */
23549 #define MA_AAUDIO_PERFORMANCE_MODE_NONE 10
23550 #define MA_AAUDIO_PERFORMANCE_MODE_POWER_SAVING 11
23551 #define MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY 12
23552 
23553 /* Usage types. */
23554 #define MA_AAUDIO_USAGE_MEDIA 1
23555 #define MA_AAUDIO_USAGE_VOICE_COMMUNICATION 2
23556 #define MA_AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING 3
23557 #define MA_AAUDIO_USAGE_ALARM 4
23558 #define MA_AAUDIO_USAGE_NOTIFICATION 5
23559 #define MA_AAUDIO_USAGE_NOTIFICATION_RINGTONE 6
23560 #define MA_AAUDIO_USAGE_NOTIFICATION_EVENT 10
23561 #define MA_AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY 11
23562 #define MA_AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE 12
23563 #define MA_AAUDIO_USAGE_ASSISTANCE_SONIFICATION 13
23564 #define MA_AAUDIO_USAGE_GAME 14
23565 #define MA_AAUDIO_USAGE_ASSISTANT 16
23566 #define MA_AAUDIO_SYSTEM_USAGE_EMERGENCY 1000
23567 #define MA_AAUDIO_SYSTEM_USAGE_SAFETY 1001
23568 #define MA_AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS 1002
23569 #define MA_AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT 1003
23570 
23571 /* Content types. */
23572 #define MA_AAUDIO_CONTENT_TYPE_SPEECH 1
23573 #define MA_AAUDIO_CONTENT_TYPE_MUSIC 2
23574 #define MA_AAUDIO_CONTENT_TYPE_MOVIE 3
23575 #define MA_AAUDIO_CONTENT_TYPE_SONIFICATION 4
23576 
23577 /* Input presets. */
23578 #define MA_AAUDIO_INPUT_PRESET_GENERIC 1
23579 #define MA_AAUDIO_INPUT_PRESET_CAMCORDER 5
23580 #define MA_AAUDIO_INPUT_PRESET_VOICE_RECOGNITION 6
23581 #define MA_AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION 7
23582 #define MA_AAUDIO_INPUT_PRESET_UNPROCESSED 9
23583 #define MA_AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE 10
23584 
23585 /* Callback results. */
23586 #define MA_AAUDIO_CALLBACK_RESULT_CONTINUE 0
23587 #define MA_AAUDIO_CALLBACK_RESULT_STOP 1
23588 
23589 
23590 typedef ma_aaudio_data_callback_result_t (* ma_AAudioStream_dataCallback) (ma_AAudioStream* pStream, void* pUserData, void* pAudioData, int32_t numFrames);
23591 typedef void (* ma_AAudioStream_errorCallback)(ma_AAudioStream *pStream, void *pUserData, ma_aaudio_result_t error);
23592 
23593 typedef ma_aaudio_result_t (* MA_PFN_AAudio_createStreamBuilder) (ma_AAudioStreamBuilder** ppBuilder);
23594 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_delete) (ma_AAudioStreamBuilder* pBuilder);
23595 typedef void (* MA_PFN_AAudioStreamBuilder_setDeviceId) (ma_AAudioStreamBuilder* pBuilder, int32_t deviceId);
23596 typedef void (* MA_PFN_AAudioStreamBuilder_setDirection) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_direction_t direction);
23597 typedef void (* MA_PFN_AAudioStreamBuilder_setSharingMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_sharing_mode_t sharingMode);
23598 typedef void (* MA_PFN_AAudioStreamBuilder_setFormat) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_format_t format);
23599 typedef void (* MA_PFN_AAudioStreamBuilder_setChannelCount) (ma_AAudioStreamBuilder* pBuilder, int32_t channelCount);
23600 typedef void (* MA_PFN_AAudioStreamBuilder_setSampleRate) (ma_AAudioStreamBuilder* pBuilder, int32_t sampleRate);
23601 typedef void (* MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)(ma_AAudioStreamBuilder* pBuilder, int32_t numFrames);
23602 typedef void (* MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback) (ma_AAudioStreamBuilder* pBuilder, int32_t numFrames);
23603 typedef void (* MA_PFN_AAudioStreamBuilder_setDataCallback) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream_dataCallback callback, void* pUserData);
23604 typedef void (* MA_PFN_AAudioStreamBuilder_setErrorCallback) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream_errorCallback callback, void* pUserData);
23605 typedef void (* MA_PFN_AAudioStreamBuilder_setPerformanceMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_performance_mode_t mode);
23606 typedef void (* MA_PFN_AAudioStreamBuilder_setUsage) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_usage_t contentType);
23607 typedef void (* MA_PFN_AAudioStreamBuilder_setContentType) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_content_type_t contentType);
23608 typedef void (* MA_PFN_AAudioStreamBuilder_setInputPreset) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_input_preset_t inputPreset);
23609 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_openStream) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream** ppStream);
23610 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_close) (ma_AAudioStream* pStream);
23611 typedef ma_aaudio_stream_state_t (* MA_PFN_AAudioStream_getState) (ma_AAudioStream* pStream);
23612 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_waitForStateChange) (ma_AAudioStream* pStream, ma_aaudio_stream_state_t inputState, ma_aaudio_stream_state_t* pNextState, int64_t timeoutInNanoseconds);
23613 typedef ma_aaudio_format_t (* MA_PFN_AAudioStream_getFormat) (ma_AAudioStream* pStream);
23614 typedef int32_t (* MA_PFN_AAudioStream_getChannelCount) (ma_AAudioStream* pStream);
23615 typedef int32_t (* MA_PFN_AAudioStream_getSampleRate) (ma_AAudioStream* pStream);
23616 typedef int32_t (* MA_PFN_AAudioStream_getBufferCapacityInFrames) (ma_AAudioStream* pStream);
23617 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerDataCallback) (ma_AAudioStream* pStream);
23618 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerBurst) (ma_AAudioStream* pStream);
23619 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStart) (ma_AAudioStream* pStream);
23620 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStop) (ma_AAudioStream* pStream);
23621 
23622 static ma_result ma_result_from_aaudio(ma_aaudio_result_t resultAA)
23623 {
23624  switch (resultAA)
23625  {
23626  case MA_AAUDIO_OK: return MA_SUCCESS;
23627  default: break;
23628  }
23629 
23630  return MA_ERROR;
23631 }
23632 
23633 static ma_aaudio_usage_t ma_to_usage__aaudio(ma_aaudio_usage usage)
23634 {
23635  switch (usage) {
23636  case ma_aaudio_usage_announcement: return MA_AAUDIO_USAGE_MEDIA;
23637  case ma_aaudio_usage_emergency: return MA_AAUDIO_USAGE_VOICE_COMMUNICATION;
23638  case ma_aaudio_usage_safety: return MA_AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
23639  case ma_aaudio_usage_vehicle_status: return MA_AAUDIO_USAGE_ALARM;
23640  case ma_aaudio_usage_alarm: return MA_AAUDIO_USAGE_NOTIFICATION;
23641  case ma_aaudio_usage_assistance_accessibility: return MA_AAUDIO_USAGE_NOTIFICATION_RINGTONE;
23642  case ma_aaudio_usage_assistance_navigation_guidance: return MA_AAUDIO_USAGE_NOTIFICATION_EVENT;
23643  case ma_aaudio_usage_assistance_sonification: return MA_AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
23644  case ma_aaudio_usage_assitant: return MA_AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
23645  case ma_aaudio_usage_game: return MA_AAUDIO_USAGE_ASSISTANCE_SONIFICATION;
23646  case ma_aaudio_usage_media: return MA_AAUDIO_USAGE_GAME;
23647  case ma_aaudio_usage_notification: return MA_AAUDIO_USAGE_ASSISTANT;
23648  case ma_aaudio_usage_notification_event: return MA_AAUDIO_SYSTEM_USAGE_EMERGENCY;
23649  case ma_aaudio_usage_notification_ringtone: return MA_AAUDIO_SYSTEM_USAGE_SAFETY;
23650  case ma_aaudio_usage_voice_communication: return MA_AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS;
23651  case ma_aaudio_usage_voice_communication_signalling: return MA_AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT;
23652  default: break;
23653  }
23654 
23655  return MA_AAUDIO_USAGE_MEDIA;
23656 }
23657 
23658 static ma_aaudio_content_type_t ma_to_content_type__aaudio(ma_aaudio_content_type contentType)
23659 {
23660  switch (contentType) {
23661  case ma_aaudio_content_type_movie: return MA_AAUDIO_CONTENT_TYPE_MOVIE;
23662  case ma_aaudio_content_type_music: return MA_AAUDIO_CONTENT_TYPE_MUSIC;
23663  case ma_aaudio_content_type_sonification: return MA_AAUDIO_CONTENT_TYPE_SONIFICATION;
23664  case ma_aaudio_content_type_speech: return MA_AAUDIO_CONTENT_TYPE_SPEECH;
23665  default: break;
23666  }
23667 
23668  return MA_AAUDIO_CONTENT_TYPE_SPEECH;
23669 }
23670 
23671 static ma_aaudio_input_preset_t ma_to_input_preset__aaudio(ma_aaudio_input_preset inputPreset)
23672 {
23673  switch (inputPreset) {
23674  case ma_aaudio_input_preset_generic: return MA_AAUDIO_INPUT_PRESET_GENERIC;
23675  case ma_aaudio_input_preset_camcorder: return MA_AAUDIO_INPUT_PRESET_CAMCORDER;
23676  case ma_aaudio_input_preset_unprocessed: return MA_AAUDIO_INPUT_PRESET_UNPROCESSED;
23677  case ma_aaudio_input_preset_voice_recognition: return MA_AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
23678  case ma_aaudio_input_preset_voice_communication: return MA_AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION;
23679  case ma_aaudio_input_preset_voice_performance: return MA_AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE;
23680  default: break;
23681  }
23682 
23683  return MA_AAUDIO_INPUT_PRESET_GENERIC;
23684 }
23685 
23686 static void ma_stream_error_callback__aaudio(ma_AAudioStream* pStream, void* pUserData, ma_aaudio_result_t error)
23687 {
23688  ma_device* pDevice = (ma_device*)pUserData;
23689  MA_ASSERT(pDevice != NULL);
23690 
23691  (void)error;
23692 
23693  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[AAudio] ERROR CALLBACK: error=%d, AAudioStream_getState()=%d\n", error, ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream));
23694 
23695  /*
23696  From the documentation for AAudio, when a device is disconnected all we can do is stop it. However, we cannot stop it from the callback - we need
23697  to do it from another thread. Therefore we are going to use an event thread for the AAudio backend to do this cleanly and safely.
23698  */
23699  if (((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream) == MA_AAUDIO_STREAM_STATE_DISCONNECTED) {
23700  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[AAudio] Device Disconnected.\n");
23701  }
23702 }
23703 
23704 static ma_aaudio_data_callback_result_t ma_stream_data_callback_capture__aaudio(ma_AAudioStream* pStream, void* pUserData, void* pAudioData, int32_t frameCount)
23705 {
23706  ma_device* pDevice = (ma_device*)pUserData;
23707  MA_ASSERT(pDevice != NULL);
23708 
23709  ma_device_handle_backend_data_callback(pDevice, NULL, pAudioData, frameCount);
23710 
23711  (void)pStream;
23712  return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
23713 }
23714 
23715 static ma_aaudio_data_callback_result_t ma_stream_data_callback_playback__aaudio(ma_AAudioStream* pStream, void* pUserData, void* pAudioData, int32_t frameCount)
23716 {
23717  ma_device* pDevice = (ma_device*)pUserData;
23718  MA_ASSERT(pDevice != NULL);
23719 
23720  ma_device_handle_backend_data_callback(pDevice, pAudioData, NULL, frameCount);
23721 
23722  (void)pStream;
23723  return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
23724 }
23725 
23726 static ma_result ma_create_and_configure_AAudioStreamBuilder__aaudio(ma_context* pContext, const ma_device_id* pDeviceID, ma_device_type deviceType, ma_share_mode shareMode, const ma_device_descriptor* pDescriptor, const ma_device_config* pConfig, ma_device* pDevice, ma_AAudioStreamBuilder** ppBuilder)
23727 {
23728  ma_AAudioStreamBuilder* pBuilder;
23729  ma_aaudio_result_t resultAA;
23730  ma_uint32 bufferCapacityInFrames;
23731 
23732  /* Safety. */
23733  *ppBuilder = NULL;
23734 
23735  resultAA = ((MA_PFN_AAudio_createStreamBuilder)pContext->aaudio.AAudio_createStreamBuilder)(&pBuilder);
23736  if (resultAA != MA_AAUDIO_OK) {
23737  return ma_result_from_aaudio(resultAA);
23738  }
23739 
23740  if (pDeviceID != NULL) {
23741  ((MA_PFN_AAudioStreamBuilder_setDeviceId)pContext->aaudio.AAudioStreamBuilder_setDeviceId)(pBuilder, pDeviceID->aaudio);
23742  }
23743 
23744  ((MA_PFN_AAudioStreamBuilder_setDirection)pContext->aaudio.AAudioStreamBuilder_setDirection)(pBuilder, (deviceType == ma_device_type_playback) ? MA_AAUDIO_DIRECTION_OUTPUT : MA_AAUDIO_DIRECTION_INPUT);
23745  ((MA_PFN_AAudioStreamBuilder_setSharingMode)pContext->aaudio.AAudioStreamBuilder_setSharingMode)(pBuilder, (shareMode == ma_share_mode_shared) ? MA_AAUDIO_SHARING_MODE_SHARED : MA_AAUDIO_SHARING_MODE_EXCLUSIVE);
23746 
23747 
23748  /* If we have a device descriptor make sure we configure the stream builder to take our requested parameters. */
23749  if (pDescriptor != NULL) {
23750  MA_ASSERT(pConfig != NULL); /* We must have a device config if we also have a descriptor. The config is required for AAudio specific configuration options. */
23751 
23752  if (pDescriptor->sampleRate != 0) {
23753  ((MA_PFN_AAudioStreamBuilder_setSampleRate)pContext->aaudio.AAudioStreamBuilder_setSampleRate)(pBuilder, pDescriptor->sampleRate);
23754  }
23755 
23756  if (deviceType == ma_device_type_capture) {
23757  if (pDescriptor->channels != 0) {
23758  ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
23759  }
23760  if (pDescriptor->format != ma_format_unknown) {
23761  ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
23762  }
23763  } else {
23764  if (pDescriptor->channels != 0) {
23765  ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
23766  }
23767  if (pDescriptor->format != ma_format_unknown) {
23768  ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
23769  }
23770  }
23771 
23772  /*
23773  AAudio is annoying when it comes to it's buffer calculation stuff because it doesn't let you
23774  retrieve the actual sample rate until after you've opened the stream. But you need to configure
23775  the buffer capacity before you open the stream... :/
23776 
23777  To solve, we're just going to assume MA_DEFAULT_SAMPLE_RATE (48000) and move on.
23778  */
23779  bufferCapacityInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, pDescriptor->sampleRate, pConfig->performanceProfile) * pDescriptor->periodCount;
23780 
23781  ((MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames)(pBuilder, bufferCapacityInFrames);
23782  ((MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback)pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback)(pBuilder, bufferCapacityInFrames / pDescriptor->periodCount);
23783 
23784  if (deviceType == ma_device_type_capture) {
23785  if (pConfig->aaudio.inputPreset != ma_aaudio_input_preset_default && pContext->aaudio.AAudioStreamBuilder_setInputPreset != NULL) {
23786  ((MA_PFN_AAudioStreamBuilder_setInputPreset)pContext->aaudio.AAudioStreamBuilder_setInputPreset)(pBuilder, ma_to_input_preset__aaudio(pConfig->aaudio.inputPreset));
23787  }
23788 
23789  ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_capture__aaudio, (void*)pDevice);
23790  } else {
23791  if (pConfig->aaudio.usage != ma_aaudio_usage_default && pContext->aaudio.AAudioStreamBuilder_setUsage != NULL) {
23792  ((MA_PFN_AAudioStreamBuilder_setUsage)pContext->aaudio.AAudioStreamBuilder_setUsage)(pBuilder, ma_to_usage__aaudio(pConfig->aaudio.usage));
23793  }
23794 
23795  if (pConfig->aaudio.contentType != ma_aaudio_content_type_default && pContext->aaudio.AAudioStreamBuilder_setContentType != NULL) {
23796  ((MA_PFN_AAudioStreamBuilder_setContentType)pContext->aaudio.AAudioStreamBuilder_setContentType)(pBuilder, ma_to_content_type__aaudio(pConfig->aaudio.contentType));
23797  }
23798 
23799  ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_playback__aaudio, (void*)pDevice);
23800  }
23801 
23802  /* Not sure how this affects things, but since there's a mapping between miniaudio's performance profiles and AAudio's performance modes, let go ahead and set it. */
23803  ((MA_PFN_AAudioStreamBuilder_setPerformanceMode)pContext->aaudio.AAudioStreamBuilder_setPerformanceMode)(pBuilder, (pConfig->performanceProfile == ma_performance_profile_low_latency) ? MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY : MA_AAUDIO_PERFORMANCE_MODE_NONE);
23804 
23805  /* We need to set an error callback to detect device changes. */
23806  if (pDevice != NULL) { /* <-- pDevice should never be null if pDescriptor is not null, which is always the case if we hit this branch. Check anyway for safety. */
23807  ((MA_PFN_AAudioStreamBuilder_setErrorCallback)pContext->aaudio.AAudioStreamBuilder_setErrorCallback)(pBuilder, ma_stream_error_callback__aaudio, (void*)pDevice);
23808  }
23809  }
23810 
23811  *ppBuilder = pBuilder;
23812 
23813  return MA_SUCCESS;
23814 }
23815 
23816 static ma_result ma_open_stream_and_close_builder__aaudio(ma_context* pContext, ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream** ppStream)
23817 {
23818  ma_result result;
23819 
23820  result = ma_result_from_aaudio(((MA_PFN_AAudioStreamBuilder_openStream)pContext->aaudio.AAudioStreamBuilder_openStream)(pBuilder, ppStream));
23821  ((MA_PFN_AAudioStreamBuilder_delete)pContext->aaudio.AAudioStreamBuilder_delete)(pBuilder);
23822 
23823  return result;
23824 }
23825 
23826 static ma_result ma_open_stream_basic__aaudio(ma_context* pContext, const ma_device_id* pDeviceID, ma_device_type deviceType, ma_share_mode shareMode, ma_AAudioStream** ppStream)
23827 {
23828  ma_result result;
23829  ma_AAudioStreamBuilder* pBuilder;
23830 
23831  *ppStream = NULL;
23832 
23833  result = ma_create_and_configure_AAudioStreamBuilder__aaudio(pContext, pDeviceID, deviceType, shareMode, NULL, NULL, NULL, &pBuilder);
23834  if (result != MA_SUCCESS) {
23835  return result;
23836  }
23837 
23838  return ma_open_stream_and_close_builder__aaudio(pContext, pBuilder, ppStream);
23839 }
23840 
23841 static ma_result ma_open_stream__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_type deviceType, const ma_device_descriptor* pDescriptor, ma_AAudioStream** ppStream)
23842 {
23843  ma_result result;
23844  ma_AAudioStreamBuilder* pBuilder;
23845 
23846  MA_ASSERT(pConfig != NULL);
23847  MA_ASSERT(pConfig->deviceType != ma_device_type_duplex); /* This function should not be called for a full-duplex device type. */
23848 
23849  *ppStream = NULL;
23850 
23851  result = ma_create_and_configure_AAudioStreamBuilder__aaudio(pDevice->pContext, pDescriptor->pDeviceID, deviceType, pDescriptor->shareMode, pDescriptor, pConfig, pDevice, &pBuilder);
23852  if (result != MA_SUCCESS) {
23853  return result;
23854  }
23855 
23856  return ma_open_stream_and_close_builder__aaudio(pDevice->pContext, pBuilder, ppStream);
23857 }
23858 
23859 static ma_result ma_close_stream__aaudio(ma_context* pContext, ma_AAudioStream* pStream)
23860 {
23861  return ma_result_from_aaudio(((MA_PFN_AAudioStream_close)pContext->aaudio.AAudioStream_close)(pStream));
23862 }
23863 
23864 static ma_bool32 ma_has_default_device__aaudio(ma_context* pContext, ma_device_type deviceType)
23865 {
23866  /* The only way to know this is to try creating a stream. */
23867  ma_AAudioStream* pStream;
23868  ma_result result = ma_open_stream_basic__aaudio(pContext, NULL, deviceType, ma_share_mode_shared, &pStream);
23869  if (result != MA_SUCCESS) {
23870  return MA_FALSE;
23871  }
23872 
23873  ma_close_stream__aaudio(pContext, pStream);
23874  return MA_TRUE;
23875 }
23876 
23877 static ma_result ma_wait_for_simple_state_transition__aaudio(ma_context* pContext, ma_AAudioStream* pStream, ma_aaudio_stream_state_t oldState, ma_aaudio_stream_state_t newState)
23878 {
23879  ma_aaudio_stream_state_t actualNewState;
23880  ma_aaudio_result_t resultAA = ((MA_PFN_AAudioStream_waitForStateChange)pContext->aaudio.AAudioStream_waitForStateChange)(pStream, oldState, &actualNewState, 5000000000); /* 5 second timeout. */
23881  if (resultAA != MA_AAUDIO_OK) {
23882  return ma_result_from_aaudio(resultAA);
23883  }
23884 
23885  if (newState != actualNewState) {
23886  return MA_ERROR; /* Failed to transition into the expected state. */
23887  }
23888 
23889  return MA_SUCCESS;
23890 }
23891 
23892 
23893 static ma_result ma_context_enumerate_devices__aaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
23894 {
23895  ma_bool32 cbResult = MA_TRUE;
23896 
23897  MA_ASSERT(pContext != NULL);
23898  MA_ASSERT(callback != NULL);
23899 
23900  /* Unfortunately AAudio does not have an enumeration API. Therefore I'm only going to report default devices, but only if it can instantiate a stream. */
23901 
23902  /* Playback. */
23903  if (cbResult) {
23904  ma_device_info deviceInfo;
23905  MA_ZERO_OBJECT(&deviceInfo);
23906  deviceInfo.id.aaudio = MA_AAUDIO_UNSPECIFIED;
23907  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
23908 
23909  if (ma_has_default_device__aaudio(pContext, ma_device_type_playback)) {
23910  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
23911  }
23912  }
23913 
23914  /* Capture. */
23915  if (cbResult) {
23916  ma_device_info deviceInfo;
23917  MA_ZERO_OBJECT(&deviceInfo);
23918  deviceInfo.id.aaudio = MA_AAUDIO_UNSPECIFIED;
23919  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
23920 
23921  if (ma_has_default_device__aaudio(pContext, ma_device_type_capture)) {
23922  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
23923  }
23924  }
23925 
23926  return MA_SUCCESS;
23927 }
23928 
23929 static void ma_context_add_native_data_format_from_AAudioStream_ex__aaudio(ma_context* pContext, ma_AAudioStream* pStream, ma_format format, ma_uint32 flags, ma_device_info* pDeviceInfo)
23930 {
23931  MA_ASSERT(pContext != NULL);
23932  MA_ASSERT(pStream != NULL);
23933  MA_ASSERT(pDeviceInfo != NULL);
23934 
23935  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
23936  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)(pStream);
23937  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)(pStream);
23938  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = flags;
23939  pDeviceInfo->nativeDataFormatCount += 1;
23940 }
23941 
23942 static void ma_context_add_native_data_format_from_AAudioStream__aaudio(ma_context* pContext, ma_AAudioStream* pStream, ma_uint32 flags, ma_device_info* pDeviceInfo)
23943 {
23944  /* AAudio supports s16 and f32. */
23945  ma_context_add_native_data_format_from_AAudioStream_ex__aaudio(pContext, pStream, ma_format_f32, flags, pDeviceInfo);
23946  ma_context_add_native_data_format_from_AAudioStream_ex__aaudio(pContext, pStream, ma_format_s16, flags, pDeviceInfo);
23947 }
23948 
23949 static ma_result ma_context_get_device_info__aaudio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
23950 {
23951  ma_AAudioStream* pStream;
23952  ma_result result;
23953 
23954  MA_ASSERT(pContext != NULL);
23955 
23956  /* ID */
23957  if (pDeviceID != NULL) {
23958  pDeviceInfo->id.aaudio = pDeviceID->aaudio;
23959  } else {
23960  pDeviceInfo->id.aaudio = MA_AAUDIO_UNSPECIFIED;
23961  }
23962 
23963  /* Name */
23964  if (deviceType == ma_device_type_playback) {
23965  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
23966  } else {
23967  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
23968  }
23969 
23970 
23971  pDeviceInfo->nativeDataFormatCount = 0;
23972 
23973  /* We'll need to open the device to get accurate sample rate and channel count information. */
23974  result = ma_open_stream_basic__aaudio(pContext, pDeviceID, deviceType, ma_share_mode_shared, &pStream);
23975  if (result != MA_SUCCESS) {
23976  return result;
23977  }
23978 
23979  ma_context_add_native_data_format_from_AAudioStream__aaudio(pContext, pStream, 0, pDeviceInfo);
23980 
23981  ma_close_stream__aaudio(pContext, pStream);
23982  pStream = NULL;
23983 
23984  return MA_SUCCESS;
23985 }
23986 
23987 
23988 static ma_result ma_device_uninit__aaudio(ma_device* pDevice)
23989 {
23990  MA_ASSERT(pDevice != NULL);
23991 
23992  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
23993  ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23994  pDevice->aaudio.pStreamCapture = NULL;
23995  }
23996 
23997  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
23998  ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23999  pDevice->aaudio.pStreamPlayback = NULL;
24000  }
24001 
24002  return MA_SUCCESS;
24003 }
24004 
24005 static ma_result ma_device_init_by_type__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_type deviceType, ma_device_descriptor* pDescriptor, ma_AAudioStream** ppStream)
24006 {
24007  ma_result result;
24008  int32_t bufferCapacityInFrames;
24009  int32_t framesPerDataCallback;
24010  ma_AAudioStream* pStream;
24011 
24012  MA_ASSERT(pDevice != NULL);
24013  MA_ASSERT(pConfig != NULL);
24014  MA_ASSERT(pDescriptor != NULL);
24015 
24016  *ppStream = NULL; /* Safety. */
24017 
24018  /* First step is to open the stream. From there we'll be able to extract the internal configuration. */
24019  result = ma_open_stream__aaudio(pDevice, pConfig, deviceType, pDescriptor, &pStream);
24020  if (result != MA_SUCCESS) {
24021  return result; /* Failed to open the AAudio stream. */
24022  }
24023 
24024  /* Now extract the internal configuration. */
24025  pDescriptor->format = (((MA_PFN_AAudioStream_getFormat)pDevice->pContext->aaudio.AAudioStream_getFormat)(pStream) == MA_AAUDIO_FORMAT_PCM_I16) ? ma_format_s16 : ma_format_f32;
24026  pDescriptor->channels = ((MA_PFN_AAudioStream_getChannelCount)pDevice->pContext->aaudio.AAudioStream_getChannelCount)(pStream);
24027  pDescriptor->sampleRate = ((MA_PFN_AAudioStream_getSampleRate)pDevice->pContext->aaudio.AAudioStream_getSampleRate)(pStream);
24028 
24029  /* For the channel map we need to be sure we don't overflow any buffers. */
24030  if (pDescriptor->channels <= MA_MAX_CHANNELS) {
24031  ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptor->channels, pDescriptor->channelMap); /* <-- Cannot find info on channel order, so assuming a default. */
24032  } else {
24033  ma_channel_map_init_blank(MA_MAX_CHANNELS, pDescriptor->channelMap); /* Too many channels. Use a blank channel map. */
24034  }
24035 
24036  bufferCapacityInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pDevice->pContext->aaudio.AAudioStream_getBufferCapacityInFrames)(pStream);
24037  framesPerDataCallback = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pDevice->pContext->aaudio.AAudioStream_getFramesPerDataCallback)(pStream);
24038 
24039  if (framesPerDataCallback > 0) {
24040  pDescriptor->periodSizeInFrames = framesPerDataCallback;
24041  pDescriptor->periodCount = bufferCapacityInFrames / framesPerDataCallback;
24042  } else {
24043  pDescriptor->periodSizeInFrames = bufferCapacityInFrames;
24044  pDescriptor->periodCount = 1;
24045  }
24046 
24047  *ppStream = pStream;
24048 
24049  return MA_SUCCESS;
24050 }
24051 
24052 static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
24053 {
24054  ma_result result;
24055 
24056  MA_ASSERT(pDevice != NULL);
24057 
24058  if (pConfig->deviceType == ma_device_type_loopback) {
24060  }
24061 
24062  /* No exclusive mode with AAudio. */
24063  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
24064  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
24066  }
24067 
24068  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
24069  result = ma_device_init_by_type__aaudio(pDevice, pConfig, ma_device_type_capture, pDescriptorCapture, (ma_AAudioStream**)&pDevice->aaudio.pStreamCapture);
24070  if (result != MA_SUCCESS) {
24071  return result;
24072  }
24073  }
24074 
24075  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
24076  result = ma_device_init_by_type__aaudio(pDevice, pConfig, ma_device_type_playback, pDescriptorPlayback, (ma_AAudioStream**)&pDevice->aaudio.pStreamPlayback);
24077  if (result != MA_SUCCESS) {
24078  return result;
24079  }
24080  }
24081 
24082  return MA_SUCCESS;
24083 }
24084 
24085 static ma_result ma_device_start_stream__aaudio(ma_device* pDevice, ma_AAudioStream* pStream)
24086 {
24087  ma_aaudio_result_t resultAA;
24088  ma_aaudio_stream_state_t currentState;
24089 
24090  MA_ASSERT(pDevice != NULL);
24091 
24092  resultAA = ((MA_PFN_AAudioStream_requestStart)pDevice->pContext->aaudio.AAudioStream_requestStart)(pStream);
24093  if (resultAA != MA_AAUDIO_OK) {
24094  return ma_result_from_aaudio(resultAA);
24095  }
24096 
24097  /* Do we actually need to wait for the device to transition into it's started state? */
24098 
24099  /* The device should be in either a starting or started state. If it's not set to started we need to wait for it to transition. It should go from starting to started. */
24100  currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
24101  if (currentState != MA_AAUDIO_STREAM_STATE_STARTED) {
24102  ma_result result;
24103 
24104  if (currentState != MA_AAUDIO_STREAM_STATE_STARTING) {
24105  return MA_ERROR; /* Expecting the stream to be a starting or started state. */
24106  }
24107 
24108  result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STARTED);
24109  if (result != MA_SUCCESS) {
24110  return result;
24111  }
24112  }
24113 
24114  return MA_SUCCESS;
24115 }
24116 
24117 static ma_result ma_device_stop_stream__aaudio(ma_device* pDevice, ma_AAudioStream* pStream)
24118 {
24119  ma_aaudio_result_t resultAA;
24120  ma_aaudio_stream_state_t currentState;
24121 
24122  MA_ASSERT(pDevice != NULL);
24123 
24124  /*
24125  From the AAudio documentation:
24126 
24127  The stream will stop after all of the data currently buffered has been played.
24128 
24129  This maps with miniaudio's requirement that device's be drained which means we don't need to implement any draining logic.
24130  */
24131 
24132  resultAA = ((MA_PFN_AAudioStream_requestStop)pDevice->pContext->aaudio.AAudioStream_requestStop)(pStream);
24133  if (resultAA != MA_AAUDIO_OK) {
24134  return ma_result_from_aaudio(resultAA);
24135  }
24136 
24137  /* The device should be in either a stopping or stopped state. If it's not set to started we need to wait for it to transition. It should go from stopping to stopped. */
24138  currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
24139  if (currentState != MA_AAUDIO_STREAM_STATE_STOPPED) {
24140  ma_result result;
24141 
24142  if (currentState != MA_AAUDIO_STREAM_STATE_STOPPING) {
24143  return MA_ERROR; /* Expecting the stream to be a stopping or stopped state. */
24144  }
24145 
24146  result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STOPPED);
24147  if (result != MA_SUCCESS) {
24148  return result;
24149  }
24150  }
24151 
24152  return MA_SUCCESS;
24153 }
24154 
24155 static ma_result ma_device_start__aaudio(ma_device* pDevice)
24156 {
24157  MA_ASSERT(pDevice != NULL);
24158 
24159  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24160  ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
24161  if (result != MA_SUCCESS) {
24162  return result;
24163  }
24164  }
24165 
24166  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24167  ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
24168  if (result != MA_SUCCESS) {
24169  if (pDevice->type == ma_device_type_duplex) {
24170  ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
24171  }
24172  return result;
24173  }
24174  }
24175 
24176  return MA_SUCCESS;
24177 }
24178 
24179 static ma_result ma_device_stop__aaudio(ma_device* pDevice)
24180 {
24181  ma_stop_proc onStop;
24182 
24183  MA_ASSERT(pDevice != NULL);
24184 
24185  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24186  ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
24187  if (result != MA_SUCCESS) {
24188  return result;
24189  }
24190  }
24191 
24192  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24193  ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
24194  if (result != MA_SUCCESS) {
24195  return result;
24196  }
24197  }
24198 
24199  onStop = pDevice->onStop;
24200  if (onStop) {
24201  onStop(pDevice);
24202  }
24203 
24204  return MA_SUCCESS;
24205 }
24206 
24207 
24208 static ma_result ma_context_uninit__aaudio(ma_context* pContext)
24209 {
24210  MA_ASSERT(pContext != NULL);
24211  MA_ASSERT(pContext->backend == ma_backend_aaudio);
24212 
24213  ma_dlclose(pContext, pContext->aaudio.hAAudio);
24214  pContext->aaudio.hAAudio = NULL;
24215 
24216  return MA_SUCCESS;
24217 }
24218 
24219 static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
24220 {
24221  size_t i;
24222  const char* libNames[] = {
24223  "libaaudio.so"
24224  };
24225 
24226  for (i = 0; i < ma_countof(libNames); ++i) {
24227  pContext->aaudio.hAAudio = ma_dlopen(pContext, libNames[i]);
24228  if (pContext->aaudio.hAAudio != NULL) {
24229  break;
24230  }
24231  }
24232 
24233  if (pContext->aaudio.hAAudio == NULL) {
24235  }
24236 
24237  pContext->aaudio.AAudio_createStreamBuilder = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudio_createStreamBuilder");
24238  pContext->aaudio.AAudioStreamBuilder_delete = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_delete");
24239  pContext->aaudio.AAudioStreamBuilder_setDeviceId = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDeviceId");
24240  pContext->aaudio.AAudioStreamBuilder_setDirection = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDirection");
24241  pContext->aaudio.AAudioStreamBuilder_setSharingMode = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setSharingMode");
24242  pContext->aaudio.AAudioStreamBuilder_setFormat = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setFormat");
24243  pContext->aaudio.AAudioStreamBuilder_setChannelCount = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setChannelCount");
24244  pContext->aaudio.AAudioStreamBuilder_setSampleRate = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setSampleRate");
24245  pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setBufferCapacityInFrames");
24246  pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setFramesPerDataCallback");
24247  pContext->aaudio.AAudioStreamBuilder_setDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDataCallback");
24248  pContext->aaudio.AAudioStreamBuilder_setErrorCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setErrorCallback");
24249  pContext->aaudio.AAudioStreamBuilder_setPerformanceMode = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setPerformanceMode");
24250  pContext->aaudio.AAudioStreamBuilder_setUsage = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setUsage");
24251  pContext->aaudio.AAudioStreamBuilder_setContentType = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setContentType");
24252  pContext->aaudio.AAudioStreamBuilder_setInputPreset = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setInputPreset");
24253  pContext->aaudio.AAudioStreamBuilder_openStream = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_openStream");
24254  pContext->aaudio.AAudioStream_close = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_close");
24255  pContext->aaudio.AAudioStream_getState = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getState");
24256  pContext->aaudio.AAudioStream_waitForStateChange = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_waitForStateChange");
24257  pContext->aaudio.AAudioStream_getFormat = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFormat");
24258  pContext->aaudio.AAudioStream_getChannelCount = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getChannelCount");
24259  pContext->aaudio.AAudioStream_getSampleRate = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getSampleRate");
24260  pContext->aaudio.AAudioStream_getBufferCapacityInFrames = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getBufferCapacityInFrames");
24261  pContext->aaudio.AAudioStream_getFramesPerDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerDataCallback");
24262  pContext->aaudio.AAudioStream_getFramesPerBurst = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerBurst");
24263  pContext->aaudio.AAudioStream_requestStart = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStart");
24264  pContext->aaudio.AAudioStream_requestStop = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStop");
24265 
24266 
24267  pCallbacks->onContextInit = ma_context_init__aaudio;
24268  pCallbacks->onContextUninit = ma_context_uninit__aaudio;
24269  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__aaudio;
24270  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__aaudio;
24271  pCallbacks->onDeviceInit = ma_device_init__aaudio;
24272  pCallbacks->onDeviceUninit = ma_device_uninit__aaudio;
24273  pCallbacks->onDeviceStart = ma_device_start__aaudio;
24274  pCallbacks->onDeviceStop = ma_device_stop__aaudio;
24275  pCallbacks->onDeviceRead = NULL; /* Not used because AAudio is asynchronous. */
24276  pCallbacks->onDeviceWrite = NULL; /* Not used because AAudio is asynchronous. */
24277  pCallbacks->onDeviceDataLoop = NULL; /* Not used because AAudio is asynchronous. */
24278 
24279  (void)pConfig;
24280  return MA_SUCCESS;
24281 }
24282 #endif /* AAudio */
24283 
24284 
24285 /******************************************************************************
24286 
24287 OpenSL|ES Backend
24288 
24289 ******************************************************************************/
24290 #ifdef MA_HAS_OPENSL
24291 #include <SLES/OpenSLES.h>
24292 #ifdef MA_ANDROID
24293 #include <SLES/OpenSLES_Android.h>
24294 #endif
24295 
24296 typedef SLresult (SLAPIENTRY * ma_slCreateEngine_proc)(SLObjectItf* pEngine, SLuint32 numOptions, SLEngineOption* pEngineOptions, SLuint32 numInterfaces, SLInterfaceID* pInterfaceIds, SLboolean* pInterfaceRequired);
24297 
24298 /* OpenSL|ES has one-per-application objects :( */
24299 static SLObjectItf g_maEngineObjectSL = NULL;
24300 static SLEngineItf g_maEngineSL = NULL;
24301 static ma_uint32 g_maOpenSLInitCounter = 0;
24302 static ma_spinlock g_maOpenSLSpinlock = 0; /* For init/uninit. */
24303 
24304 #define MA_OPENSL_OBJ(p) (*((SLObjectItf)(p)))
24305 #define MA_OPENSL_OUTPUTMIX(p) (*((SLOutputMixItf)(p)))
24306 #define MA_OPENSL_PLAY(p) (*((SLPlayItf)(p)))
24307 #define MA_OPENSL_RECORD(p) (*((SLRecordItf)(p)))
24308 
24309 #ifdef MA_ANDROID
24310 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLAndroidSimpleBufferQueueItf)(p)))
24311 #else
24312 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLBufferQueueItf)(p)))
24313 #endif
24314 
24315 static ma_result ma_result_from_OpenSL(SLuint32 result)
24316 {
24317  switch (result)
24318  {
24319  case SL_RESULT_SUCCESS: return MA_SUCCESS;
24320  case SL_RESULT_PRECONDITIONS_VIOLATED: return MA_ERROR;
24321  case SL_RESULT_PARAMETER_INVALID: return MA_INVALID_ARGS;
24322  case SL_RESULT_MEMORY_FAILURE: return MA_OUT_OF_MEMORY;
24323  case SL_RESULT_RESOURCE_ERROR: return MA_INVALID_DATA;
24324  case SL_RESULT_RESOURCE_LOST: return MA_ERROR;
24325  case SL_RESULT_IO_ERROR: return MA_IO_ERROR;
24326  case SL_RESULT_BUFFER_INSUFFICIENT: return MA_NO_SPACE;
24327  case SL_RESULT_CONTENT_CORRUPTED: return MA_INVALID_DATA;
24328  case SL_RESULT_CONTENT_UNSUPPORTED: return MA_FORMAT_NOT_SUPPORTED;
24329  case SL_RESULT_CONTENT_NOT_FOUND: return MA_ERROR;
24330  case SL_RESULT_PERMISSION_DENIED: return MA_ACCESS_DENIED;
24331  case SL_RESULT_FEATURE_UNSUPPORTED: return MA_NOT_IMPLEMENTED;
24332  case SL_RESULT_INTERNAL_ERROR: return MA_ERROR;
24333  case SL_RESULT_UNKNOWN_ERROR: return MA_ERROR;
24334  case SL_RESULT_OPERATION_ABORTED: return MA_ERROR;
24335  case SL_RESULT_CONTROL_LOST: return MA_ERROR;
24336  default: return MA_ERROR;
24337  }
24338 }
24339 
24340 /* Converts an individual OpenSL-style channel identifier (SL_SPEAKER_FRONT_LEFT, etc.) to miniaudio. */
24341 static ma_uint8 ma_channel_id_to_ma__opensl(SLuint32 id)
24342 {
24343  switch (id)
24344  {
24345  case SL_SPEAKER_FRONT_LEFT: return MA_CHANNEL_FRONT_LEFT;
24346  case SL_SPEAKER_FRONT_RIGHT: return MA_CHANNEL_FRONT_RIGHT;
24347  case SL_SPEAKER_FRONT_CENTER: return MA_CHANNEL_FRONT_CENTER;
24348  case SL_SPEAKER_LOW_FREQUENCY: return MA_CHANNEL_LFE;
24349  case SL_SPEAKER_BACK_LEFT: return MA_CHANNEL_BACK_LEFT;
24350  case SL_SPEAKER_BACK_RIGHT: return MA_CHANNEL_BACK_RIGHT;
24351  case SL_SPEAKER_FRONT_LEFT_OF_CENTER: return MA_CHANNEL_FRONT_LEFT_CENTER;
24352  case SL_SPEAKER_FRONT_RIGHT_OF_CENTER: return MA_CHANNEL_FRONT_RIGHT_CENTER;
24353  case SL_SPEAKER_BACK_CENTER: return MA_CHANNEL_BACK_CENTER;
24354  case SL_SPEAKER_SIDE_LEFT: return MA_CHANNEL_SIDE_LEFT;
24355  case SL_SPEAKER_SIDE_RIGHT: return MA_CHANNEL_SIDE_RIGHT;
24356  case SL_SPEAKER_TOP_CENTER: return MA_CHANNEL_TOP_CENTER;
24357  case SL_SPEAKER_TOP_FRONT_LEFT: return MA_CHANNEL_TOP_FRONT_LEFT;
24358  case SL_SPEAKER_TOP_FRONT_CENTER: return MA_CHANNEL_TOP_FRONT_CENTER;
24359  case SL_SPEAKER_TOP_FRONT_RIGHT: return MA_CHANNEL_TOP_FRONT_RIGHT;
24360  case SL_SPEAKER_TOP_BACK_LEFT: return MA_CHANNEL_TOP_BACK_LEFT;
24361  case SL_SPEAKER_TOP_BACK_CENTER: return MA_CHANNEL_TOP_BACK_CENTER;
24362  case SL_SPEAKER_TOP_BACK_RIGHT: return MA_CHANNEL_TOP_BACK_RIGHT;
24363  default: return 0;
24364  }
24365 }
24366 
24367 /* Converts an individual miniaudio channel identifier (MA_CHANNEL_FRONT_LEFT, etc.) to OpenSL-style. */
24368 static SLuint32 ma_channel_id_to_opensl(ma_uint8 id)
24369 {
24370  switch (id)
24371  {
24372  case MA_CHANNEL_MONO: return SL_SPEAKER_FRONT_CENTER;
24373  case MA_CHANNEL_FRONT_LEFT: return SL_SPEAKER_FRONT_LEFT;
24374  case MA_CHANNEL_FRONT_RIGHT: return SL_SPEAKER_FRONT_RIGHT;
24375  case MA_CHANNEL_FRONT_CENTER: return SL_SPEAKER_FRONT_CENTER;
24376  case MA_CHANNEL_LFE: return SL_SPEAKER_LOW_FREQUENCY;
24377  case MA_CHANNEL_BACK_LEFT: return SL_SPEAKER_BACK_LEFT;
24378  case MA_CHANNEL_BACK_RIGHT: return SL_SPEAKER_BACK_RIGHT;
24379  case MA_CHANNEL_FRONT_LEFT_CENTER: return SL_SPEAKER_FRONT_LEFT_OF_CENTER;
24380  case MA_CHANNEL_FRONT_RIGHT_CENTER: return SL_SPEAKER_FRONT_RIGHT_OF_CENTER;
24381  case MA_CHANNEL_BACK_CENTER: return SL_SPEAKER_BACK_CENTER;
24382  case MA_CHANNEL_SIDE_LEFT: return SL_SPEAKER_SIDE_LEFT;
24383  case MA_CHANNEL_SIDE_RIGHT: return SL_SPEAKER_SIDE_RIGHT;
24384  case MA_CHANNEL_TOP_CENTER: return SL_SPEAKER_TOP_CENTER;
24385  case MA_CHANNEL_TOP_FRONT_LEFT: return SL_SPEAKER_TOP_FRONT_LEFT;
24386  case MA_CHANNEL_TOP_FRONT_CENTER: return SL_SPEAKER_TOP_FRONT_CENTER;
24387  case MA_CHANNEL_TOP_FRONT_RIGHT: return SL_SPEAKER_TOP_FRONT_RIGHT;
24388  case MA_CHANNEL_TOP_BACK_LEFT: return SL_SPEAKER_TOP_BACK_LEFT;
24389  case MA_CHANNEL_TOP_BACK_CENTER: return SL_SPEAKER_TOP_BACK_CENTER;
24390  case MA_CHANNEL_TOP_BACK_RIGHT: return SL_SPEAKER_TOP_BACK_RIGHT;
24391  default: return 0;
24392  }
24393 }
24394 
24395 /* Converts a channel mapping to an OpenSL-style channel mask. */
24396 static SLuint32 ma_channel_map_to_channel_mask__opensl(const ma_channel* pChannelMap, ma_uint32 channels)
24397 {
24398  SLuint32 channelMask = 0;
24399  ma_uint32 iChannel;
24400  for (iChannel = 0; iChannel < channels; ++iChannel) {
24401  channelMask |= ma_channel_id_to_opensl(pChannelMap[iChannel]);
24402  }
24403 
24404  return channelMask;
24405 }
24406 
24407 /* Converts an OpenSL-style channel mask to a miniaudio channel map. */
24408 static void ma_channel_mask_to_channel_map__opensl(SLuint32 channelMask, ma_uint32 channels, ma_channel* pChannelMap)
24409 {
24410  if (channels == 1 && channelMask == 0) {
24411  pChannelMap[0] = MA_CHANNEL_MONO;
24412  } else if (channels == 2 && channelMask == 0) {
24413  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
24414  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
24415  } else {
24416  if (channels == 1 && (channelMask & SL_SPEAKER_FRONT_CENTER) != 0) {
24417  pChannelMap[0] = MA_CHANNEL_MONO;
24418  } else {
24419  /* Just iterate over each bit. */
24420  ma_uint32 iChannel = 0;
24421  ma_uint32 iBit;
24422  for (iBit = 0; iBit < 32 && iChannel < channels; ++iBit) {
24423  SLuint32 bitValue = (channelMask & (1UL << iBit));
24424  if (bitValue != 0) {
24425  /* The bit is set. */
24426  pChannelMap[iChannel] = ma_channel_id_to_ma__opensl(bitValue);
24427  iChannel += 1;
24428  }
24429  }
24430  }
24431  }
24432 }
24433 
24434 static SLuint32 ma_round_to_standard_sample_rate__opensl(SLuint32 samplesPerSec)
24435 {
24436  if (samplesPerSec <= SL_SAMPLINGRATE_8) {
24437  return SL_SAMPLINGRATE_8;
24438  }
24439  if (samplesPerSec <= SL_SAMPLINGRATE_11_025) {
24440  return SL_SAMPLINGRATE_11_025;
24441  }
24442  if (samplesPerSec <= SL_SAMPLINGRATE_12) {
24443  return SL_SAMPLINGRATE_12;
24444  }
24445  if (samplesPerSec <= SL_SAMPLINGRATE_16) {
24446  return SL_SAMPLINGRATE_16;
24447  }
24448  if (samplesPerSec <= SL_SAMPLINGRATE_22_05) {
24449  return SL_SAMPLINGRATE_22_05;
24450  }
24451  if (samplesPerSec <= SL_SAMPLINGRATE_24) {
24452  return SL_SAMPLINGRATE_24;
24453  }
24454  if (samplesPerSec <= SL_SAMPLINGRATE_32) {
24455  return SL_SAMPLINGRATE_32;
24456  }
24457  if (samplesPerSec <= SL_SAMPLINGRATE_44_1) {
24458  return SL_SAMPLINGRATE_44_1;
24459  }
24460  if (samplesPerSec <= SL_SAMPLINGRATE_48) {
24461  return SL_SAMPLINGRATE_48;
24462  }
24463 
24464  /* Android doesn't support more than 48000. */
24465 #ifndef MA_ANDROID
24466  if (samplesPerSec <= SL_SAMPLINGRATE_64) {
24467  return SL_SAMPLINGRATE_64;
24468  }
24469  if (samplesPerSec <= SL_SAMPLINGRATE_88_2) {
24470  return SL_SAMPLINGRATE_88_2;
24471  }
24472  if (samplesPerSec <= SL_SAMPLINGRATE_96) {
24473  return SL_SAMPLINGRATE_96;
24474  }
24475  if (samplesPerSec <= SL_SAMPLINGRATE_192) {
24476  return SL_SAMPLINGRATE_192;
24477  }
24478 #endif
24479 
24480  return SL_SAMPLINGRATE_16;
24481 }
24482 
24483 
24484 static SLint32 ma_to_stream_type__opensl(ma_opensl_stream_type streamType)
24485 {
24486  switch (streamType) {
24487  case ma_opensl_stream_type_voice: return SL_ANDROID_STREAM_VOICE;
24488  case ma_opensl_stream_type_system: return SL_ANDROID_STREAM_SYSTEM;
24489  case ma_opensl_stream_type_ring: return SL_ANDROID_STREAM_RING;
24490  case ma_opensl_stream_type_media: return SL_ANDROID_STREAM_MEDIA;
24491  case ma_opensl_stream_type_alarm: return SL_ANDROID_STREAM_ALARM;
24492  case ma_opensl_stream_type_notification: return SL_ANDROID_STREAM_NOTIFICATION;
24493  default: break;
24494  }
24495 
24496  return SL_ANDROID_STREAM_VOICE;
24497 }
24498 
24499 static SLint32 ma_to_recording_preset__opensl(ma_opensl_recording_preset recordingPreset)
24500 {
24501  switch (recordingPreset) {
24502  case ma_opensl_recording_preset_generic: return SL_ANDROID_RECORDING_PRESET_GENERIC;
24503  case ma_opensl_recording_preset_camcorder: return SL_ANDROID_RECORDING_PRESET_CAMCORDER;
24504  case ma_opensl_recording_preset_voice_recognition: return SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
24505  case ma_opensl_recording_preset_voice_communication: return SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
24506  case ma_opensl_recording_preset_voice_unprocessed: return SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
24507  default: break;
24508  }
24509 
24510  return SL_ANDROID_RECORDING_PRESET_NONE;
24511 }
24512 
24513 
24514 static ma_result ma_context_enumerate_devices__opensl(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
24515 {
24516  ma_bool32 cbResult;
24517 
24518  MA_ASSERT(pContext != NULL);
24519  MA_ASSERT(callback != NULL);
24520 
24521  MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it and then attempted to enumerate devices. */
24522  if (g_maOpenSLInitCounter == 0) {
24523  return MA_INVALID_OPERATION;
24524  }
24525 
24526  /*
24527  TODO: Test Me.
24528 
24529  This is currently untested, so for now we are just returning default devices.
24530  */
24531 #if 0 && !defined(MA_ANDROID)
24532  ma_bool32 isTerminated = MA_FALSE;
24533 
24534  SLuint32 pDeviceIDs[128];
24535  SLint32 deviceCount = sizeof(pDeviceIDs) / sizeof(pDeviceIDs[0]);
24536 
24537  SLAudioIODeviceCapabilitiesItf deviceCaps;
24538  SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
24539  if (resultSL != SL_RESULT_SUCCESS) {
24540  /* The interface may not be supported so just report a default device. */
24541  goto return_default_device;
24542  }
24543 
24544  /* Playback */
24545  if (!isTerminated) {
24546  resultSL = (*deviceCaps)->GetAvailableAudioOutputs(deviceCaps, &deviceCount, pDeviceIDs);
24547  if (resultSL != SL_RESULT_SUCCESS) {
24548  return ma_result_from_OpenSL(resultSL);
24549  }
24550 
24551  for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
24552  ma_device_info deviceInfo;
24553  MA_ZERO_OBJECT(&deviceInfo);
24554  deviceInfo.id.opensl = pDeviceIDs[iDevice];
24555 
24556  SLAudioOutputDescriptor desc;
24557  resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, deviceInfo.id.opensl, &desc);
24558  if (resultSL == SL_RESULT_SUCCESS) {
24559  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), (const char*)desc.pDeviceName, (size_t)-1);
24560 
24561  ma_bool32 cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
24562  if (cbResult == MA_FALSE) {
24563  isTerminated = MA_TRUE;
24564  break;
24565  }
24566  }
24567  }
24568  }
24569 
24570  /* Capture */
24571  if (!isTerminated) {
24572  resultSL = (*deviceCaps)->GetAvailableAudioInputs(deviceCaps, &deviceCount, pDeviceIDs);
24573  if (resultSL != SL_RESULT_SUCCESS) {
24574  return ma_result_from_OpenSL(resultSL);
24575  }
24576 
24577  for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
24578  ma_device_info deviceInfo;
24579  MA_ZERO_OBJECT(&deviceInfo);
24580  deviceInfo.id.opensl = pDeviceIDs[iDevice];
24581 
24582  SLAudioInputDescriptor desc;
24583  resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, deviceInfo.id.opensl, &desc);
24584  if (resultSL == SL_RESULT_SUCCESS) {
24585  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), (const char*)desc.deviceName, (size_t)-1);
24586 
24587  ma_bool32 cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
24588  if (cbResult == MA_FALSE) {
24589  isTerminated = MA_TRUE;
24590  break;
24591  }
24592  }
24593  }
24594  }
24595 
24596  return MA_SUCCESS;
24597 #else
24598  goto return_default_device;
24599 #endif
24600 
24601 return_default_device:;
24602  cbResult = MA_TRUE;
24603 
24604  /* Playback. */
24605  if (cbResult) {
24606  ma_device_info deviceInfo;
24607  MA_ZERO_OBJECT(&deviceInfo);
24608  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
24609  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
24610  }
24611 
24612  /* Capture. */
24613  if (cbResult) {
24614  ma_device_info deviceInfo;
24615  MA_ZERO_OBJECT(&deviceInfo);
24616  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
24617  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
24618  }
24619 
24620  return MA_SUCCESS;
24621 }
24622 
24623 static void ma_context_add_data_format_ex__opensl(ma_context* pContext, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_device_info* pDeviceInfo)
24624 {
24625  MA_ASSERT(pContext != NULL);
24626  MA_ASSERT(pDeviceInfo != NULL);
24627 
24628  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
24629  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
24630  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
24631  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
24632  pDeviceInfo->nativeDataFormatCount += 1;
24633 }
24634 
24635 static void ma_context_add_data_format__opensl(ma_context* pContext, ma_format format, ma_device_info* pDeviceInfo)
24636 {
24637  ma_uint32 minChannels = 1;
24638  ma_uint32 maxChannels = 2;
24641  ma_uint32 iChannel;
24642  ma_uint32 iSampleRate;
24643 
24644  MA_ASSERT(pContext != NULL);
24645  MA_ASSERT(pDeviceInfo != NULL);
24646 
24647  /*
24648  Each sample format can support mono and stereo, and we'll support a small subset of standard
24649  rates (up to 48000). A better solution would be to somehow find a native sample rate.
24650  */
24651  for (iChannel = minChannels; iChannel < maxChannels; iChannel += 1) {
24652  for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); iSampleRate += 1) {
24653  ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iSampleRate];
24654  if (standardSampleRate >= minSampleRate && standardSampleRate <= maxSampleRate) {
24655  ma_context_add_data_format_ex__opensl(pContext, format, iChannel, standardSampleRate, pDeviceInfo);
24656  }
24657  }
24658  }
24659 }
24660 
24661 static ma_result ma_context_get_device_info__opensl(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
24662 {
24663  MA_ASSERT(pContext != NULL);
24664 
24665  MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it and then attempted to get device info. */
24666  if (g_maOpenSLInitCounter == 0) {
24667  return MA_INVALID_OPERATION;
24668  }
24669 
24670  /*
24671  TODO: Test Me.
24672 
24673  This is currently untested, so for now we are just returning default devices.
24674  */
24675 #if 0 && !defined(MA_ANDROID)
24676  SLAudioIODeviceCapabilitiesItf deviceCaps;
24677  SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
24678  if (resultSL != SL_RESULT_SUCCESS) {
24679  /* The interface may not be supported so just report a default device. */
24680  goto return_default_device;
24681  }
24682 
24683  if (deviceType == ma_device_type_playback) {
24684  SLAudioOutputDescriptor desc;
24685  resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
24686  if (resultSL != SL_RESULT_SUCCESS) {
24687  return ma_result_from_OpenSL(resultSL);
24688  }
24689 
24690  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), (const char*)desc.pDeviceName, (size_t)-1);
24691  } else {
24692  SLAudioInputDescriptor desc;
24693  resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
24694  if (resultSL != SL_RESULT_SUCCESS) {
24695  return ma_result_from_OpenSL(resultSL);
24696  }
24697 
24698  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), (const char*)desc.deviceName, (size_t)-1);
24699  }
24700 
24701  goto return_detailed_info;
24702 #else
24703  goto return_default_device;
24704 #endif
24705 
24706 return_default_device:
24707  if (pDeviceID != NULL) {
24708  if ((deviceType == ma_device_type_playback && pDeviceID->opensl != SL_DEFAULTDEVICEID_AUDIOOUTPUT) ||
24709  (deviceType == ma_device_type_capture && pDeviceID->opensl != SL_DEFAULTDEVICEID_AUDIOINPUT)) {
24710  return MA_NO_DEVICE; /* Don't know the device. */
24711  }
24712  }
24713 
24714  /* Name / Description */
24715  if (deviceType == ma_device_type_playback) {
24716  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
24717  } else {
24718  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
24719  }
24720 
24721  pDeviceInfo->isDefault = MA_TRUE;
24722 
24723  goto return_detailed_info;
24724 
24725 
24726 return_detailed_info:
24727 
24728  /*
24729  For now we're just outputting a set of values that are supported by the API but not necessarily supported
24730  by the device natively. Later on we should work on this so that it more closely reflects the device's
24731  actual native format.
24732  */
24733  pDeviceInfo->nativeDataFormatCount = 0;
24734 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24735  ma_context_add_data_format__opensl(pContext, ma_format_f32, pDeviceInfo);
24736 #endif
24737  ma_context_add_data_format__opensl(pContext, ma_format_s16, pDeviceInfo);
24738  ma_context_add_data_format__opensl(pContext, ma_format_u8, pDeviceInfo);
24739 
24740  return MA_SUCCESS;
24741 }
24742 
24743 
24744 #ifdef MA_ANDROID
24745 /*void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue, SLuint32 eventFlags, const void* pBuffer, SLuint32 bufferSize, SLuint32 dataUsed, void* pContext)*/
24746 static void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue, void* pUserData)
24747 {
24748  ma_device* pDevice = (ma_device*)pUserData;
24749  size_t periodSizeInBytes;
24750  ma_uint8* pBuffer;
24751  SLresult resultSL;
24752 
24753  MA_ASSERT(pDevice != NULL);
24754 
24755  (void)pBufferQueue;
24756 
24757  /*
24758  For now, don't do anything unless the buffer was fully processed. From what I can tell, it looks like
24759  OpenSL|ES 1.1 improves on buffer queues to the point that we could much more intelligently handle this,
24760  but unfortunately it looks like Android is only supporting OpenSL|ES 1.0.1 for now :(
24761  */
24762 
24763  /* Don't do anything if the device is not started. */
24764  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
24765  return;
24766  }
24767 
24768  /* Don't do anything if the device is being drained. */
24769  if (pDevice->opensl.isDrainingCapture) {
24770  return;
24771  }
24772 
24773  periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
24774  pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
24775 
24777 
24778  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pBuffer, periodSizeInBytes);
24779  if (resultSL != SL_RESULT_SUCCESS) {
24780  return;
24781  }
24782 
24783  pDevice->opensl.currentBufferIndexCapture = (pDevice->opensl.currentBufferIndexCapture + 1) % pDevice->capture.internalPeriods;
24784 }
24785 
24786 static void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue, void* pUserData)
24787 {
24788  ma_device* pDevice = (ma_device*)pUserData;
24789  size_t periodSizeInBytes;
24790  ma_uint8* pBuffer;
24791  SLresult resultSL;
24792 
24793  MA_ASSERT(pDevice != NULL);
24794 
24795  (void)pBufferQueue;
24796 
24797  /* Don't do anything if the device is not started. */
24798  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
24799  return;
24800  }
24801 
24802  /* Don't do anything if the device is being drained. */
24803  if (pDevice->opensl.isDrainingPlayback) {
24804  return;
24805  }
24806 
24808  pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
24809 
24811 
24812  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pBuffer, periodSizeInBytes);
24813  if (resultSL != SL_RESULT_SUCCESS) {
24814  return;
24815  }
24816 
24817  pDevice->opensl.currentBufferIndexPlayback = (pDevice->opensl.currentBufferIndexPlayback + 1) % pDevice->playback.internalPeriods;
24818 }
24819 #endif
24820 
24821 static ma_result ma_device_uninit__opensl(ma_device* pDevice)
24822 {
24823  MA_ASSERT(pDevice != NULL);
24824 
24825  MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it before uninitializing the device. */
24826  if (g_maOpenSLInitCounter == 0) {
24827  return MA_INVALID_OPERATION;
24828  }
24829 
24830  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24831  if (pDevice->opensl.pAudioRecorderObj) {
24832  MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioRecorderObj);
24833  }
24834 
24835  ma__free_from_callbacks(pDevice->opensl.pBufferCapture, &pDevice->pContext->allocationCallbacks);
24836  }
24837 
24838  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24839  if (pDevice->opensl.pAudioPlayerObj) {
24840  MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioPlayerObj);
24841  }
24842  if (pDevice->opensl.pOutputMixObj) {
24843  MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Destroy((SLObjectItf)pDevice->opensl.pOutputMixObj);
24844  }
24845 
24846  ma__free_from_callbacks(pDevice->opensl.pBufferPlayback, &pDevice->pContext->allocationCallbacks);
24847  }
24848 
24849  return MA_SUCCESS;
24850 }
24851 
24852 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24853 typedef SLAndroidDataFormat_PCM_EX ma_SLDataFormat_PCM;
24854 #else
24855 typedef SLDataFormat_PCM ma_SLDataFormat_PCM;
24856 #endif
24857 
24858 static ma_result ma_SLDataFormat_PCM_init__opensl(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, const ma_channel* channelMap, ma_SLDataFormat_PCM* pDataFormat)
24859 {
24860  /* We need to convert our format/channels/rate so that they aren't set to default. */
24861  if (format == ma_format_unknown) {
24862  format = MA_DEFAULT_FORMAT;
24863  }
24864  if (channels == 0) {
24865  channels = MA_DEFAULT_CHANNELS;
24866  }
24867  if (sampleRate == 0) {
24868  sampleRate = MA_DEFAULT_SAMPLE_RATE;
24869  }
24870 
24871 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24872  if (format == ma_format_f32) {
24873  pDataFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
24874  pDataFormat->representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
24875  } else {
24876  pDataFormat->formatType = SL_DATAFORMAT_PCM;
24877  }
24878 #else
24879  pDataFormat->formatType = SL_DATAFORMAT_PCM;
24880 #endif
24881 
24882  pDataFormat->numChannels = channels;
24883  ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = ma_round_to_standard_sample_rate__opensl(sampleRate) * 1000; /* In millihertz. Annoyingly, the sample rate variable is named differently between SLAndroidDataFormat_PCM_EX and SLDataFormat_PCM */
24884  pDataFormat->bitsPerSample = ma_get_bytes_per_sample(format)*8;
24885  pDataFormat->channelMask = ma_channel_map_to_channel_mask__opensl(channelMap, channels);
24886  pDataFormat->endianness = (ma_is_little_endian()) ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
24887 
24888  /*
24889  Android has a few restrictions on the format as documented here: https://developer.android.com/ndk/guides/audio/opensl-for-android.html
24890  - Only mono and stereo is supported.
24891  - Only u8 and s16 formats are supported.
24892  - Maximum sample rate of 48000.
24893  */
24894 #ifdef MA_ANDROID
24895  if (pDataFormat->numChannels > 2) {
24896  pDataFormat->numChannels = 2;
24897  }
24898 #if __ANDROID_API__ >= 21
24899  if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
24900  /* It's floating point. */
24901  MA_ASSERT(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
24902  if (pDataFormat->bitsPerSample > 32) {
24903  pDataFormat->bitsPerSample = 32;
24904  }
24905  } else {
24906  if (pDataFormat->bitsPerSample > 16) {
24907  pDataFormat->bitsPerSample = 16;
24908  }
24909  }
24910 #else
24911  if (pDataFormat->bitsPerSample > 16) {
24912  pDataFormat->bitsPerSample = 16;
24913  }
24914 #endif
24915  if (((SLDataFormat_PCM*)pDataFormat)->samplesPerSec > SL_SAMPLINGRATE_48) {
24916  ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = SL_SAMPLINGRATE_48;
24917  }
24918 #endif
24919 
24920  pDataFormat->containerSize = pDataFormat->bitsPerSample; /* Always tightly packed for now. */
24921 
24922  return MA_SUCCESS;
24923 }
24924 
24925 static ma_result ma_deconstruct_SLDataFormat_PCM__opensl(ma_SLDataFormat_PCM* pDataFormat, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
24926 {
24927  ma_bool32 isFloatingPoint = MA_FALSE;
24928 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24929  if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
24930  MA_ASSERT(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
24931  isFloatingPoint = MA_TRUE;
24932  }
24933 #endif
24934  if (isFloatingPoint) {
24935  if (pDataFormat->bitsPerSample == 32) {
24936  *pFormat = ma_format_f32;
24937  }
24938  } else {
24939  if (pDataFormat->bitsPerSample == 8) {
24940  *pFormat = ma_format_u8;
24941  } else if (pDataFormat->bitsPerSample == 16) {
24942  *pFormat = ma_format_s16;
24943  } else if (pDataFormat->bitsPerSample == 24) {
24944  *pFormat = ma_format_s24;
24945  } else if (pDataFormat->bitsPerSample == 32) {
24946  *pFormat = ma_format_s32;
24947  }
24948  }
24949 
24950  *pChannels = pDataFormat->numChannels;
24951  *pSampleRate = ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec / 1000;
24952  ma_channel_mask_to_channel_map__opensl(pDataFormat->channelMask, ma_min(pDataFormat->numChannels, channelMapCap), pChannelMap);
24953 
24954  return MA_SUCCESS;
24955 }
24956 
24957 static ma_result ma_device_init__opensl(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
24958 {
24959 #ifdef MA_ANDROID
24960  SLDataLocator_AndroidSimpleBufferQueue queue;
24961  SLresult resultSL;
24962  size_t bufferSizeInBytes;
24963  SLInterfaceID itfIDs[2];
24964  const SLboolean itfIDsRequired[] = {
24965  SL_BOOLEAN_TRUE, /* SL_IID_ANDROIDSIMPLEBUFFERQUEUE */
24966  SL_BOOLEAN_FALSE /* SL_IID_ANDROIDCONFIGURATION */
24967  };
24968 #endif
24969 
24970  MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it and then attempted to initialize a new device. */
24971  if (g_maOpenSLInitCounter == 0) {
24972  return MA_INVALID_OPERATION;
24973  }
24974 
24975  if (pConfig->deviceType == ma_device_type_loopback) {
24977  }
24978 
24979  /*
24980  For now, only supporting Android implementations of OpenSL|ES since that's the only one I've
24981  been able to test with and I currently depend on Android-specific extensions (simple buffer
24982  queues).
24983  */
24984 #ifdef MA_ANDROID
24985  itfIDs[0] = (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
24986  itfIDs[1] = (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION;
24987 
24988  /* No exclusive mode with OpenSL|ES. */
24989  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
24990  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
24992  }
24993 
24994  /* Now we can start initializing the device properly. */
24995  MA_ASSERT(pDevice != NULL);
24996  MA_ZERO_OBJECT(&pDevice->opensl);
24997 
24998  queue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
24999 
25000  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
25001  ma_SLDataFormat_PCM pcm;
25002  SLDataLocator_IODevice locatorDevice;
25003  SLDataSource source;
25004  SLDataSink sink;
25005  SLAndroidConfigurationItf pRecorderConfig;
25006 
25007  ma_SLDataFormat_PCM_init__opensl(pDescriptorCapture->format, pDescriptorCapture->channels, pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, &pcm);
25008 
25009  locatorDevice.locatorType = SL_DATALOCATOR_IODEVICE;
25010  locatorDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
25011  locatorDevice.deviceID = (pDescriptorCapture->pDeviceID == NULL) ? SL_DEFAULTDEVICEID_AUDIOINPUT : pDescriptorCapture->pDeviceID->opensl;
25012  locatorDevice.device = NULL;
25013 
25014  source.pLocator = &locatorDevice;
25015  source.pFormat = NULL;
25016 
25017  queue.numBuffers = pDescriptorCapture->periodCount;
25018 
25019  sink.pLocator = &queue;
25020  sink.pFormat = (SLDataFormat_PCM*)&pcm;
25021 
25022  resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
25023  if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
25024  /* Unsupported format. Fall back to something safer and try again. If this fails, just abort. */
25025  pcm.formatType = SL_DATAFORMAT_PCM;
25026  pcm.numChannels = 1;
25027  ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16; /* The name of the sample rate variable is different between SLAndroidDataFormat_PCM_EX and SLDataFormat_PCM. */
25028  pcm.bitsPerSample = 16;
25029  pcm.containerSize = pcm.bitsPerSample; /* Always tightly packed for now. */
25030  pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
25031  resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
25032  }
25033 
25034  if (resultSL != SL_RESULT_SUCCESS) {
25035  ma_device_uninit__opensl(pDevice);
25036  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to create audio recorder.", ma_result_from_OpenSL(resultSL));
25037  }
25038 
25039 
25040  /* Set the recording preset before realizing the player. */
25042  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pRecorderConfig);
25043  if (resultSL == SL_RESULT_SUCCESS) {
25044  SLint32 recordingPreset = ma_to_recording_preset__opensl(pConfig->opensl.recordingPreset);
25045  resultSL = (*pRecorderConfig)->SetConfiguration(pRecorderConfig, SL_ANDROID_KEY_RECORDING_PRESET, &recordingPreset, sizeof(SLint32));
25046  if (resultSL != SL_RESULT_SUCCESS) {
25047  /* Failed to set the configuration. Just keep going. */
25048  }
25049  }
25050  }
25051 
25052  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Realize((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_BOOLEAN_FALSE);
25053  if (resultSL != SL_RESULT_SUCCESS) {
25054  ma_device_uninit__opensl(pDevice);
25055  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize audio recorder.", ma_result_from_OpenSL(resultSL));
25056  }
25057 
25058  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_RECORD, &pDevice->opensl.pAudioRecorder);
25059  if (resultSL != SL_RESULT_SUCCESS) {
25060  ma_device_uninit__opensl(pDevice);
25061  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_RECORD interface.", ma_result_from_OpenSL(resultSL));
25062  }
25063 
25064  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueueCapture);
25065  if (resultSL != SL_RESULT_SUCCESS) {
25066  ma_device_uninit__opensl(pDevice);
25067  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_ANDROIDSIMPLEBUFFERQUEUE interface.", ma_result_from_OpenSL(resultSL));
25068  }
25069 
25070  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, ma_buffer_queue_callback_capture__opensl_android, pDevice);
25071  if (resultSL != SL_RESULT_SUCCESS) {
25072  ma_device_uninit__opensl(pDevice);
25073  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to register buffer queue callback.", ma_result_from_OpenSL(resultSL));
25074  }
25075 
25076  /* The internal format is determined by the "pcm" object. */
25077  ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDescriptorCapture->format, &pDescriptorCapture->channels, &pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, ma_countof(pDescriptorCapture->channelMap));
25078 
25079  /* Buffer. */
25080  pDescriptorCapture->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorCapture, pDescriptorCapture->sampleRate, pConfig->performanceProfile);
25081  pDevice->opensl.currentBufferIndexCapture = 0;
25082 
25083  bufferSizeInBytes = pDescriptorCapture->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) * pDescriptorCapture->periodCount;
25084  pDevice->opensl.pBufferCapture = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pDevice->pContext->allocationCallbacks);
25085  if (pDevice->opensl.pBufferCapture == NULL) {
25086  ma_device_uninit__opensl(pDevice);
25087  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to allocate memory for data buffer.", MA_OUT_OF_MEMORY);
25088  }
25089  MA_ZERO_MEMORY(pDevice->opensl.pBufferCapture, bufferSizeInBytes);
25090  }
25091 
25092  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
25093  ma_SLDataFormat_PCM pcm;
25094  SLDataSource source;
25095  SLDataLocator_OutputMix outmixLocator;
25096  SLDataSink sink;
25097  SLAndroidConfigurationItf pPlayerConfig;
25098 
25099  ma_SLDataFormat_PCM_init__opensl(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &pcm);
25100 
25101  resultSL = (*g_maEngineSL)->CreateOutputMix(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pOutputMixObj, 0, NULL, NULL);
25102  if (resultSL != SL_RESULT_SUCCESS) {
25103  ma_device_uninit__opensl(pDevice);
25104  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to create output mix.", ma_result_from_OpenSL(resultSL));
25105  }
25106 
25107  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Realize((SLObjectItf)pDevice->opensl.pOutputMixObj, SL_BOOLEAN_FALSE);
25108  if (resultSL != SL_RESULT_SUCCESS) {
25109  ma_device_uninit__opensl(pDevice);
25110  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize output mix object.", ma_result_from_OpenSL(resultSL));
25111  }
25112 
25113  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->GetInterface((SLObjectItf)pDevice->opensl.pOutputMixObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_OUTPUTMIX, &pDevice->opensl.pOutputMix);
25114  if (resultSL != SL_RESULT_SUCCESS) {
25115  ma_device_uninit__opensl(pDevice);
25116  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_OUTPUTMIX interface.", ma_result_from_OpenSL(resultSL));
25117  }
25118 
25119  /* Set the output device. */
25120  if (pDescriptorPlayback->pDeviceID != NULL) {
25121  SLuint32 deviceID_OpenSL = pDescriptorPlayback->pDeviceID->opensl;
25122  MA_OPENSL_OUTPUTMIX(pDevice->opensl.pOutputMix)->ReRoute((SLOutputMixItf)pDevice->opensl.pOutputMix, 1, &deviceID_OpenSL);
25123  }
25124 
25125  queue.numBuffers = pDescriptorPlayback->periodCount;
25126 
25127  source.pLocator = &queue;
25128  source.pFormat = (SLDataFormat_PCM*)&pcm;
25129 
25130  outmixLocator.locatorType = SL_DATALOCATOR_OUTPUTMIX;
25131  outmixLocator.outputMix = (SLObjectItf)pDevice->opensl.pOutputMixObj;
25132 
25133  sink.pLocator = &outmixLocator;
25134  sink.pFormat = NULL;
25135 
25136  resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
25137  if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
25138  /* Unsupported format. Fall back to something safer and try again. If this fails, just abort. */
25139  pcm.formatType = SL_DATAFORMAT_PCM;
25140  pcm.numChannels = 2;
25141  ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16;
25142  pcm.bitsPerSample = 16;
25143  pcm.containerSize = pcm.bitsPerSample; /* Always tightly packed for now. */
25144  pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
25145  resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
25146  }
25147 
25148  if (resultSL != SL_RESULT_SUCCESS) {
25149  ma_device_uninit__opensl(pDevice);
25150  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to create audio player.", ma_result_from_OpenSL(resultSL));
25151  }
25152 
25153 
25154  /* Set the stream type before realizing the player. */
25156  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pPlayerConfig);
25157  if (resultSL == SL_RESULT_SUCCESS) {
25158  SLint32 streamType = ma_to_stream_type__opensl(pConfig->opensl.streamType);
25159  resultSL = (*pPlayerConfig)->SetConfiguration(pPlayerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
25160  if (resultSL != SL_RESULT_SUCCESS) {
25161  /* Failed to set the configuration. Just keep going. */
25162  }
25163  }
25164  }
25165 
25166  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Realize((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_BOOLEAN_FALSE);
25167  if (resultSL != SL_RESULT_SUCCESS) {
25168  ma_device_uninit__opensl(pDevice);
25169  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize audio player.", ma_result_from_OpenSL(resultSL));
25170  }
25171 
25172  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_PLAY, &pDevice->opensl.pAudioPlayer);
25173  if (resultSL != SL_RESULT_SUCCESS) {
25174  ma_device_uninit__opensl(pDevice);
25175  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_PLAY interface.", ma_result_from_OpenSL(resultSL));
25176  }
25177 
25178  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueuePlayback);
25179  if (resultSL != SL_RESULT_SUCCESS) {
25180  ma_device_uninit__opensl(pDevice);
25181  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_ANDROIDSIMPLEBUFFERQUEUE interface.", ma_result_from_OpenSL(resultSL));
25182  }
25183 
25184  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, ma_buffer_queue_callback_playback__opensl_android, pDevice);
25185  if (resultSL != SL_RESULT_SUCCESS) {
25186  ma_device_uninit__opensl(pDevice);
25187  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to register buffer queue callback.", ma_result_from_OpenSL(resultSL));
25188  }
25189 
25190  /* The internal format is determined by the "pcm" object. */
25191  ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDescriptorPlayback->format, &pDescriptorPlayback->channels, &pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap));
25192 
25193  /* Buffer. */
25194  pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
25195  pDevice->opensl.currentBufferIndexPlayback = 0;
25196 
25197  bufferSizeInBytes = pDescriptorPlayback->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) * pDescriptorPlayback->periodCount;
25198  pDevice->opensl.pBufferPlayback = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pDevice->pContext->allocationCallbacks);
25199  if (pDevice->opensl.pBufferPlayback == NULL) {
25200  ma_device_uninit__opensl(pDevice);
25201  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to allocate memory for data buffer.", MA_OUT_OF_MEMORY);
25202  }
25203  MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, bufferSizeInBytes);
25204  }
25205 
25206  return MA_SUCCESS;
25207 #else
25208  return MA_NO_BACKEND; /* Non-Android implementations are not supported. */
25209 #endif
25210 }
25211 
25212 static ma_result ma_device_start__opensl(ma_device* pDevice)
25213 {
25214  SLresult resultSL;
25215  size_t periodSizeInBytes;
25216  ma_uint32 iPeriod;
25217 
25218  MA_ASSERT(pDevice != NULL);
25219 
25220  MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it and then attempted to start the device. */
25221  if (g_maOpenSLInitCounter == 0) {
25222  return MA_INVALID_OPERATION;
25223  }
25224 
25225  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
25226  resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_RECORDING);
25227  if (resultSL != SL_RESULT_SUCCESS) {
25228  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to start internal capture device.", ma_result_from_OpenSL(resultSL));
25229  }
25230 
25231  periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
25232  for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
25233  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pDevice->opensl.pBufferCapture + (periodSizeInBytes * iPeriod), periodSizeInBytes);
25234  if (resultSL != SL_RESULT_SUCCESS) {
25235  MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
25236  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to enqueue buffer for capture device.", ma_result_from_OpenSL(resultSL));
25237  }
25238  }
25239  }
25240 
25241  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
25242  resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_PLAYING);
25243  if (resultSL != SL_RESULT_SUCCESS) {
25244  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to start internal playback device.", ma_result_from_OpenSL(resultSL));
25245  }
25246 
25247  /* In playback mode (no duplex) we need to load some initial buffers. In duplex mode we need to enqueu silent buffers. */
25248  if (pDevice->type == ma_device_type_duplex) {
25249  MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, pDevice->playback.internalPeriodSizeInFrames * pDevice->playback.internalPeriods * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
25250  } else {
25251  ma_device__read_frames_from_client(pDevice, pDevice->playback.internalPeriodSizeInFrames * pDevice->playback.internalPeriods, pDevice->opensl.pBufferPlayback);
25252  }
25253 
25255  for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
25256  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pDevice->opensl.pBufferPlayback + (periodSizeInBytes * iPeriod), periodSizeInBytes);
25257  if (resultSL != SL_RESULT_SUCCESS) {
25258  MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
25259  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to enqueue buffer for playback device.", ma_result_from_OpenSL(resultSL));
25260  }
25261  }
25262  }
25263 
25264  return MA_SUCCESS;
25265 }
25266 
25267 static ma_result ma_device_drain__opensl(ma_device* pDevice, ma_device_type deviceType)
25268 {
25269  SLAndroidSimpleBufferQueueItf pBufferQueue;
25270 
25271  MA_ASSERT(deviceType == ma_device_type_capture || deviceType == ma_device_type_playback);
25272 
25273  if (pDevice->type == ma_device_type_capture) {
25274  pBufferQueue = (SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture;
25275  pDevice->opensl.isDrainingCapture = MA_TRUE;
25276  } else {
25277  pBufferQueue = (SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback;
25278  pDevice->opensl.isDrainingPlayback = MA_TRUE;
25279  }
25280 
25281  for (;;) {
25282  SLAndroidSimpleBufferQueueState state;
25283 
25284  MA_OPENSL_BUFFERQUEUE(pBufferQueue)->GetState(pBufferQueue, &state);
25285  if (state.count == 0) {
25286  break;
25287  }
25288 
25289  ma_sleep(10);
25290  }
25291 
25292  if (pDevice->type == ma_device_type_capture) {
25293  pDevice->opensl.isDrainingCapture = MA_FALSE;
25294  } else {
25295  pDevice->opensl.isDrainingPlayback = MA_FALSE;
25296  }
25297 
25298  return MA_SUCCESS;
25299 }
25300 
25301 static ma_result ma_device_stop__opensl(ma_device* pDevice)
25302 {
25303  SLresult resultSL;
25304  ma_stop_proc onStop;
25305 
25306  MA_ASSERT(pDevice != NULL);
25307 
25308  MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it before stopping/uninitializing the device. */
25309  if (g_maOpenSLInitCounter == 0) {
25310  return MA_INVALID_OPERATION;
25311  }
25312 
25313  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
25314  ma_device_drain__opensl(pDevice, ma_device_type_capture);
25315 
25316  resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
25317  if (resultSL != SL_RESULT_SUCCESS) {
25318  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal capture device.", ma_result_from_OpenSL(resultSL));
25319  }
25320 
25321  MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture);
25322  }
25323 
25324  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
25325  ma_device_drain__opensl(pDevice, ma_device_type_playback);
25326 
25327  resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
25328  if (resultSL != SL_RESULT_SUCCESS) {
25329  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal playback device.", ma_result_from_OpenSL(resultSL));
25330  }
25331 
25332  MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback);
25333  }
25334 
25335  /* Make sure the client is aware that the device has stopped. There may be an OpenSL|ES callback for this, but I haven't found it. */
25336  onStop = pDevice->onStop;
25337  if (onStop) {
25338  onStop(pDevice);
25339  }
25340 
25341  return MA_SUCCESS;
25342 }
25343 
25344 
25345 static ma_result ma_context_uninit__opensl(ma_context* pContext)
25346 {
25347  MA_ASSERT(pContext != NULL);
25348  MA_ASSERT(pContext->backend == ma_backend_opensl);
25349  (void)pContext;
25350 
25351  /* Uninit global data. */
25352  ma_spinlock_lock(&g_maOpenSLSpinlock);
25353  {
25354  MA_ASSERT(g_maOpenSLInitCounter > 0); /* If you've triggered this, it means you have ma_context_init/uninit mismatch. Each successful call to ma_context_init() must be matched up with a call to ma_context_uninit(). */
25355 
25356  g_maOpenSLInitCounter -= 1;
25357  if (g_maOpenSLInitCounter == 0) {
25358  (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
25359  }
25360  }
25361  ma_spinlock_unlock(&g_maOpenSLSpinlock);
25362 
25363  return MA_SUCCESS;
25364 }
25365 
25366 static ma_result ma_dlsym_SLInterfaceID__opensl(ma_context* pContext, const char* pName, ma_handle* pHandle)
25367 {
25368  /* We need to return an error if the symbol cannot be found. This is important because there have been reports that some symbols do not exist. */
25369  ma_handle* p = (ma_handle*)ma_dlsym(pContext, pContext->opensl.libOpenSLES, pName);
25370  if (p == NULL) {
25371  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_INFO, "[OpenSL|ES] Cannot find symbol %s", pName);
25372  return MA_NO_BACKEND;
25373  }
25374 
25375  *pHandle = *p;
25376  return MA_SUCCESS;
25377 }
25378 
25379 static ma_result ma_context_init_engine_nolock__opensl(ma_context* pContext)
25380 {
25381  g_maOpenSLInitCounter += 1;
25382  if (g_maOpenSLInitCounter == 1) {
25383  SLresult resultSL;
25384 
25385  resultSL = ((ma_slCreateEngine_proc)pContext->opensl.slCreateEngine)(&g_maEngineObjectSL, 0, NULL, 0, NULL, NULL);
25386  if (resultSL != SL_RESULT_SUCCESS) {
25387  g_maOpenSLInitCounter -= 1;
25388  return ma_result_from_OpenSL(resultSL);
25389  }
25390 
25391  (*g_maEngineObjectSL)->Realize(g_maEngineObjectSL, SL_BOOLEAN_FALSE);
25392 
25393  resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_ENGINE, &g_maEngineSL);
25394  if (resultSL != SL_RESULT_SUCCESS) {
25395  (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
25396  g_maOpenSLInitCounter -= 1;
25397  return ma_result_from_OpenSL(resultSL);
25398  }
25399  }
25400 
25401  return MA_SUCCESS;
25402 }
25403 
25404 static ma_result ma_context_init__opensl(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
25405 {
25406  ma_result result;
25407 
25408 #if !defined(MA_NO_RUNTIME_LINKING)
25409  size_t i;
25410  const char* libOpenSLESNames[] = {
25411  "libOpenSLES.so"
25412  };
25413 #endif
25414 
25415  MA_ASSERT(pContext != NULL);
25416 
25417  (void)pConfig;
25418 
25419 #if !defined(MA_NO_RUNTIME_LINKING)
25420  /*
25421  Dynamically link against libOpenSLES.so. I have now had multiple reports that SL_IID_ANDROIDSIMPLEBUFFERQUEUE cannot be found. One
25422  report was happening at compile time and another at runtime. To try working around this, I'm going to link to libOpenSLES at runtime
25423  and extract the symbols rather than reference them directly. This should, hopefully, fix these issues as the compiler won't see any
25424  references to the symbols and will hopefully skip the checks.
25425  */
25426  for (i = 0; i < ma_countof(libOpenSLESNames); i += 1) {
25427  pContext->opensl.libOpenSLES = ma_dlopen(pContext, libOpenSLESNames[i]);
25428  if (pContext->opensl.libOpenSLES != NULL) {
25429  break;
25430  }
25431  }
25432 
25433  if (pContext->opensl.libOpenSLES == NULL) {
25434  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_INFO, "[OpenSL|ES] Could not find libOpenSLES.so");
25435  return MA_NO_BACKEND;
25436  }
25437 
25438  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ENGINE", &pContext->opensl.SL_IID_ENGINE);
25439  if (result != MA_SUCCESS) {
25440  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25441  return result;
25442  }
25443 
25444  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_AUDIOIODEVICECAPABILITIES", &pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES);
25445  if (result != MA_SUCCESS) {
25446  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25447  return result;
25448  }
25449 
25450  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ANDROIDSIMPLEBUFFERQUEUE", &pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE);
25451  if (result != MA_SUCCESS) {
25452  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25453  return result;
25454  }
25455 
25456  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_RECORD", &pContext->opensl.SL_IID_RECORD);
25457  if (result != MA_SUCCESS) {
25458  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25459  return result;
25460  }
25461 
25462  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_PLAY", &pContext->opensl.SL_IID_PLAY);
25463  if (result != MA_SUCCESS) {
25464  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25465  return result;
25466  }
25467 
25468  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_OUTPUTMIX", &pContext->opensl.SL_IID_OUTPUTMIX);
25469  if (result != MA_SUCCESS) {
25470  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25471  return result;
25472  }
25473 
25474  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ANDROIDCONFIGURATION", &pContext->opensl.SL_IID_ANDROIDCONFIGURATION);
25475  if (result != MA_SUCCESS) {
25476  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25477  return result;
25478  }
25479 
25480  pContext->opensl.slCreateEngine = (ma_proc)ma_dlsym(pContext, pContext->opensl.libOpenSLES, "slCreateEngine");
25481  if (pContext->opensl.slCreateEngine == NULL) {
25482  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25483  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_INFO, "[OpenSL|ES] Cannot find symbol slCreateEngine.");
25484  return MA_NO_BACKEND;
25485  }
25486 #else
25487  pContext->opensl.SL_IID_ENGINE = (ma_handle)SL_IID_ENGINE;
25488  pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES = (ma_handle)SL_IID_AUDIOIODEVICECAPABILITIES;
25489  pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE = (ma_handle)SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
25490  pContext->opensl.SL_IID_RECORD = (ma_handle)SL_IID_RECORD;
25491  pContext->opensl.SL_IID_PLAY = (ma_handle)SL_IID_PLAY;
25492  pContext->opensl.SL_IID_OUTPUTMIX = (ma_handle)SL_IID_OUTPUTMIX;
25493  pContext->opensl.SL_IID_ANDROIDCONFIGURATION = (ma_handle)SL_IID_ANDROIDCONFIGURATION;
25494  pContext->opensl.slCreateEngine = (ma_proc)slCreateEngine;
25495 #endif
25496 
25497 
25498  /* Initialize global data first if applicable. */
25499  ma_spinlock_lock(&g_maOpenSLSpinlock);
25500  {
25501  result = ma_context_init_engine_nolock__opensl(pContext);
25502  }
25503  ma_spinlock_unlock(&g_maOpenSLSpinlock);
25504 
25505  if (result != MA_SUCCESS) {
25506  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
25507  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_INFO, "[OpenSL|ES] Failed to initialize OpenSL engine.");
25508  return result;
25509  }
25510 
25511  pCallbacks->onContextInit = ma_context_init__opensl;
25512  pCallbacks->onContextUninit = ma_context_uninit__opensl;
25513  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__opensl;
25514  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__opensl;
25515  pCallbacks->onDeviceInit = ma_device_init__opensl;
25516  pCallbacks->onDeviceUninit = ma_device_uninit__opensl;
25517  pCallbacks->onDeviceStart = ma_device_start__opensl;
25518  pCallbacks->onDeviceStop = ma_device_stop__opensl;
25519  pCallbacks->onDeviceRead = NULL; /* Not needed because OpenSL|ES is asynchronous. */
25520  pCallbacks->onDeviceWrite = NULL; /* Not needed because OpenSL|ES is asynchronous. */
25521  pCallbacks->onDeviceDataLoop = NULL; /* Not needed because OpenSL|ES is asynchronous. */
25522 
25523  return MA_SUCCESS;
25524 }
25525 #endif /* OpenSL|ES */
25526 
25527 
25528 /******************************************************************************
25529 
25530 Web Audio Backend
25531 
25532 ******************************************************************************/
25533 #ifdef MA_HAS_WEBAUDIO
25534 #include <emscripten/emscripten.h>
25535 
25536 static ma_bool32 ma_is_capture_supported__webaudio()
25537 {
25538  return EM_ASM_INT({
25539  return (navigator.mediaDevices !== undefined && navigator.mediaDevices.getUserMedia !== undefined);
25540  }, 0) != 0; /* Must pass in a dummy argument for C99 compatibility. */
25541 }
25542 
25543 #ifdef __cplusplus
25544 extern "C" {
25545 #endif
25546 void EMSCRIPTEN_KEEPALIVE ma_device_process_pcm_frames_capture__webaudio(ma_device* pDevice, int frameCount, float* pFrames)
25547 {
25548  ma_device_handle_backend_data_callback(pDevice, NULL, pFrames, (ma_uint32)frameCount);
25549 }
25550 
25551 void EMSCRIPTEN_KEEPALIVE ma_device_process_pcm_frames_playback__webaudio(ma_device* pDevice, int frameCount, float* pFrames)
25552 {
25553  ma_device_handle_backend_data_callback(pDevice, pFrames, NULL, (ma_uint32)frameCount);
25554 }
25555 #ifdef __cplusplus
25556 }
25557 #endif
25558 
25559 static ma_result ma_context_enumerate_devices__webaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
25560 {
25561  ma_bool32 cbResult = MA_TRUE;
25562 
25563  MA_ASSERT(pContext != NULL);
25564  MA_ASSERT(callback != NULL);
25565 
25566  /* Only supporting default devices for now. */
25567 
25568  /* Playback. */
25569  if (cbResult) {
25570  ma_device_info deviceInfo;
25571  MA_ZERO_OBJECT(&deviceInfo);
25572  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
25573  deviceInfo.isDefault = MA_TRUE; /* Only supporting default devices. */
25574  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
25575  }
25576 
25577  /* Capture. */
25578  if (cbResult) {
25579  if (ma_is_capture_supported__webaudio()) {
25580  ma_device_info deviceInfo;
25581  MA_ZERO_OBJECT(&deviceInfo);
25582  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
25583  deviceInfo.isDefault = MA_TRUE; /* Only supporting default devices. */
25584  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
25585  }
25586  }
25587 
25588  return MA_SUCCESS;
25589 }
25590 
25591 static ma_result ma_context_get_device_info__webaudio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
25592 {
25593  MA_ASSERT(pContext != NULL);
25594 
25595  if (deviceType == ma_device_type_capture && !ma_is_capture_supported__webaudio()) {
25596  return MA_NO_DEVICE;
25597  }
25598 
25599  MA_ZERO_MEMORY(pDeviceInfo->id.webaudio, sizeof(pDeviceInfo->id.webaudio));
25600 
25601  /* Only supporting default devices for now. */
25602  (void)pDeviceID;
25603  if (deviceType == ma_device_type_playback) {
25604  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
25605  } else {
25606  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
25607  }
25608 
25609  /* Only supporting default devices. */
25610  pDeviceInfo->isDefault = MA_TRUE;
25611 
25612  /* Web Audio can support any number of channels and sample rates. It only supports f32 formats, however. */
25613  pDeviceInfo->nativeDataFormats[0].flags = 0;
25614  pDeviceInfo->nativeDataFormats[0].format = ma_format_unknown;
25615  pDeviceInfo->nativeDataFormats[0].channels = 0; /* All channels are supported. */
25616  pDeviceInfo->nativeDataFormats[0].sampleRate = EM_ASM_INT({
25617  try {
25618  var temp = new (window.AudioContext || window.webkitAudioContext)();
25619  var sampleRate = temp.sampleRate;
25620  temp.close();
25621  return sampleRate;
25622  } catch(e) {
25623  return 0;
25624  }
25625  }, 0); /* Must pass in a dummy argument for C99 compatibility. */
25626 
25627  if (pDeviceInfo->nativeDataFormats[0].sampleRate == 0) {
25628  return MA_NO_DEVICE;
25629  }
25630 
25631  pDeviceInfo->nativeDataFormatCount = 1;
25632 
25633  return MA_SUCCESS;
25634 }
25635 
25636 
25637 static void ma_device_uninit_by_index__webaudio(ma_device* pDevice, ma_device_type deviceType, int deviceIndex)
25638 {
25639  MA_ASSERT(pDevice != NULL);
25640 
25641  EM_ASM({
25642  var device = miniaudio.get_device_by_index($0);
25643 
25644  /* Make sure all nodes are disconnected and marked for collection. */
25645  if (device.scriptNode !== undefined) {
25646  device.scriptNode.onaudioprocess = function(e) {}; /* We want to reset the callback to ensure it doesn't get called after AudioContext.close() has returned. Shouldn't happen since we're disconnecting, but just to be safe... */
25647  device.scriptNode.disconnect();
25648  device.scriptNode = undefined;
25649  }
25650  if (device.streamNode !== undefined) {
25651  device.streamNode.disconnect();
25652  device.streamNode = undefined;
25653  }
25654 
25655  /*
25656  Stop the device. I think there is a chance the callback could get fired after calling this, hence why we want
25657  to clear the callback before closing.
25658  */
25659  device.webaudio.close();
25660  device.webaudio = undefined;
25661 
25662  /* Can't forget to free the intermediary buffer. This is the buffer that's shared between JavaScript and C. */
25663  if (device.intermediaryBuffer !== undefined) {
25664  Module._free(device.intermediaryBuffer);
25665  device.intermediaryBuffer = undefined;
25666  device.intermediaryBufferView = undefined;
25667  device.intermediaryBufferSizeInBytes = undefined;
25668  }
25669 
25670  /* Make sure the device is untracked so the slot can be reused later. */
25671  miniaudio.untrack_device_by_index($0);
25672  }, deviceIndex, deviceType);
25673 }
25674 
25675 static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
25676 {
25677  MA_ASSERT(pDevice != NULL);
25678 
25679  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
25680  ma_device_uninit_by_index__webaudio(pDevice, ma_device_type_capture, pDevice->webaudio.indexCapture);
25681  }
25682 
25683  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
25684  ma_device_uninit_by_index__webaudio(pDevice, ma_device_type_playback, pDevice->webaudio.indexPlayback);
25685  }
25686 
25687  return MA_SUCCESS;
25688 }
25689 
25690 static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(const ma_device_descriptor* pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
25691 {
25692  /*
25693  There have been reports of the default buffer size being too small on some browsers. There have been reports of the default buffer
25694  size being too small on some browsers. If we're using default buffer size, we'll make sure the period size is a big biffer than our
25695  standard defaults.
25696  */
25697  ma_uint32 periodSizeInFrames;
25698 
25699  if (pDescriptor->periodSizeInFrames == 0) {
25700  if (pDescriptor->periodSizeInMilliseconds == 0) {
25701  if (performanceProfile == ma_performance_profile_low_latency) {
25702  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(33, nativeSampleRate); /* 1 frame @ 30 FPS */
25703  } else {
25704  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(333, nativeSampleRate);
25705  }
25706  } else {
25707  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptor->periodSizeInMilliseconds, nativeSampleRate);
25708  }
25709  } else {
25710  periodSizeInFrames = pDescriptor->periodSizeInFrames;
25711  }
25712 
25713  /* The size of the buffer must be a power of 2 and between 256 and 16384. */
25714  if (periodSizeInFrames < 256) {
25715  periodSizeInFrames = 256;
25716  } else if (periodSizeInFrames > 16384) {
25717  periodSizeInFrames = 16384;
25718  } else {
25719  periodSizeInFrames = ma_next_power_of_2(periodSizeInFrames);
25720  }
25721 
25722  return periodSizeInFrames;
25723 }
25724 
25725 static ma_result ma_device_init_by_type__webaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
25726 {
25727  int deviceIndex;
25728  ma_uint32 channels;
25729  ma_uint32 sampleRate;
25730  ma_uint32 periodSizeInFrames;
25731 
25732  MA_ASSERT(pDevice != NULL);
25733  MA_ASSERT(pConfig != NULL);
25734  MA_ASSERT(deviceType != ma_device_type_duplex);
25735 
25736  if (deviceType == ma_device_type_capture && !ma_is_capture_supported__webaudio()) {
25737  return MA_NO_DEVICE;
25738  }
25739 
25740  /* We're going to calculate some stuff in C just to simplify the JS code. */
25741  channels = (pDescriptor->channels > 0) ? pDescriptor->channels : MA_DEFAULT_CHANNELS;
25742  sampleRate = (pDescriptor->sampleRate > 0) ? pDescriptor->sampleRate : MA_DEFAULT_SAMPLE_RATE;
25743  periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__webaudio(pDescriptor, sampleRate, pConfig->performanceProfile);
25744 
25745 
25746  /* We create the device on the JavaScript side and reference it using an index. We use this to make it possible to reference the device between JavaScript and C. */
25747  deviceIndex = EM_ASM_INT({
25748  var channels = $0;
25749  var sampleRate = $1;
25750  var bufferSize = $2; /* In PCM frames. */
25751  var isCapture = $3;
25752  var pDevice = $4;
25753 
25754  if (typeof(miniaudio) === 'undefined') {
25755  return -1; /* Context not initialized. */
25756  }
25757 
25758  var device = {};
25759 
25760  /* The AudioContext must be created in a suspended state. */
25761  device.webaudio = new (window.AudioContext || window.webkitAudioContext)({sampleRate:sampleRate});
25762  device.webaudio.suspend();
25763  device.state = 1; /* MA_STATE_STOPPED */
25764 
25765  /*
25766  We need an intermediary buffer which we use for JavaScript and C interop. This buffer stores interleaved f32 PCM data. Because it's passed between
25767  JavaScript and C it needs to be allocated and freed using Module._malloc() and Module._free().
25768  */
25769  device.intermediaryBufferSizeInBytes = channels * bufferSize * 4;
25770  device.intermediaryBuffer = Module._malloc(device.intermediaryBufferSizeInBytes);
25771  device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
25772 
25773  /*
25774  Both playback and capture devices use a ScriptProcessorNode for performing per-sample operations.
25775 
25776  ScriptProcessorNode is actually deprecated so this is likely to be temporary. The way this works for playback is very simple. You just set a callback
25777  that's periodically fired, just like a normal audio callback function. But apparently this design is "flawed" and is now deprecated in favour of
25778  something called AudioWorklets which _forces_ you to load a _separate_ .js file at run time... nice... Hopefully ScriptProcessorNode will continue to
25779  work for years to come, but this may need to change to use AudioSourceBufferNode instead, which I think is what Emscripten uses for it's built-in SDL
25780  implementation. I'll be avoiding that insane AudioWorklet API like the plague...
25781 
25782  For capture it is a bit unintuitive. We use the ScriptProccessorNode _only_ to get the raw PCM data. It is connected to an AudioContext just like the
25783  playback case, however we just output silence to the AudioContext instead of passing any real data. It would make more sense to me to use the
25784  MediaRecorder API, but unfortunately you need to specify a MIME time (Opus, Vorbis, etc.) for the binary blob that's returned to the client, but I've
25785  been unable to figure out how to get this as raw PCM. The closest I can think is to use the MIME type for WAV files and just parse it, but I don't know
25786  how well this would work. Although ScriptProccessorNode is deprecated, in practice it seems to have pretty good browser support so I'm leaving it like
25787  this for now. If anyone knows how I could get raw PCM data using the MediaRecorder API please let me know!
25788  */
25789  device.scriptNode = device.webaudio.createScriptProcessor(bufferSize, channels, channels);
25790 
25791  if (isCapture) {
25792  device.scriptNode.onaudioprocess = function(e) {
25793  if (device.intermediaryBuffer === undefined) {
25794  return; /* This means the device has been uninitialized. */
25795  }
25796 
25797  if(device.intermediaryBufferView.length == 0) {
25798  /* Recreate intermediaryBufferView when losing reference to the underlying buffer, probably due to emscripten resizing heap. */
25799  device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
25800  }
25801 
25802  /* Make sure silence it output to the AudioContext destination. Not doing this will cause sound to come out of the speakers! */
25803  for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
25804  e.outputBuffer.getChannelData(iChannel).fill(0.0);
25805  }
25806 
25807  /* There are some situations where we may want to send silence to the client. */
25808  var sendSilence = false;
25809  if (device.streamNode === undefined) {
25810  sendSilence = true;
25811  }
25812 
25813  /* Sanity check. This will never happen, right? */
25814  if (e.inputBuffer.numberOfChannels != channels) {
25815  console.log("Capture: Channel count mismatch. " + e.inputBufer.numberOfChannels + " != " + channels + ". Sending silence.");
25816  sendSilence = true;
25817  }
25818 
25819  /* This looped design guards against the situation where e.inputBuffer is a different size to the original buffer size. Should never happen in practice. */
25820  var totalFramesProcessed = 0;
25821  while (totalFramesProcessed < e.inputBuffer.length) {
25822  var framesRemaining = e.inputBuffer.length - totalFramesProcessed;
25823  var framesToProcess = framesRemaining;
25824  if (framesToProcess > (device.intermediaryBufferSizeInBytes/channels/4)) {
25825  framesToProcess = (device.intermediaryBufferSizeInBytes/channels/4);
25826  }
25827 
25828  /* We need to do the reverse of the playback case. We need to interleave the input data and copy it into the intermediary buffer. Then we send it to the client. */
25829  if (sendSilence) {
25830  device.intermediaryBufferView.fill(0.0);
25831  } else {
25832  for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
25833  for (var iChannel = 0; iChannel < e.inputBuffer.numberOfChannels; ++iChannel) {
25834  device.intermediaryBufferView[iFrame*channels + iChannel] = e.inputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame];
25835  }
25836  }
25837  }
25838 
25839  /* Send data to the client from our intermediary buffer. */
25840  ccall("ma_device_process_pcm_frames_capture__webaudio", "undefined", ["number", "number", "number"], [pDevice, framesToProcess, device.intermediaryBuffer]);
25841 
25842  totalFramesProcessed += framesToProcess;
25843  }
25844  };
25845 
25846  navigator.mediaDevices.getUserMedia({audio:true, video:false})
25847  .then(function(stream) {
25848  device.streamNode = device.webaudio.createMediaStreamSource(stream);
25849  device.streamNode.connect(device.scriptNode);
25850  device.scriptNode.connect(device.webaudio.destination);
25851  })
25852  .catch(function(error) {
25853  /* I think this should output silence... */
25854  device.scriptNode.connect(device.webaudio.destination);
25855  });
25856  } else {
25857  device.scriptNode.onaudioprocess = function(e) {
25858  if (device.intermediaryBuffer === undefined) {
25859  return; /* This means the device has been uninitialized. */
25860  }
25861 
25862  if(device.intermediaryBufferView.length == 0) {
25863  /* Recreate intermediaryBufferView when losing reference to the underlying buffer, probably due to emscripten resizing heap. */
25864  device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
25865  }
25866 
25867  var outputSilence = false;
25868 
25869  /* Sanity check. This will never happen, right? */
25870  if (e.outputBuffer.numberOfChannels != channels) {
25871  console.log("Playback: Channel count mismatch. " + e.outputBufer.numberOfChannels + " != " + channels + ". Outputting silence.");
25872  outputSilence = true;
25873  return;
25874  }
25875 
25876  /* This looped design guards against the situation where e.outputBuffer is a different size to the original buffer size. Should never happen in practice. */
25877  var totalFramesProcessed = 0;
25878  while (totalFramesProcessed < e.outputBuffer.length) {
25879  var framesRemaining = e.outputBuffer.length - totalFramesProcessed;
25880  var framesToProcess = framesRemaining;
25881  if (framesToProcess > (device.intermediaryBufferSizeInBytes/channels/4)) {
25882  framesToProcess = (device.intermediaryBufferSizeInBytes/channels/4);
25883  }
25884 
25885  /* Read data from the client into our intermediary buffer. */
25886  ccall("ma_device_process_pcm_frames_playback__webaudio", "undefined", ["number", "number", "number"], [pDevice, framesToProcess, device.intermediaryBuffer]);
25887 
25888  /* At this point we'll have data in our intermediary buffer which we now need to deinterleave and copy over to the output buffers. */
25889  if (outputSilence) {
25890  for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
25891  e.outputBuffer.getChannelData(iChannel).fill(0.0);
25892  }
25893  } else {
25894  for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
25895  for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
25896  e.outputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame] = device.intermediaryBufferView[iFrame*channels + iChannel];
25897  }
25898  }
25899  }
25900 
25901  totalFramesProcessed += framesToProcess;
25902  }
25903  };
25904 
25905  device.scriptNode.connect(device.webaudio.destination);
25906  }
25907 
25908  return miniaudio.track_device(device);
25909  }, channels, sampleRate, periodSizeInFrames, deviceType == ma_device_type_capture, pDevice);
25910 
25911  if (deviceIndex < 0) {
25913  }
25914 
25915  if (deviceType == ma_device_type_capture) {
25916  pDevice->webaudio.indexCapture = deviceIndex;
25917  } else {
25918  pDevice->webaudio.indexPlayback = deviceIndex;
25919  }
25920 
25921  pDescriptor->format = ma_format_f32;
25922  pDescriptor->channels = channels;
25924  pDescriptor->sampleRate = EM_ASM_INT({ return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
25925  pDescriptor->periodSizeInFrames = periodSizeInFrames;
25926  pDescriptor->periodCount = 1;
25927 
25928  return MA_SUCCESS;
25929 }
25930 
25931 static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
25932 {
25933  ma_result result;
25934 
25935  if (pConfig->deviceType == ma_device_type_loopback) {
25937  }
25938 
25939  /* No exclusive mode with Web Audio. */
25940  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
25941  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
25943  }
25944 
25945  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
25946  result = ma_device_init_by_type__webaudio(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
25947  if (result != MA_SUCCESS) {
25948  return result;
25949  }
25950  }
25951 
25952  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
25953  result = ma_device_init_by_type__webaudio(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
25954  if (result != MA_SUCCESS) {
25955  if (pConfig->deviceType == ma_device_type_duplex) {
25956  ma_device_uninit_by_index__webaudio(pDevice, ma_device_type_capture, pDevice->webaudio.indexCapture);
25957  }
25958  return result;
25959  }
25960  }
25961 
25962  return MA_SUCCESS;
25963 }
25964 
25965 static ma_result ma_device_start__webaudio(ma_device* pDevice)
25966 {
25967  MA_ASSERT(pDevice != NULL);
25968 
25969  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
25970  EM_ASM({
25971  var device = miniaudio.get_device_by_index($0);
25972  device.webaudio.resume();
25973  device.state = 2; /* MA_STATE_STARTED */
25974  }, pDevice->webaudio.indexCapture);
25975  }
25976 
25977  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
25978  EM_ASM({
25979  var device = miniaudio.get_device_by_index($0);
25980  device.webaudio.resume();
25981  device.state = 2; /* MA_STATE_STARTED */
25982  }, pDevice->webaudio.indexPlayback);
25983  }
25984 
25985  return MA_SUCCESS;
25986 }
25987 
25988 static ma_result ma_device_stop__webaudio(ma_device* pDevice)
25989 {
25990  MA_ASSERT(pDevice != NULL);
25991 
25992  /*
25993  From the WebAudio API documentation for AudioContext.suspend():
25994 
25995  Suspends the progression of AudioContext's currentTime, allows any current context processing blocks that are already processed to be played to the
25996  destination, and then allows the system to release its claim on audio hardware.
25997 
25998  I read this to mean that "any current context processing blocks" are processed by suspend() - i.e. They they are drained. We therefore shouldn't need to
25999  do any kind of explicit draining.
26000  */
26001 
26002  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
26003  EM_ASM({
26004  var device = miniaudio.get_device_by_index($0);
26005  device.webaudio.suspend();
26006  device.state = 1; /* MA_STATE_STOPPED */
26007  }, pDevice->webaudio.indexCapture);
26008  }
26009 
26010  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
26011  EM_ASM({
26012  var device = miniaudio.get_device_by_index($0);
26013  device.webaudio.suspend();
26014  device.state = 1; /* MA_STATE_STOPPED */
26015  }, pDevice->webaudio.indexPlayback);
26016  }
26017 
26018  ma_stop_proc onStop = pDevice->onStop;
26019  if (onStop) {
26020  onStop(pDevice);
26021  }
26022 
26023  return MA_SUCCESS;
26024 }
26025 
26026 static ma_result ma_context_uninit__webaudio(ma_context* pContext)
26027 {
26028  MA_ASSERT(pContext != NULL);
26029  MA_ASSERT(pContext->backend == ma_backend_webaudio);
26030 
26031  /* Nothing needs to be done here. */
26032  (void)pContext;
26033 
26034  return MA_SUCCESS;
26035 }
26036 
26037 static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
26038 {
26039  int resultFromJS;
26040 
26041  MA_ASSERT(pContext != NULL);
26042 
26043  (void)pConfig; /* Unused. */
26044 
26045  /* Here is where our global JavaScript object is initialized. */
26046  resultFromJS = EM_ASM_INT({
26047  if ((window.AudioContext || window.webkitAudioContext) === undefined) {
26048  return 0; /* Web Audio not supported. */
26049  }
26050 
26051  if (typeof(miniaudio) === 'undefined') {
26052  miniaudio = {};
26053  miniaudio.devices = []; /* Device cache for mapping devices to indexes for JavaScript/C interop. */
26054 
26055  miniaudio.track_device = function(device) {
26056  /* Try inserting into a free slot first. */
26057  for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
26058  if (miniaudio.devices[iDevice] == null) {
26059  miniaudio.devices[iDevice] = device;
26060  return iDevice;
26061  }
26062  }
26063 
26064  /* Getting here means there is no empty slots in the array so we just push to the end. */
26065  miniaudio.devices.push(device);
26066  return miniaudio.devices.length - 1;
26067  };
26068 
26069  miniaudio.untrack_device_by_index = function(deviceIndex) {
26070  /* We just set the device's slot to null. The slot will get reused in the next call to ma_track_device. */
26071  miniaudio.devices[deviceIndex] = null;
26072 
26073  /* Trim the array if possible. */
26074  while (miniaudio.devices.length > 0) {
26075  if (miniaudio.devices[miniaudio.devices.length-1] == null) {
26076  miniaudio.devices.pop();
26077  } else {
26078  break;
26079  }
26080  }
26081  };
26082 
26083  miniaudio.untrack_device = function(device) {
26084  for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
26085  if (miniaudio.devices[iDevice] == device) {
26086  return miniaudio.untrack_device_by_index(iDevice);
26087  }
26088  }
26089  };
26090 
26091  miniaudio.get_device_by_index = function(deviceIndex) {
26092  return miniaudio.devices[deviceIndex];
26093  };
26094 
26095  miniaudio.unlock_event_types = (function(){
26096  return ['touchstart', 'touchend', 'click'];
26097  })();
26098 
26099  miniaudio.unlock = function() {
26100  for(var i = 0; i < miniaudio.devices.length; ++i) {
26101  var device = miniaudio.devices[i];
26102  if (device != null && device.webaudio != null && device.state === 2 /* MA_STATE_STARTED */) {
26103  device.webaudio.resume();
26104  }
26105  }
26106  miniaudio.unlock_event_types.map(function(event_type) {
26107  document.removeEventListener(event_type, miniaudio.unlock, true);
26108  });
26109  };
26110 
26111  miniaudio.unlock_event_types.map(function(event_type) {
26112  document.addEventListener(event_type, miniaudio.unlock, true);
26113  });
26114  }
26115 
26116  return 1;
26117  }, 0); /* Must pass in a dummy argument for C99 compatibility. */
26118 
26119  if (resultFromJS != 1) {
26121  }
26122 
26123  pCallbacks->onContextInit = ma_context_init__webaudio;
26124  pCallbacks->onContextUninit = ma_context_uninit__webaudio;
26125  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__webaudio;
26126  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__webaudio;
26127  pCallbacks->onDeviceInit = ma_device_init__webaudio;
26128  pCallbacks->onDeviceUninit = ma_device_uninit__webaudio;
26129  pCallbacks->onDeviceStart = ma_device_start__webaudio;
26130  pCallbacks->onDeviceStop = ma_device_stop__webaudio;
26131  pCallbacks->onDeviceRead = NULL; /* Not needed because WebAudio is asynchronous. */
26132  pCallbacks->onDeviceWrite = NULL; /* Not needed because WebAudio is asynchronous. */
26133  pCallbacks->onDeviceDataLoop = NULL; /* Not needed because WebAudio is asynchronous. */
26134 
26135  return MA_SUCCESS;
26136 }
26137 #endif /* Web Audio */
26138 
26139 
26140 
26141 static ma_bool32 ma__is_channel_map_valid(const ma_channel* channelMap, ma_uint32 channels)
26142 {
26143  /* A blank channel map should be allowed, in which case it should use an appropriate default which will depend on context. */
26144  if (channelMap[0] != MA_CHANNEL_NONE) {
26145  ma_uint32 iChannel;
26146 
26147  if (channels == 0 || channels > MA_MAX_CHANNELS) {
26148  return MA_FALSE; /* Channel count out of range. */
26149  }
26150 
26151  /* A channel cannot be present in the channel map more than once. */
26152  for (iChannel = 0; iChannel < channels; ++iChannel) {
26153  ma_uint32 jChannel;
26154  for (jChannel = iChannel + 1; jChannel < channels; ++jChannel) {
26155  if (channelMap[iChannel] == channelMap[jChannel]) {
26156  return MA_FALSE;
26157  }
26158  }
26159  }
26160  }
26161 
26162  return MA_TRUE;
26163 }
26164 
26165 
26167 {
26168  ma_result result;
26169 
26170  MA_ASSERT(pDevice != NULL);
26171 
26172  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
26173  if (pDevice->capture.format == ma_format_unknown) {
26174  pDevice->capture.format = pDevice->capture.internalFormat;
26175  }
26176  if (pDevice->capture.channels == 0) {
26177  pDevice->capture.channels = pDevice->capture.internalChannels;
26178  }
26179  if (pDevice->capture.channelMap[0] == MA_CHANNEL_NONE) {
26181  if (pDevice->capture.internalChannels == pDevice->capture.channels) {
26183  } else {
26186  } else {
26188  }
26189  }
26190  }
26191  }
26192 
26193  if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
26194  if (pDevice->playback.format == ma_format_unknown) {
26195  pDevice->playback.format = pDevice->playback.internalFormat;
26196  }
26197  if (pDevice->playback.channels == 0) {
26198  pDevice->playback.channels = pDevice->playback.internalChannels;
26199  }
26200  if (pDevice->playback.channelMap[0] == MA_CHANNEL_NONE) {
26202  if (pDevice->playback.internalChannels == pDevice->playback.channels) {
26204  } else {
26207  } else {
26209  }
26210  }
26211  }
26212  }
26213 
26214  if (pDevice->sampleRate == 0) {
26215  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
26216  pDevice->sampleRate = pDevice->capture.internalSampleRate;
26217  } else {
26218  pDevice->sampleRate = pDevice->playback.internalSampleRate;
26219  }
26220  }
26221 
26222  /* Data converters. */
26223  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
26224  /* Converting from internal device format to client format. */
26226  converterConfig.formatIn = pDevice->capture.internalFormat;
26227  converterConfig.channelsIn = pDevice->capture.internalChannels;
26228  converterConfig.sampleRateIn = pDevice->capture.internalSampleRate;
26230  converterConfig.formatOut = pDevice->capture.format;
26231  converterConfig.channelsOut = pDevice->capture.channels;
26232  converterConfig.sampleRateOut = pDevice->sampleRate;
26234  converterConfig.channelMixMode = pDevice->capture.channelMixMode;
26235  converterConfig.resampling.allowDynamicSampleRate = MA_FALSE;
26236  converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
26237  converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
26238  converterConfig.resampling.speex.quality = pDevice->resampling.speex.quality;
26239 
26240  result = ma_data_converter_init(&converterConfig, &pDevice->capture.converter);
26241  if (result != MA_SUCCESS) {
26242  return result;
26243  }
26244  }
26245 
26246  if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
26247  /* Converting from client format to device format. */
26249  converterConfig.formatIn = pDevice->playback.format;
26250  converterConfig.channelsIn = pDevice->playback.channels;
26251  converterConfig.sampleRateIn = pDevice->sampleRate;
26253  converterConfig.formatOut = pDevice->playback.internalFormat;
26254  converterConfig.channelsOut = pDevice->playback.internalChannels;
26255  converterConfig.sampleRateOut = pDevice->playback.internalSampleRate;
26257  converterConfig.channelMixMode = pDevice->playback.channelMixMode;
26258  converterConfig.resampling.allowDynamicSampleRate = MA_FALSE;
26259  converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
26260  converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
26261  converterConfig.resampling.speex.quality = pDevice->resampling.speex.quality;
26262 
26263  result = ma_data_converter_init(&converterConfig, &pDevice->playback.converter);
26264  if (result != MA_SUCCESS) {
26265  return result;
26266  }
26267  }
26268 
26269  return MA_SUCCESS;
26270 }
26271 
26272 
26274 {
26275  ma_device* pDevice = (ma_device*)pData;
26276  MA_ASSERT(pDevice != NULL);
26277 
26278 #ifdef MA_WIN32
26279  ma_CoInitializeEx(pDevice->pContext, NULL, MA_COINIT_VALUE);
26280 #endif
26281 
26282  /*
26283  When the device is being initialized it's initial state is set to MA_STATE_UNINITIALIZED. Before returning from
26284  ma_device_init(), the state needs to be set to something valid. In miniaudio the device's default state immediately
26285  after initialization is stopped, so therefore we need to mark the device as such. miniaudio will wait on the worker
26286  thread to signal an event to know when the worker thread is ready for action.
26287  */
26289  ma_event_signal(&pDevice->stopEvent);
26290 
26291  for (;;) { /* <-- This loop just keeps the thread alive. The main audio loop is inside. */
26292  ma_result startResult;
26293  ma_result stopResult; /* <-- This will store the result from onDeviceStop(). If it returns an error, we don't fire the onStop callback. */
26294 
26295  /* We wait on an event to know when something has requested that the device be started and the main loop entered. */
26296  ma_event_wait(&pDevice->wakeupEvent);
26297 
26298  /* Default result code. */
26299  pDevice->workResult = MA_SUCCESS;
26300 
26301  /* If the reason for the wake up is that we are terminating, just break from the loop. */
26302  if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
26303  break;
26304  }
26305 
26306  /*
26307  Getting to this point means the device is wanting to get started. The function that has requested that the device
26308  be started will be waiting on an event (pDevice->startEvent) which means we need to make sure we signal the event
26309  in both the success and error case. It's important that the state of the device is set _before_ signaling the event.
26310  */
26312 
26313  /* If the device has a start callback, start it now. */
26314  if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
26315  startResult = pDevice->pContext->callbacks.onDeviceStart(pDevice);
26316  } else {
26317  startResult = MA_SUCCESS;
26318  }
26319 
26320  if (startResult != MA_SUCCESS) {
26321  pDevice->workResult = startResult;
26322  continue; /* Failed to start. Loop back to the start and wait for something to happen (pDevice->wakeupEvent). */
26323  }
26324 
26325  /* Make sure the state is set appropriately. */
26327  ma_event_signal(&pDevice->startEvent);
26328 
26329  if (pDevice->pContext->callbacks.onDeviceDataLoop != NULL) {
26330  pDevice->pContext->callbacks.onDeviceDataLoop(pDevice);
26331  } else {
26332  /* The backend is not using a custom main loop implementation, so now fall back to the blocking read-write implementation. */
26334  }
26335 
26336  /* Getting here means we have broken from the main loop which happens the application has requested that device be stopped. */
26337  if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
26338  stopResult = pDevice->pContext->callbacks.onDeviceStop(pDevice);
26339  } else {
26340  stopResult = MA_SUCCESS; /* No stop callback with the backend. Just assume successful. */
26341  }
26342 
26343  /*
26344  After the device has stopped, make sure an event is posted. Don't post an onStop event if
26345  stopping failed. This can happen on some backends when the underlying stream has been
26346  stopped due to the device being physically unplugged or disabled via an OS setting.
26347  */
26348  if (pDevice->onStop && stopResult != MA_SUCCESS) {
26349  pDevice->onStop(pDevice);
26350  }
26351 
26352  /* A function somewhere is waiting for the device to have stopped for real so we need to signal an event to allow it to continue. */
26354  ma_event_signal(&pDevice->stopEvent);
26355  }
26356 
26357 #ifdef MA_WIN32
26358  ma_CoUninitialize(pDevice->pContext);
26359 #endif
26360 
26361  return (ma_thread_result)0;
26362 }
26363 
26364 
26365 /* Helper for determining whether or not the given device is initialized. */
26367 {
26368  if (pDevice == NULL) {
26369  return MA_FALSE;
26370  }
26371 
26372  return ma_device_get_state(pDevice) != MA_STATE_UNINITIALIZED;
26373 }
26374 
26375 
26376 #ifdef MA_WIN32
26377 static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
26378 {
26379  ma_CoUninitialize(pContext);
26380  ma_dlclose(pContext, pContext->win32.hUser32DLL);
26381  ma_dlclose(pContext, pContext->win32.hOle32DLL);
26382  ma_dlclose(pContext, pContext->win32.hAdvapi32DLL);
26383 
26384  return MA_SUCCESS;
26385 }
26386 
26387 static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
26388 {
26389 #ifdef MA_WIN32_DESKTOP
26390  /* Ole32.dll */
26391  pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
26392  if (pContext->win32.hOle32DLL == NULL) {
26394  }
26395 
26396  pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitializeEx");
26397  pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoUninitialize");
26398  pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoCreateInstance");
26399  pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoTaskMemFree");
26400  pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "PropVariantClear");
26401  pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "StringFromGUID2");
26402 
26403 
26404  /* User32.dll */
26405  pContext->win32.hUser32DLL = ma_dlopen(pContext, "user32.dll");
26406  if (pContext->win32.hUser32DLL == NULL) {
26408  }
26409 
26410  pContext->win32.GetForegroundWindow = (ma_proc)ma_dlsym(pContext, pContext->win32.hUser32DLL, "GetForegroundWindow");
26411  pContext->win32.GetDesktopWindow = (ma_proc)ma_dlsym(pContext, pContext->win32.hUser32DLL, "GetDesktopWindow");
26412 
26413 
26414  /* Advapi32.dll */
26415  pContext->win32.hAdvapi32DLL = ma_dlopen(pContext, "advapi32.dll");
26416  if (pContext->win32.hAdvapi32DLL == NULL) {
26418  }
26419 
26420  pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegOpenKeyExA");
26421  pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegCloseKey");
26422  pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegQueryValueExA");
26423 #endif
26424 
26425  ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
26426  return MA_SUCCESS;
26427 }
26428 #else
26430 {
26431 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
26432  ma_dlclose(pContext, pContext->posix.pthreadSO);
26433 #else
26434  (void)pContext;
26435 #endif
26436 
26437  return MA_SUCCESS;
26438 }
26439 
26441 {
26442  /* pthread */
26443 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
26444  const char* libpthreadFileNames[] = {
26445  "libpthread.so",
26446  "libpthread.so.0",
26447  "libpthread.dylib"
26448  };
26449  size_t i;
26450 
26451  for (i = 0; i < sizeof(libpthreadFileNames) / sizeof(libpthreadFileNames[0]); ++i) {
26452  pContext->posix.pthreadSO = ma_dlopen(pContext, libpthreadFileNames[i]);
26453  if (pContext->posix.pthreadSO != NULL) {
26454  break;
26455  }
26456  }
26457 
26458  if (pContext->posix.pthreadSO == NULL) {
26460  }
26461 
26462  pContext->posix.pthread_create = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_create");
26463  pContext->posix.pthread_join = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_join");
26464  pContext->posix.pthread_mutex_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_init");
26465  pContext->posix.pthread_mutex_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_destroy");
26466  pContext->posix.pthread_mutex_lock = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_lock");
26467  pContext->posix.pthread_mutex_unlock = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_unlock");
26468  pContext->posix.pthread_cond_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_init");
26469  pContext->posix.pthread_cond_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_destroy");
26470  pContext->posix.pthread_cond_wait = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_wait");
26471  pContext->posix.pthread_cond_signal = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_signal");
26472  pContext->posix.pthread_attr_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_init");
26473  pContext->posix.pthread_attr_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_destroy");
26474  pContext->posix.pthread_attr_setschedpolicy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_setschedpolicy");
26475  pContext->posix.pthread_attr_getschedparam = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_getschedparam");
26476  pContext->posix.pthread_attr_setschedparam = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_setschedparam");
26477 #else
26478  pContext->posix.pthread_create = (ma_proc)pthread_create;
26479  pContext->posix.pthread_join = (ma_proc)pthread_join;
26480  pContext->posix.pthread_mutex_init = (ma_proc)pthread_mutex_init;
26481  pContext->posix.pthread_mutex_destroy = (ma_proc)pthread_mutex_destroy;
26482  pContext->posix.pthread_mutex_lock = (ma_proc)pthread_mutex_lock;
26483  pContext->posix.pthread_mutex_unlock = (ma_proc)pthread_mutex_unlock;
26484  pContext->posix.pthread_cond_init = (ma_proc)pthread_cond_init;
26485  pContext->posix.pthread_cond_destroy = (ma_proc)pthread_cond_destroy;
26486  pContext->posix.pthread_cond_wait = (ma_proc)pthread_cond_wait;
26487  pContext->posix.pthread_cond_signal = (ma_proc)pthread_cond_signal;
26488  pContext->posix.pthread_attr_init = (ma_proc)pthread_attr_init;
26489  pContext->posix.pthread_attr_destroy = (ma_proc)pthread_attr_destroy;
26490 #if !defined(__EMSCRIPTEN__)
26491  pContext->posix.pthread_attr_setschedpolicy = (ma_proc)pthread_attr_setschedpolicy;
26492  pContext->posix.pthread_attr_getschedparam = (ma_proc)pthread_attr_getschedparam;
26493  pContext->posix.pthread_attr_setschedparam = (ma_proc)pthread_attr_setschedparam;
26494 #endif
26495 #endif
26496 
26497  return MA_SUCCESS;
26498 }
26499 #endif
26500 
26502 {
26503  ma_result result;
26504 #ifdef MA_WIN32
26505  result = ma_context_init_backend_apis__win32(pContext);
26506 #else
26507  result = ma_context_init_backend_apis__nix(pContext);
26508 #endif
26509 
26510  return result;
26511 }
26512 
26514 {
26515  ma_result result;
26516 #ifdef MA_WIN32
26517  result = ma_context_uninit_backend_apis__win32(pContext);
26518 #else
26519  result = ma_context_uninit_backend_apis__nix(pContext);
26520 #endif
26521 
26522  return result;
26523 }
26524 
26525 
26527 {
26528  MA_ASSERT(pContext != NULL);
26529 
26530  if (pContext->callbacks.onDeviceRead == NULL && pContext->callbacks.onDeviceWrite == NULL) {
26531  if (pContext->callbacks.onDeviceDataLoop == NULL) {
26532  return MA_TRUE;
26533  } else {
26534  return MA_FALSE;
26535  }
26536  } else {
26537  return MA_FALSE;
26538  }
26539 }
26540 
26541 
26543 {
26546 
26547  return config;
26548 }
26549 
26550 MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config* pConfig, ma_context* pContext)
26551 {
26552  ma_result result;
26553  ma_context_config defaultConfig;
26554  ma_backend defaultBackends[ma_backend_null+1];
26555  ma_uint32 iBackend;
26556  ma_backend* pBackendsToIterate;
26557  ma_uint32 backendsToIterateCount;
26558 
26559  if (pContext == NULL) {
26560  return MA_INVALID_ARGS;
26561  }
26562 
26563  MA_ZERO_OBJECT(pContext);
26564 
26565  /* Always make sure the config is set first to ensure properties are available as soon as possible. */
26566  if (pConfig == NULL) {
26567  defaultConfig = ma_context_config_init();
26568  pConfig = &defaultConfig;
26569  }
26570 
26571  /* Allocation callbacks need to come first because they'll be passed around to other areas. */
26573  if (result != MA_SUCCESS) {
26574  return result;
26575  }
26576 
26577  /* Get a lot set up first so we can start logging ASAP. */
26578  if (pConfig->pLog != NULL) {
26579  pContext->pLog = pConfig->pLog;
26580  } else {
26581  result = ma_log_init(&pContext->allocationCallbacks, &pContext->log);
26582  if (result == MA_SUCCESS) {
26583  pContext->pLog = &pContext->log;
26584  } else {
26585  pContext->pLog = NULL; /* Logging is not available. */
26586  }
26587  }
26588 
26589  pContext->logCallback = pConfig->logCallback;
26590  pContext->threadPriority = pConfig->threadPriority;
26591  pContext->threadStackSize = pConfig->threadStackSize;
26592  pContext->pUserData = pConfig->pUserData;
26593 
26594  /* Backend APIs need to be initialized first. This is where external libraries will be loaded and linked. */
26595  result = ma_context_init_backend_apis(pContext);
26596  if (result != MA_SUCCESS) {
26597  return result;
26598  }
26599 
26600  for (iBackend = 0; iBackend <= ma_backend_null; ++iBackend) {
26601  defaultBackends[iBackend] = (ma_backend)iBackend;
26602  }
26603 
26604  pBackendsToIterate = (ma_backend*)backends;
26605  backendsToIterateCount = backendCount;
26606  if (pBackendsToIterate == NULL) {
26607  pBackendsToIterate = (ma_backend*)defaultBackends;
26608  backendsToIterateCount = ma_countof(defaultBackends);
26609  }
26610 
26611  MA_ASSERT(pBackendsToIterate != NULL);
26612 
26613  for (iBackend = 0; iBackend < backendsToIterateCount; iBackend += 1) {
26614  ma_backend backend = pBackendsToIterate[iBackend];
26615 
26616  /* Make sure all callbacks are reset so we don't accidentally drag in any from previously failed initialization attempts. */
26617  MA_ZERO_OBJECT(&pContext->callbacks);
26618 
26619  /* These backends are using the new callback system. */
26620  switch (backend) {
26621  #ifdef MA_HAS_WASAPI
26622  case ma_backend_wasapi:
26623  {
26624  pContext->callbacks.onContextInit = ma_context_init__wasapi;
26625  } break;
26626  #endif
26627  #ifdef MA_HAS_DSOUND
26628  case ma_backend_dsound:
26629  {
26630  pContext->callbacks.onContextInit = ma_context_init__dsound;
26631  } break;
26632  #endif
26633  #ifdef MA_HAS_WINMM
26634  case ma_backend_winmm:
26635  {
26636  pContext->callbacks.onContextInit = ma_context_init__winmm;
26637  } break;
26638  #endif
26639  #ifdef MA_HAS_COREAUDIO
26640  case ma_backend_coreaudio:
26641  {
26642  pContext->callbacks.onContextInit = ma_context_init__coreaudio;
26643  } break;
26644  #endif
26645  #ifdef MA_HAS_SNDIO
26646  case ma_backend_sndio:
26647  {
26648  pContext->callbacks.onContextInit = ma_context_init__sndio;
26649  } break;
26650  #endif
26651  #ifdef MA_HAS_AUDIO4
26652  case ma_backend_audio4:
26653  {
26654  pContext->callbacks.onContextInit = ma_context_init__audio4;
26655  } break;
26656  #endif
26657  #ifdef MA_HAS_OSS
26658  case ma_backend_oss:
26659  {
26660  pContext->callbacks.onContextInit = ma_context_init__oss;
26661  } break;
26662  #endif
26663  #ifdef MA_HAS_PULSEAUDIO
26664  case ma_backend_pulseaudio:
26665  {
26666  pContext->callbacks.onContextInit = ma_context_init__pulse;
26667  } break;
26668  #endif
26669  #ifdef MA_HAS_ALSA
26670  case ma_backend_alsa:
26671  {
26672  pContext->callbacks.onContextInit = ma_context_init__alsa;
26673  } break;
26674  #endif
26675  #ifdef MA_HAS_JACK
26676  case ma_backend_jack:
26677  {
26678  pContext->callbacks.onContextInit = ma_context_init__jack;
26679  } break;
26680  #endif
26681  #ifdef MA_HAS_AAUDIO
26682  case ma_backend_aaudio:
26683  {
26684  pContext->callbacks.onContextInit = ma_context_init__aaudio;
26685  } break;
26686  #endif
26687  #ifdef MA_HAS_OPENSL
26688  case ma_backend_opensl:
26689  {
26690  pContext->callbacks.onContextInit = ma_context_init__opensl;
26691  } break;
26692  #endif
26693  #ifdef MA_HAS_WEBAUDIO
26694  case ma_backend_webaudio:
26695  {
26696  pContext->callbacks.onContextInit = ma_context_init__webaudio;
26697  } break;
26698  #endif
26699  #ifdef MA_HAS_CUSTOM
26700  case ma_backend_custom:
26701  {
26702  /* Slightly different logic for custom backends. Custom backends can optionally set all of their callbacks in the config. */
26703  pContext->callbacks = pConfig->custom;
26704  } break;
26705  #endif
26706  #ifdef MA_HAS_NULL
26707  case ma_backend_null:
26708  {
26710  } break;
26711  #endif
26712 
26713  default: break;
26714  }
26715 
26716  if (pContext->callbacks.onContextInit != NULL) {
26717  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Attempting to initialize %s backend...\n", ma_get_backend_name(backend));
26718  result = pContext->callbacks.onContextInit(pContext, pConfig, &pContext->callbacks);
26719  } else {
26720  result = MA_NO_BACKEND;
26721  }
26722 
26723  /* If this iteration was successful, return. */
26724  if (result == MA_SUCCESS) {
26725  result = ma_mutex_init(&pContext->deviceEnumLock);
26726  if (result != MA_SUCCESS) {
26727  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "Failed to initialize mutex for device enumeration. ma_context_get_devices() is not thread safe.\n", result);
26728  }
26729 
26730  result = ma_mutex_init(&pContext->deviceInfoLock);
26731  if (result != MA_SUCCESS) {
26732  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_WARNING, "Failed to initialize mutex for device info retrieval. ma_context_get_device_info() is not thread safe.\n", result);
26733  }
26734 
26735  #ifdef MA_DEBUG_OUTPUT
26736  {
26737  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] Endian: %s\n", ma_is_little_endian() ? "LE" : "BE");
26738  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] SSE2: %s\n", ma_has_sse2() ? "YES" : "NO");
26739  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] AVX2: %s\n", ma_has_avx2() ? "YES" : "NO");
26740  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] AVX512F: %s\n", ma_has_avx512f() ? "YES" : "NO");
26741  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] NEON: %s\n", ma_has_neon() ? "YES" : "NO");
26742  }
26743  #endif
26744 
26745  pContext->backend = backend;
26746  return result;
26747  } else {
26748  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Failed to initialize %s backend.\n", ma_get_backend_name(backend));
26749  }
26750  }
26751 
26752  /* If we get here it means an error occurred. */
26753  MA_ZERO_OBJECT(pContext); /* Safety. */
26754  return MA_NO_BACKEND;
26755 }
26756 
26758 {
26759  if (pContext == NULL) {
26760  return MA_INVALID_ARGS;
26761  }
26762 
26763  if (pContext->callbacks.onContextUninit != NULL) {
26764  pContext->callbacks.onContextUninit(pContext);
26765  }
26766 
26767  ma_mutex_uninit(&pContext->deviceEnumLock);
26768  ma_mutex_uninit(&pContext->deviceInfoLock);
26771 
26772  if (pContext->pLog == &pContext->log) {
26773  ma_log_uninit(&pContext->log);
26774  }
26775 
26776  return MA_SUCCESS;
26777 }
26778 
26780 {
26781  return sizeof(ma_context);
26782 }
26783 
26784 
26786 {
26787  if (pContext == NULL) {
26788  return NULL;
26789  }
26790 
26791  return pContext->pLog;
26792 }
26793 
26794 
26796 {
26797  ma_result result;
26798 
26799  if (pContext == NULL || callback == NULL) {
26800  return MA_INVALID_ARGS;
26801  }
26802 
26803  if (pContext->callbacks.onContextEnumerateDevices == NULL) {
26804  return MA_INVALID_OPERATION;
26805  }
26806 
26807  ma_mutex_lock(&pContext->deviceEnumLock);
26808  {
26809  result = pContext->callbacks.onContextEnumerateDevices(pContext, callback, pUserData);
26810  }
26811  ma_mutex_unlock(&pContext->deviceEnumLock);
26812 
26813  return result;
26814 }
26815 
26816 
26817 static ma_bool32 ma_context_get_devices__enum_callback(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData)
26818 {
26819  /*
26820  We need to insert the device info into our main internal buffer. Where it goes depends on the device type. If it's a capture device
26821  it's just appended to the end. If it's a playback device it's inserted just before the first capture device.
26822  */
26823 
26824  /*
26825  First make sure we have room. Since the number of devices we add to the list is usually relatively small I've decided to use a
26826  simple fixed size increment for buffer expansion.
26827  */
26828  const ma_uint32 bufferExpansionCount = 2;
26829  const ma_uint32 totalDeviceInfoCount = pContext->playbackDeviceInfoCount + pContext->captureDeviceInfoCount;
26830 
26831  if (totalDeviceInfoCount >= pContext->deviceInfoCapacity) {
26832  ma_uint32 oldCapacity = pContext->deviceInfoCapacity;
26833  ma_uint32 newCapacity = oldCapacity + bufferExpansionCount;
26834  ma_device_info* pNewInfos = (ma_device_info*)ma__realloc_from_callbacks(pContext->pDeviceInfos, sizeof(*pContext->pDeviceInfos)*newCapacity, sizeof(*pContext->pDeviceInfos)*oldCapacity, &pContext->allocationCallbacks);
26835  if (pNewInfos == NULL) {
26836  return MA_FALSE; /* Out of memory. */
26837  }
26838 
26839  pContext->pDeviceInfos = pNewInfos;
26840  pContext->deviceInfoCapacity = newCapacity;
26841  }
26842 
26843  if (deviceType == ma_device_type_playback) {
26844  /* Playback. Insert just before the first capture device. */
26845 
26846  /* The first thing to do is move all of the capture devices down a slot. */
26847  ma_uint32 iFirstCaptureDevice = pContext->playbackDeviceInfoCount;
26848  size_t iCaptureDevice;
26849  for (iCaptureDevice = totalDeviceInfoCount; iCaptureDevice > iFirstCaptureDevice; --iCaptureDevice) {
26850  pContext->pDeviceInfos[iCaptureDevice] = pContext->pDeviceInfos[iCaptureDevice-1];
26851  }
26852 
26853  /* Now just insert where the first capture device was before moving it down a slot. */
26854  pContext->pDeviceInfos[iFirstCaptureDevice] = *pInfo;
26855  pContext->playbackDeviceInfoCount += 1;
26856  } else {
26857  /* Capture. Insert at the end. */
26858  pContext->pDeviceInfos[totalDeviceInfoCount] = *pInfo;
26859  pContext->captureDeviceInfoCount += 1;
26860  }
26861 
26862  (void)pUserData;
26863  return MA_TRUE;
26864 }
26865 
26866 MA_API ma_result ma_context_get_devices(ma_context* pContext, ma_device_info** ppPlaybackDeviceInfos, ma_uint32* pPlaybackDeviceCount, ma_device_info** ppCaptureDeviceInfos, ma_uint32* pCaptureDeviceCount)
26867 {
26868  ma_result result;
26869 
26870  /* Safety. */
26871  if (ppPlaybackDeviceInfos != NULL) *ppPlaybackDeviceInfos = NULL;
26872  if (pPlaybackDeviceCount != NULL) *pPlaybackDeviceCount = 0;
26873  if (ppCaptureDeviceInfos != NULL) *ppCaptureDeviceInfos = NULL;
26874  if (pCaptureDeviceCount != NULL) *pCaptureDeviceCount = 0;
26875 
26876  if (pContext == NULL) {
26877  return MA_INVALID_ARGS;
26878  }
26879 
26880  if (pContext->callbacks.onContextEnumerateDevices == NULL) {
26881  return MA_INVALID_OPERATION;
26882  }
26883 
26884  /* Note that we don't use ma_context_enumerate_devices() here because we want to do locking at a higher level. */
26885  ma_mutex_lock(&pContext->deviceEnumLock);
26886  {
26887  /* Reset everything first. */
26888  pContext->playbackDeviceInfoCount = 0;
26889  pContext->captureDeviceInfoCount = 0;
26890 
26891  /* Now enumerate over available devices. */
26893  if (result == MA_SUCCESS) {
26894  /* Playback devices. */
26895  if (ppPlaybackDeviceInfos != NULL) {
26896  *ppPlaybackDeviceInfos = pContext->pDeviceInfos;
26897  }
26898  if (pPlaybackDeviceCount != NULL) {
26899  *pPlaybackDeviceCount = pContext->playbackDeviceInfoCount;
26900  }
26901 
26902  /* Capture devices. */
26903  if (ppCaptureDeviceInfos != NULL) {
26904  *ppCaptureDeviceInfos = pContext->pDeviceInfos + pContext->playbackDeviceInfoCount; /* Capture devices come after playback devices. */
26905  }
26906  if (pCaptureDeviceCount != NULL) {
26907  *pCaptureDeviceCount = pContext->captureDeviceInfoCount;
26908  }
26909  }
26910  }
26911  ma_mutex_unlock(&pContext->deviceEnumLock);
26912 
26913  return result;
26914 }
26915 
26916 MA_API ma_result ma_context_get_device_info(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_share_mode shareMode, ma_device_info* pDeviceInfo)
26917 {
26918  ma_result result;
26919  ma_device_info deviceInfo;
26920 
26921  (void)shareMode; /* Unused. This parameter will be removed in version 0.11. */
26922 
26923  /* NOTE: Do not clear pDeviceInfo on entry. The reason is the pDeviceID may actually point to pDeviceInfo->id which will break things. */
26924  if (pContext == NULL || pDeviceInfo == NULL) {
26925  return MA_INVALID_ARGS;
26926  }
26927 
26928  MA_ZERO_OBJECT(&deviceInfo);
26929 
26930  /* Help the backend out by copying over the device ID if we have one. */
26931  if (pDeviceID != NULL) {
26932  MA_COPY_MEMORY(&deviceInfo.id, pDeviceID, sizeof(*pDeviceID));
26933  }
26934 
26935  if (pContext->callbacks.onContextGetDeviceInfo == NULL) {
26936  return MA_INVALID_OPERATION;
26937  }
26938 
26939  ma_mutex_lock(&pContext->deviceInfoLock);
26940  {
26941  result = pContext->callbacks.onContextGetDeviceInfo(pContext, deviceType, pDeviceID, &deviceInfo);
26942  }
26943  ma_mutex_unlock(&pContext->deviceInfoLock);
26944 
26945  /*
26946  If the backend is using the new device info system, do a pass to fill out the old settings for backwards compatibility. This will be removed in
26947  the future when all backends have implemented the new device info system.
26948  */
26949  if (deviceInfo.nativeDataFormatCount > 0) {
26950  ma_uint32 iNativeFormat;
26951  ma_uint32 iSampleFormat;
26952 
26953  deviceInfo.minChannels = 0xFFFFFFFF;
26954  deviceInfo.maxChannels = 0;
26955  deviceInfo.minSampleRate = 0xFFFFFFFF;
26956  deviceInfo.maxSampleRate = 0;
26957 
26958  for (iNativeFormat = 0; iNativeFormat < deviceInfo.nativeDataFormatCount; iNativeFormat += 1) {
26959  /* Formats. */
26960  if (deviceInfo.nativeDataFormats[iNativeFormat].format == ma_format_unknown) {
26961  /* All formats are supported. */
26962  deviceInfo.formats[0] = ma_format_u8;
26963  deviceInfo.formats[1] = ma_format_s16;
26964  deviceInfo.formats[2] = ma_format_s24;
26965  deviceInfo.formats[3] = ma_format_s32;
26966  deviceInfo.formats[4] = ma_format_f32;
26967  deviceInfo.formatCount = 5;
26968  } else {
26969  /* Make sure the format isn't already in the list. If so, skip. */
26970  ma_bool32 alreadyExists = MA_FALSE;
26971  for (iSampleFormat = 0; iSampleFormat < deviceInfo.formatCount; iSampleFormat += 1) {
26972  if (deviceInfo.formats[iSampleFormat] == deviceInfo.nativeDataFormats[iNativeFormat].format) {
26973  alreadyExists = MA_TRUE;
26974  break;
26975  }
26976  }
26977 
26978  if (!alreadyExists) {
26979  deviceInfo.formats[deviceInfo.formatCount++] = deviceInfo.nativeDataFormats[iNativeFormat].format;
26980  }
26981  }
26982 
26983  /* Channels. */
26984  if (deviceInfo.nativeDataFormats[iNativeFormat].channels == 0) {
26985  /* All channels supported. */
26986  deviceInfo.minChannels = MA_MIN_CHANNELS;
26987  deviceInfo.maxChannels = MA_MAX_CHANNELS;
26988  } else {
26989  if (deviceInfo.minChannels > deviceInfo.nativeDataFormats[iNativeFormat].channels) {
26990  deviceInfo.minChannels = deviceInfo.nativeDataFormats[iNativeFormat].channels;
26991  }
26992  if (deviceInfo.maxChannels < deviceInfo.nativeDataFormats[iNativeFormat].channels) {
26993  deviceInfo.maxChannels = deviceInfo.nativeDataFormats[iNativeFormat].channels;
26994  }
26995  }
26996 
26997  /* Sample rate. */
26998  if (deviceInfo.nativeDataFormats[iNativeFormat].sampleRate == 0) {
26999  /* All sample rates supported. */
27002  } else {
27003  if (deviceInfo.minSampleRate > deviceInfo.nativeDataFormats[iNativeFormat].sampleRate) {
27004  deviceInfo.minSampleRate = deviceInfo.nativeDataFormats[iNativeFormat].sampleRate;
27005  }
27006  if (deviceInfo.maxSampleRate < deviceInfo.nativeDataFormats[iNativeFormat].sampleRate) {
27007  deviceInfo.maxSampleRate = deviceInfo.nativeDataFormats[iNativeFormat].sampleRate;
27008  }
27009  }
27010  }
27011  }
27012 
27013 
27014  /* Clamp ranges. */
27015  deviceInfo.minChannels = ma_max(deviceInfo.minChannels, MA_MIN_CHANNELS);
27016  deviceInfo.maxChannels = ma_min(deviceInfo.maxChannels, MA_MAX_CHANNELS);
27019 
27020  *pDeviceInfo = deviceInfo;
27021  return result;
27022 }
27023 
27025 {
27026  if (pContext == NULL) {
27027  return MA_FALSE;
27028  }
27029 
27030  return ma_is_loopback_supported(pContext->backend);
27031 }
27032 
27033 
27035 {
27038  config.deviceType = deviceType;
27039 
27040  /* Resampling defaults. We must never use the Speex backend by default because it uses licensed third party code. */
27041  config.resampling.algorithm = ma_resample_algorithm_linear;
27042  config.resampling.linear.lpfOrder = ma_min(MA_DEFAULT_RESAMPLER_LPF_ORDER, MA_MAX_FILTER_ORDER);
27043  config.resampling.speex.quality = 3;
27044 
27045  return config;
27046 }
27047 
27049 {
27050  ma_result result;
27051  ma_device_descriptor descriptorPlayback;
27052  ma_device_descriptor descriptorCapture;
27053 
27054  /* The context can be null, in which case we self-manage it. */
27055  if (pContext == NULL) {
27056  return ma_device_init_ex(NULL, 0, NULL, pConfig, pDevice);
27057  }
27058 
27059  if (pDevice == NULL) {
27060  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid arguments (pDevice == NULL).", MA_INVALID_ARGS);
27061  }
27062 
27063  MA_ZERO_OBJECT(pDevice);
27064 
27065  if (pConfig == NULL) {
27066  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid arguments (pConfig == NULL).", MA_INVALID_ARGS);
27067  }
27068 
27069 
27070  /* Check that we have our callbacks defined. */
27071  if (pContext->callbacks.onDeviceInit == NULL) {
27072  return MA_INVALID_OPERATION;
27073  }
27074 
27075 
27076  /* Basic config validation. */
27078  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Device type is invalid. Make sure the device type has been set in the config.", MA_INVALID_DEVICE_CONFIG);
27079  }
27080 
27081  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
27082  if (pConfig->capture.channels > MA_MAX_CHANNELS) {
27083  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Capture channel count cannot exceed 32.", MA_INVALID_DEVICE_CONFIG);
27084  }
27085  if (!ma__is_channel_map_valid(pConfig->capture.channelMap, pConfig->capture.channels)) {
27086  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid config. Capture channel map is invalid.", MA_INVALID_DEVICE_CONFIG);
27087  }
27088  }
27089 
27091  if (pConfig->playback.channels > MA_MAX_CHANNELS) {
27092  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Playback channel count cannot exceed 32.", MA_INVALID_DEVICE_CONFIG);
27093  }
27094  if (!ma__is_channel_map_valid(pConfig->playback.channelMap, pConfig->playback.channels)) {
27095  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid config. Playback channel map is invalid.", MA_INVALID_DEVICE_CONFIG);
27096  }
27097  }
27098 
27099  pDevice->pContext = pContext;
27100 
27101  /* Set the user data and log callback ASAP to ensure it is available for the entire initialization process. */
27102  pDevice->pUserData = pConfig->pUserData;
27103  pDevice->onData = pConfig->dataCallback;
27104  pDevice->onStop = pConfig->stopCallback;
27105 
27106  if (((ma_uintptr)pDevice % sizeof(pDevice)) != 0) {
27107  if (pContext->logCallback) {
27108  pContext->logCallback(pContext, pDevice, MA_LOG_LEVEL_WARNING, "WARNING: ma_device_init() called for a device that is not properly aligned. Thread safety is not supported.");
27109  }
27110  }
27111 
27112  if (pConfig->playback.pDeviceID != NULL) {
27113  MA_COPY_MEMORY(&pDevice->playback.id, pConfig->playback.pDeviceID, sizeof(pDevice->playback.id));
27114  }
27115 
27116  if (pConfig->capture.pDeviceID != NULL) {
27117  MA_COPY_MEMORY(&pDevice->capture.id, pConfig->capture.pDeviceID, sizeof(pDevice->capture.id));
27118  }
27119 
27121  pDevice->noClip = pConfig->noClip;
27122  pDevice->masterVolumeFactor = 1;
27123 
27124  pDevice->type = pConfig->deviceType;
27125  pDevice->sampleRate = pConfig->sampleRate;
27126  pDevice->resampling.algorithm = pConfig->resampling.algorithm;
27127  pDevice->resampling.linear.lpfOrder = pConfig->resampling.linear.lpfOrder;
27128  pDevice->resampling.speex.quality = pConfig->resampling.speex.quality;
27129 
27130  pDevice->capture.shareMode = pConfig->capture.shareMode;
27131  pDevice->capture.format = pConfig->capture.format;
27132  pDevice->capture.channels = pConfig->capture.channels;
27134  pDevice->capture.channelMixMode = pConfig->capture.channelMixMode;
27135 
27136  pDevice->playback.shareMode = pConfig->playback.shareMode;
27137  pDevice->playback.format = pConfig->playback.format;
27138  pDevice->playback.channels = pConfig->playback.channels;
27140  pDevice->playback.channelMixMode = pConfig->playback.channelMixMode;
27141 
27142 
27143  result = ma_mutex_init(&pDevice->startStopLock);
27144  if (result != MA_SUCCESS) {
27145  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create mutex.", result);
27146  }
27147 
27148  /*
27149  When the device is started, the worker thread is the one that does the actual startup of the backend device. We
27150  use a semaphore to wait for the background thread to finish the work. The same applies for stopping the device.
27151 
27152  Each of these semaphores is released internally by the worker thread when the work is completed. The start
27153  semaphore is also used to wake up the worker thread.
27154  */
27155  result = ma_event_init(&pDevice->wakeupEvent);
27156  if (result != MA_SUCCESS) {
27157  ma_mutex_uninit(&pDevice->startStopLock);
27158  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread wakeup event.", result);
27159  }
27160 
27161  result = ma_event_init(&pDevice->startEvent);
27162  if (result != MA_SUCCESS) {
27163  ma_event_uninit(&pDevice->wakeupEvent);
27164  ma_mutex_uninit(&pDevice->startStopLock);
27165  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread start event.", result);
27166  }
27167 
27168  result = ma_event_init(&pDevice->stopEvent);
27169  if (result != MA_SUCCESS) {
27170  ma_event_uninit(&pDevice->startEvent);
27171  ma_event_uninit(&pDevice->wakeupEvent);
27172  ma_mutex_uninit(&pDevice->startStopLock);
27173  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread stop event.", result);
27174  }
27175 
27176 
27177  MA_ZERO_OBJECT(&descriptorPlayback);
27178  descriptorPlayback.pDeviceID = pConfig->playback.pDeviceID;
27179  descriptorPlayback.shareMode = pConfig->playback.shareMode;
27180  descriptorPlayback.format = pConfig->playback.format;
27181  descriptorPlayback.channels = pConfig->playback.channels;
27182  descriptorPlayback.sampleRate = pConfig->sampleRate;
27183  ma_channel_map_copy(descriptorPlayback.channelMap, pConfig->playback.channelMap, pConfig->playback.channels);
27184  descriptorPlayback.periodSizeInFrames = pConfig->periodSizeInFrames;
27185  descriptorPlayback.periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
27186  descriptorPlayback.periodCount = pConfig->periods;
27187 
27188  if (descriptorPlayback.periodCount == 0) {
27189  descriptorPlayback.periodCount = MA_DEFAULT_PERIODS;
27190  }
27191 
27192 
27193  MA_ZERO_OBJECT(&descriptorCapture);
27194  descriptorCapture.pDeviceID = pConfig->capture.pDeviceID;
27195  descriptorCapture.shareMode = pConfig->capture.shareMode;
27196  descriptorCapture.format = pConfig->capture.format;
27197  descriptorCapture.channels = pConfig->capture.channels;
27198  descriptorCapture.sampleRate = pConfig->sampleRate;
27199  ma_channel_map_copy(descriptorCapture.channelMap, pConfig->capture.channelMap, pConfig->capture.channels);
27200  descriptorCapture.periodSizeInFrames = pConfig->periodSizeInFrames;
27201  descriptorCapture.periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
27202  descriptorCapture.periodCount = pConfig->periods;
27203 
27204  if (descriptorCapture.periodCount == 0) {
27205  descriptorCapture.periodCount = MA_DEFAULT_PERIODS;
27206  }
27207 
27208 
27209  result = pContext->callbacks.onDeviceInit(pDevice, pConfig, &descriptorPlayback, &descriptorCapture);
27210  if (result != MA_SUCCESS) {
27211  ma_event_uninit(&pDevice->startEvent);
27212  ma_event_uninit(&pDevice->wakeupEvent);
27213  ma_mutex_uninit(&pDevice->startStopLock);
27214  return result;
27215  }
27216 
27217 
27218  /*
27219  On output the descriptors will contain the *actual* data format of the device. We need this to know how to convert the data between
27220  the requested format and the internal format.
27221  */
27223  if (!ma_device_descriptor_is_valid(&descriptorCapture)) {
27224  ma_device_uninit(pDevice);
27225  return MA_INVALID_ARGS;
27226  }
27227 
27228  pDevice->capture.internalFormat = descriptorCapture.format;
27229  pDevice->capture.internalChannels = descriptorCapture.channels;
27230  pDevice->capture.internalSampleRate = descriptorCapture.sampleRate;
27231  ma_channel_map_copy(pDevice->capture.internalChannelMap, descriptorCapture.channelMap, descriptorCapture.channels);
27232  pDevice->capture.internalPeriodSizeInFrames = descriptorCapture.periodSizeInFrames;
27233  pDevice->capture.internalPeriods = descriptorCapture.periodCount;
27234 
27235  if (pDevice->capture.internalPeriodSizeInFrames == 0) {
27237  }
27238  }
27239 
27240  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
27241  if (!ma_device_descriptor_is_valid(&descriptorPlayback)) {
27242  ma_device_uninit(pDevice);
27243  return MA_INVALID_ARGS;
27244  }
27245 
27246  pDevice->playback.internalFormat = descriptorPlayback.format;
27247  pDevice->playback.internalChannels = descriptorPlayback.channels;
27248  pDevice->playback.internalSampleRate = descriptorPlayback.sampleRate;
27249  ma_channel_map_copy(pDevice->playback.internalChannelMap, descriptorPlayback.channelMap, descriptorPlayback.channels);
27250  pDevice->playback.internalPeriodSizeInFrames = descriptorPlayback.periodSizeInFrames;
27251  pDevice->playback.internalPeriods = descriptorPlayback.periodCount;
27252 
27253  if (pDevice->playback.internalPeriodSizeInFrames == 0) {
27255  }
27256  }
27257 
27258 
27259  /*
27260  The name of the device can be retrieved from device info. This may be temporary and replaced with a `ma_device_get_info(pDevice, deviceType)` instead.
27261  For loopback devices, we need to retrieve the name of the playback device.
27262  */
27263  {
27264  ma_device_info deviceInfo;
27265 
27267  result = ma_context_get_device_info(pContext, (pConfig->deviceType == ma_device_type_loopback) ? ma_device_type_playback : ma_device_type_capture, descriptorCapture.pDeviceID, descriptorCapture.shareMode, &deviceInfo);
27268  if (result == MA_SUCCESS) {
27269  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), deviceInfo.name, (size_t)-1);
27270  } else {
27271  /* We failed to retrieve the device info. Fall back to a default name. */
27272  if (descriptorCapture.pDeviceID == NULL) {
27273  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
27274  } else {
27275  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), "Capture Device", (size_t)-1);
27276  }
27277  }
27278  }
27279 
27280  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
27281  result = ma_context_get_device_info(pContext, ma_device_type_playback, descriptorPlayback.pDeviceID, descriptorPlayback.shareMode, &deviceInfo);
27282  if (result == MA_SUCCESS) {
27283  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), deviceInfo.name, (size_t)-1);
27284  } else {
27285  /* We failed to retrieve the device info. Fall back to a default name. */
27286  if (descriptorPlayback.pDeviceID == NULL) {
27287  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
27288  } else {
27289  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), "Playback Device", (size_t)-1);
27290  }
27291  }
27292  }
27293  }
27294 
27295 
27296  ma_device__post_init_setup(pDevice, pConfig->deviceType);
27297 
27298 
27299  /* Some backends don't require the worker thread. */
27300  if (!ma_context_is_backend_asynchronous(pContext)) {
27301  /* The worker thread. */
27302  result = ma_thread_create(&pDevice->thread, pContext->threadPriority, pContext->threadStackSize, ma_worker_thread, pDevice, &pContext->allocationCallbacks);
27303  if (result != MA_SUCCESS) {
27304  ma_device_uninit(pDevice);
27305  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread.", result);
27306  }
27307 
27308  /* Wait for the worker thread to put the device into it's stopped state for real. */
27309  ma_event_wait(&pDevice->stopEvent);
27311  } else {
27312  /*
27313  If the backend is asynchronous and the device is duplex, we'll need an intermediary ring buffer. Note that this needs to be done
27314  after ma_device__post_init_setup().
27315  */
27316  if (ma_context_is_backend_asynchronous(pContext)) {
27317  if (pConfig->deviceType == ma_device_type_duplex) {
27318  result = ma_duplex_rb_init(pDevice->capture.format, pDevice->capture.channels, pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalPeriodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->duplexRB);
27319  if (result != MA_SUCCESS) {
27320  ma_device_uninit(pDevice);
27321  return result;
27322  }
27323  }
27324  }
27325 
27327  }
27328 
27329 
27331  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
27332  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", pDevice->capture.name, "Capture");
27334  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channels: %d -> %d\n", pDevice->capture.internalChannels, pDevice->capture.channels);
27335  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Sample Rate: %d -> %d\n", pDevice->capture.internalSampleRate, pDevice->sampleRate);
27337  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Conversion:\n");
27338  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Pre Format Conversion: %s\n", pDevice->capture.converter.hasPreFormatConversion ? "YES" : "NO");
27339  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Post Format Conversion: %s\n", pDevice->capture.converter.hasPostFormatConversion ? "YES" : "NO");
27340  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Routing: %s\n", pDevice->capture.converter.hasChannelConverter ? "YES" : "NO");
27341  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s\n", pDevice->capture.converter.hasResampler ? "YES" : "NO");
27342  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s\n", pDevice->capture.converter.isPassthrough ? "YES" : "NO");
27343  }
27344  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
27345  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", pDevice->playback.name, "Playback");
27347  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channels: %d -> %d\n", pDevice->playback.channels, pDevice->playback.internalChannels);
27348  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->playback.internalSampleRate);
27350  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Conversion:\n");
27351  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Pre Format Conversion: %s\n", pDevice->playback.converter.hasPreFormatConversion ? "YES" : "NO");
27352  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Post Format Conversion: %s\n", pDevice->playback.converter.hasPostFormatConversion ? "YES" : "NO");
27353  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Routing: %s\n", pDevice->playback.converter.hasChannelConverter ? "YES" : "NO");
27354  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s\n", pDevice->playback.converter.hasResampler ? "YES" : "NO");
27355  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s\n", pDevice->playback.converter.isPassthrough ? "YES" : "NO");
27356  }
27357 
27359  return MA_SUCCESS;
27360 }
27361 
27362 MA_API ma_result ma_device_init_ex(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config* pContextConfig, const ma_device_config* pConfig, ma_device* pDevice)
27363 {
27364  ma_result result;
27365  ma_context* pContext;
27366  ma_backend defaultBackends[ma_backend_null+1];
27367  ma_uint32 iBackend;
27368  ma_backend* pBackendsToIterate;
27369  ma_uint32 backendsToIterateCount;
27370  ma_allocation_callbacks allocationCallbacks;
27371 
27372  if (pConfig == NULL) {
27373  return MA_INVALID_ARGS;
27374  }
27375 
27376  if (pContextConfig != NULL) {
27377  result = ma_allocation_callbacks_init_copy(&allocationCallbacks, &pContextConfig->allocationCallbacks);
27378  if (result != MA_SUCCESS) {
27379  return result;
27380  }
27381  } else {
27382  allocationCallbacks = ma_allocation_callbacks_init_default();
27383  }
27384 
27385 
27386  pContext = (ma_context*)ma__malloc_from_callbacks(sizeof(*pContext), &allocationCallbacks);
27387  if (pContext == NULL) {
27388  return MA_OUT_OF_MEMORY;
27389  }
27390 
27391  for (iBackend = 0; iBackend <= ma_backend_null; ++iBackend) {
27392  defaultBackends[iBackend] = (ma_backend)iBackend;
27393  }
27394 
27395  pBackendsToIterate = (ma_backend*)backends;
27396  backendsToIterateCount = backendCount;
27397  if (pBackendsToIterate == NULL) {
27398  pBackendsToIterate = (ma_backend*)defaultBackends;
27399  backendsToIterateCount = ma_countof(defaultBackends);
27400  }
27401 
27402  result = MA_NO_BACKEND;
27403 
27404  for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
27405  result = ma_context_init(&pBackendsToIterate[iBackend], 1, pContextConfig, pContext);
27406  if (result == MA_SUCCESS) {
27407  result = ma_device_init(pContext, pConfig, pDevice);
27408  if (result == MA_SUCCESS) {
27409  break; /* Success. */
27410  } else {
27411  ma_context_uninit(pContext); /* Failure. */
27412  }
27413  }
27414  }
27415 
27416  if (result != MA_SUCCESS) {
27417  ma__free_from_callbacks(pContext, &allocationCallbacks);
27418  return result;
27419  }
27420 
27421  pDevice->isOwnerOfContext = MA_TRUE;
27422  return result;
27423 }
27424 
27426 {
27427  if (!ma_device__is_initialized(pDevice)) {
27428  return;
27429  }
27430 
27431  /* Make sure the device is stopped first. The backends will probably handle this naturally, but I like to do it explicitly for my own sanity. */
27432  if (ma_device_is_started(pDevice)) {
27433  ma_device_stop(pDevice);
27434  }
27435 
27436  /* Putting the device into an uninitialized state will make the worker thread return. */
27438 
27439  /* Wake up the worker thread and wait for it to properly terminate. */
27441  ma_event_signal(&pDevice->wakeupEvent);
27442  ma_thread_wait(&pDevice->thread);
27443  }
27444 
27445  if (pDevice->pContext->callbacks.onDeviceUninit != NULL) {
27446  pDevice->pContext->callbacks.onDeviceUninit(pDevice);
27447  }
27448 
27449 
27450  ma_event_uninit(&pDevice->stopEvent);
27451  ma_event_uninit(&pDevice->startEvent);
27452  ma_event_uninit(&pDevice->wakeupEvent);
27453  ma_mutex_uninit(&pDevice->startStopLock);
27454 
27456  if (pDevice->type == ma_device_type_duplex) {
27457  ma_duplex_rb_uninit(&pDevice->duplexRB);
27458  }
27459  }
27460 
27461  if (pDevice->isOwnerOfContext) {
27462  ma_allocation_callbacks allocationCallbacks = pDevice->pContext->allocationCallbacks;
27463 
27464  ma_context_uninit(pDevice->pContext);
27465  ma__free_from_callbacks(pDevice->pContext, &allocationCallbacks);
27466  }
27467 
27468  MA_ZERO_OBJECT(pDevice);
27469 }
27470 
27472 {
27473  if (pDevice == NULL) {
27474  return NULL;
27475  }
27476 
27477  return pDevice->pContext;
27478 }
27479 
27481 {
27482  return ma_context_get_log(ma_device_get_context(pDevice));
27483 }
27484 
27486 {
27487  ma_result result;
27488 
27489  if (pDevice == NULL) {
27490  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_start() called with invalid arguments (pDevice == NULL).", MA_INVALID_ARGS);
27491  }
27492 
27493  if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
27494  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_start() called for an uninitialized device.", MA_DEVICE_NOT_INITIALIZED);
27495  }
27496 
27497  if (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
27498  return ma_post_error(pDevice, MA_LOG_LEVEL_WARNING, "ma_device_start() called when the device is already started.", MA_INVALID_OPERATION); /* Already started. Returning an error to let the application know because it probably means they're doing something wrong. */
27499  }
27500 
27501  ma_mutex_lock(&pDevice->startStopLock);
27502  {
27503  /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
27505 
27507 
27508  /* Asynchronous backends need to be handled differently. */
27510  if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
27511  result = pDevice->pContext->callbacks.onDeviceStart(pDevice);
27512  } else {
27513  result = MA_INVALID_OPERATION;
27514  }
27515 
27516  if (result == MA_SUCCESS) {
27518  }
27519  } else {
27520  /*
27521  Synchronous backends are started by signaling an event that's being waited on in the worker thread. We first wake up the
27522  thread and then wait for the start event.
27523  */
27524  ma_event_signal(&pDevice->wakeupEvent);
27525 
27526  /*
27527  Wait for the worker thread to finish starting the device. Note that the worker thread will be the one who puts the device
27528  into the started state. Don't call ma_device__set_state() here.
27529  */
27530  ma_event_wait(&pDevice->startEvent);
27531  result = pDevice->workResult;
27532  }
27533 
27534  /* We changed the state from stopped to started, so if we failed, make sure we put the state back to stopped. */
27535  if (result != MA_SUCCESS) {
27537  }
27538  }
27539  ma_mutex_unlock(&pDevice->startStopLock);
27540 
27541  return result;
27542 }
27543 
27545 {
27546  ma_result result;
27547 
27548  if (pDevice == NULL) {
27549  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_stop() called with invalid arguments (pDevice == NULL).", MA_INVALID_ARGS);
27550  }
27551 
27552  if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
27553  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_stop() called for an uninitialized device.", MA_DEVICE_NOT_INITIALIZED);
27554  }
27555 
27556  if (ma_device_get_state(pDevice) == MA_STATE_STOPPED) {
27557  return ma_post_error(pDevice, MA_LOG_LEVEL_WARNING, "ma_device_stop() called when the device is already stopped.", MA_INVALID_OPERATION); /* Already stopped. Returning an error to let the application know because it probably means they're doing something wrong. */
27558  }
27559 
27560  ma_mutex_lock(&pDevice->startStopLock);
27561  {
27562  /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */
27564 
27566 
27567  /* Asynchronous backends need to be handled differently. */
27569  /* Asynchronous backends must have a stop operation. */
27570  if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
27571  result = pDevice->pContext->callbacks.onDeviceStop(pDevice);
27572  } else {
27573  result = MA_INVALID_OPERATION;
27574  }
27575 
27577  } else {
27578  /*
27579  Synchronous backends. The stop callback is always called from the worker thread. Do not call the stop callback here. If
27580  the backend is implementing it's own audio thread loop we'll need to wake it up if required. Note that we need to make
27581  sure the state of the device is *not* playing right now, which it shouldn't be since we set it above. This is super
27582  important though, so I'm asserting it here as well for extra safety in case we accidentally change something later.
27583  */
27585 
27586  if (pDevice->pContext->callbacks.onDeviceDataLoopWakeup != NULL) {
27587  pDevice->pContext->callbacks.onDeviceDataLoopWakeup(pDevice);
27588  }
27589 
27590  /*
27591  We need to wait for the worker thread to become available for work before returning. Note that the worker thread will be
27592  the one who puts the device into the stopped state. Don't call ma_device__set_state() here.
27593  */
27594  ma_event_wait(&pDevice->stopEvent);
27595  result = MA_SUCCESS;
27596  }
27597  }
27598  ma_mutex_unlock(&pDevice->startStopLock);
27599 
27600  return result;
27601 }
27602 
27604 {
27605  return ma_device_get_state(pDevice) == MA_STATE_STARTED;
27606 }
27607 
27609 {
27610  if (pDevice == NULL) {
27611  return MA_STATE_UNINITIALIZED;
27612  }
27613 
27614  return c89atomic_load_32((ma_uint32*)&pDevice->state); /* Naughty cast to get rid of a const warning. */
27615 }
27616 
27618 {
27619  if (pDevice == NULL) {
27620  return MA_INVALID_ARGS;
27621  }
27622 
27623  if (volume < 0.0f || volume > 1.0f) {
27624  return MA_INVALID_ARGS;
27625  }
27626 
27627  c89atomic_exchange_f32(&pDevice->masterVolumeFactor, volume);
27628 
27629  return MA_SUCCESS;
27630 }
27631 
27633 {
27634  if (pVolume == NULL) {
27635  return MA_INVALID_ARGS;
27636  }
27637 
27638  if (pDevice == NULL) {
27639  *pVolume = 0;
27640  return MA_INVALID_ARGS;
27641  }
27642 
27643  *pVolume = c89atomic_load_f32(&pDevice->masterVolumeFactor);
27644 
27645  return MA_SUCCESS;
27646 }
27647 
27649 {
27650  if (gainDB > 0) {
27651  return MA_INVALID_ARGS;
27652  }
27653 
27654  return ma_device_set_master_volume(pDevice, ma_gain_db_to_factor(gainDB));
27655 }
27656 
27658 {
27659  float factor;
27660  ma_result result;
27661 
27662  if (pGainDB == NULL) {
27663  return MA_INVALID_ARGS;
27664  }
27665 
27666  result = ma_device_get_master_volume(pDevice, &factor);
27667  if (result != MA_SUCCESS) {
27668  *pGainDB = 0;
27669  return result;
27670  }
27671 
27672  *pGainDB = ma_factor_to_gain_db(factor);
27673 
27674  return MA_SUCCESS;
27675 }
27676 
27677 
27678 MA_API ma_result ma_device_handle_backend_data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
27679 {
27680  if (pDevice == NULL) {
27681  return MA_INVALID_ARGS;
27682  }
27683 
27684  if (pOutput == NULL && pInput == NULL) {
27685  return MA_INVALID_ARGS;
27686  }
27687 
27688  if (pDevice->type == ma_device_type_duplex) {
27689  if (pInput != NULL) {
27690  ma_device__handle_duplex_callback_capture(pDevice, frameCount, pInput, &pDevice->duplexRB.rb);
27691  }
27692 
27693  if (pOutput != NULL) {
27694  ma_device__handle_duplex_callback_playback(pDevice, frameCount, pOutput, &pDevice->duplexRB.rb);
27695  }
27696  } else {
27697  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_loopback) {
27698  if (pInput == NULL) {
27699  return MA_INVALID_ARGS;
27700  }
27701 
27702  ma_device__send_frames_to_client(pDevice, frameCount, pInput);
27703  }
27704 
27705  if (pDevice->type == ma_device_type_playback) {
27706  if (pOutput == NULL) {
27707  return MA_INVALID_ARGS;
27708  }
27709 
27710  ma_device__read_frames_from_client(pDevice, frameCount, pOutput);
27711  }
27712  }
27713 
27714  return MA_SUCCESS;
27715 }
27716 
27718 {
27719  if (pDescriptor == NULL) {
27720  return 0;
27721  }
27722 
27723  /*
27724  We must have a non-0 native sample rate, but some backends don't allow retrieval of this at the
27725  time when the size of the buffer needs to be determined. In this case we need to just take a best
27726  guess and move on. We'll try using the sample rate in pDescriptor first. If that's not set we'll
27727  just fall back to MA_DEFAULT_SAMPLE_RATE.
27728  */
27729  if (nativeSampleRate == 0) {
27730  nativeSampleRate = pDescriptor->sampleRate;
27731  }
27732  if (nativeSampleRate == 0) {
27733  nativeSampleRate = MA_DEFAULT_SAMPLE_RATE;
27734  }
27735 
27736  MA_ASSERT(nativeSampleRate != 0);
27737 
27738  if (pDescriptor->periodSizeInFrames == 0) {
27739  if (pDescriptor->periodSizeInMilliseconds == 0) {
27740  if (performanceProfile == ma_performance_profile_low_latency) {
27742  } else {
27744  }
27745  } else {
27747  }
27748  } else {
27749  return pDescriptor->periodSizeInFrames;
27750  }
27751 }
27752 #endif /* MA_NO_DEVICE_IO */
27753 
27754 
27755 MA_API ma_uint32 ma_scale_buffer_size(ma_uint32 baseBufferSize, float scale)
27756 {
27757  return ma_max(1, (ma_uint32)(baseBufferSize*scale));
27758 }
27759 
27761 {
27762  /* Prevent a division by zero. */
27763  if (sampleRate == 0) {
27764  return 0;
27765  }
27766 
27767  return bufferSizeInFrames*1000 / sampleRate;
27768 }
27769 
27771 {
27772  /* Prevent a division by zero. */
27773  if (sampleRate == 0) {
27774  return 0;
27775  }
27776 
27777  return bufferSizeInMilliseconds*sampleRate / 1000;
27778 }
27779 
27780 MA_API void ma_copy_pcm_frames(void* dst, const void* src, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
27781 {
27782  if (dst == src) {
27783  return; /* No-op. */
27784  }
27785 
27786  ma_copy_memory_64(dst, src, frameCount * ma_get_bytes_per_frame(format, channels));
27787 }
27788 
27789 MA_API void ma_silence_pcm_frames(void* p, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
27790 {
27791  if (format == ma_format_u8) {
27792  ma_uint64 sampleCount = frameCount * channels;
27793  ma_uint64 iSample;
27794  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27795  ((ma_uint8*)p)[iSample] = 128;
27796  }
27797  } else {
27798  ma_zero_memory_64(p, frameCount * ma_get_bytes_per_frame(format, channels));
27799  }
27800 }
27801 
27802 MA_API void* ma_offset_pcm_frames_ptr(void* p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels)
27803 {
27804  return ma_offset_ptr(p, offsetInFrames * ma_get_bytes_per_frame(format, channels));
27805 }
27806 
27807 MA_API const void* ma_offset_pcm_frames_const_ptr(const void* p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels)
27808 {
27809  return ma_offset_ptr(p, offsetInFrames * ma_get_bytes_per_frame(format, channels));
27810 }
27811 
27812 
27813 MA_API void ma_clip_samples_f32(float* p, ma_uint64 sampleCount)
27814 {
27815  ma_uint32 iSample;
27816 
27817  /* TODO: Research a branchless SSE implementation. */
27818  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27819  p[iSample] = ma_clip_f32(p[iSample]);
27820  }
27821 }
27822 
27823 
27824 MA_API void ma_copy_and_apply_volume_factor_u8(ma_uint8* pSamplesOut, const ma_uint8* pSamplesIn, ma_uint64 sampleCount, float factor)
27825 {
27826  ma_uint64 iSample;
27827 
27828  if (pSamplesOut == NULL || pSamplesIn == NULL) {
27829  return;
27830  }
27831 
27832  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27833  pSamplesOut[iSample] = (ma_uint8)(pSamplesIn[iSample] * factor);
27834  }
27835 }
27836 
27837 MA_API void ma_copy_and_apply_volume_factor_s16(ma_int16* pSamplesOut, const ma_int16* pSamplesIn, ma_uint64 sampleCount, float factor)
27838 {
27839  ma_uint64 iSample;
27840 
27841  if (pSamplesOut == NULL || pSamplesIn == NULL) {
27842  return;
27843  }
27844 
27845  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27846  pSamplesOut[iSample] = (ma_int16)(pSamplesIn[iSample] * factor);
27847  }
27848 }
27849 
27850 MA_API void ma_copy_and_apply_volume_factor_s24(void* pSamplesOut, const void* pSamplesIn, ma_uint64 sampleCount, float factor)
27851 {
27852  ma_uint64 iSample;
27853  ma_uint8* pSamplesOut8;
27854  ma_uint8* pSamplesIn8;
27855 
27856  if (pSamplesOut == NULL || pSamplesIn == NULL) {
27857  return;
27858  }
27859 
27860  pSamplesOut8 = (ma_uint8*)pSamplesOut;
27861  pSamplesIn8 = (ma_uint8*)pSamplesIn;
27862 
27863  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27864  ma_int32 sampleS32;
27865 
27866  sampleS32 = (ma_int32)(((ma_uint32)(pSamplesIn8[iSample*3+0]) << 8) | ((ma_uint32)(pSamplesIn8[iSample*3+1]) << 16) | ((ma_uint32)(pSamplesIn8[iSample*3+2])) << 24);
27867  sampleS32 = (ma_int32)(sampleS32 * factor);
27868 
27869  pSamplesOut8[iSample*3+0] = (ma_uint8)(((ma_uint32)sampleS32 & 0x0000FF00) >> 8);
27870  pSamplesOut8[iSample*3+1] = (ma_uint8)(((ma_uint32)sampleS32 & 0x00FF0000) >> 16);
27871  pSamplesOut8[iSample*3+2] = (ma_uint8)(((ma_uint32)sampleS32 & 0xFF000000) >> 24);
27872  }
27873 }
27874 
27875 MA_API void ma_copy_and_apply_volume_factor_s32(ma_int32* pSamplesOut, const ma_int32* pSamplesIn, ma_uint64 sampleCount, float factor)
27876 {
27877  ma_uint64 iSample;
27878 
27879  if (pSamplesOut == NULL || pSamplesIn == NULL) {
27880  return;
27881  }
27882 
27883  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27884  pSamplesOut[iSample] = (ma_int32)(pSamplesIn[iSample] * factor);
27885  }
27886 }
27887 
27888 MA_API void ma_copy_and_apply_volume_factor_f32(float* pSamplesOut, const float* pSamplesIn, ma_uint64 sampleCount, float factor)
27889 {
27890  ma_uint64 iSample;
27891 
27892  if (pSamplesOut == NULL || pSamplesIn == NULL) {
27893  return;
27894  }
27895 
27896  for (iSample = 0; iSample < sampleCount; iSample += 1) {
27897  pSamplesOut[iSample] = pSamplesIn[iSample] * factor;
27898  }
27899 }
27900 
27901 MA_API void ma_apply_volume_factor_u8(ma_uint8* pSamples, ma_uint64 sampleCount, float factor)
27902 {
27903  ma_copy_and_apply_volume_factor_u8(pSamples, pSamples, sampleCount, factor);
27904 }
27905 
27906 MA_API void ma_apply_volume_factor_s16(ma_int16* pSamples, ma_uint64 sampleCount, float factor)
27907 {
27908  ma_copy_and_apply_volume_factor_s16(pSamples, pSamples, sampleCount, factor);
27909 }
27910 
27911 MA_API void ma_apply_volume_factor_s24(void* pSamples, ma_uint64 sampleCount, float factor)
27912 {
27913  ma_copy_and_apply_volume_factor_s24(pSamples, pSamples, sampleCount, factor);
27914 }
27915 
27916 MA_API void ma_apply_volume_factor_s32(ma_int32* pSamples, ma_uint64 sampleCount, float factor)
27917 {
27918  ma_copy_and_apply_volume_factor_s32(pSamples, pSamples, sampleCount, factor);
27919 }
27920 
27921 MA_API void ma_apply_volume_factor_f32(float* pSamples, ma_uint64 sampleCount, float factor)
27922 {
27923  ma_copy_and_apply_volume_factor_f32(pSamples, pSamples, sampleCount, factor);
27924 }
27925 
27926 MA_API void ma_copy_and_apply_volume_factor_pcm_frames_u8(ma_uint8* pPCMFramesOut, const ma_uint8* pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
27927 {
27928  ma_copy_and_apply_volume_factor_u8(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
27929 }
27930 
27931 MA_API void ma_copy_and_apply_volume_factor_pcm_frames_s16(ma_int16* pPCMFramesOut, const ma_int16* pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
27932 {
27933  ma_copy_and_apply_volume_factor_s16(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
27934 }
27935 
27936 MA_API void ma_copy_and_apply_volume_factor_pcm_frames_s24(void* pPCMFramesOut, const void* pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
27937 {
27938  ma_copy_and_apply_volume_factor_s24(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
27939 }
27940 
27941 MA_API void ma_copy_and_apply_volume_factor_pcm_frames_s32(ma_int32* pPCMFramesOut, const ma_int32* pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
27942 {
27943  ma_copy_and_apply_volume_factor_s32(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
27944 }
27945 
27946 MA_API void ma_copy_and_apply_volume_factor_pcm_frames_f32(float* pPCMFramesOut, const float* pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
27947 {
27948  ma_copy_and_apply_volume_factor_f32(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
27949 }
27950 
27951 MA_API void ma_copy_and_apply_volume_factor_pcm_frames(void* pPCMFramesOut, const void* pPCMFramesIn, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor)
27952 {
27953  switch (format)
27954  {
27955  case ma_format_u8: ma_copy_and_apply_volume_factor_pcm_frames_u8 ((ma_uint8*)pPCMFramesOut, (const ma_uint8*)pPCMFramesIn, frameCount, channels, factor); return;
27956  case ma_format_s16: ma_copy_and_apply_volume_factor_pcm_frames_s16((ma_int16*)pPCMFramesOut, (const ma_int16*)pPCMFramesIn, frameCount, channels, factor); return;
27957  case ma_format_s24: ma_copy_and_apply_volume_factor_pcm_frames_s24( pPCMFramesOut, pPCMFramesIn, frameCount, channels, factor); return;
27958  case ma_format_s32: ma_copy_and_apply_volume_factor_pcm_frames_s32((ma_int32*)pPCMFramesOut, (const ma_int32*)pPCMFramesIn, frameCount, channels, factor); return;
27959  case ma_format_f32: ma_copy_and_apply_volume_factor_pcm_frames_f32( (float*)pPCMFramesOut, (const float*)pPCMFramesIn, frameCount, channels, factor); return;
27960  default: return; /* Do nothing. */
27961  }
27962 }
27963 
27964 MA_API void ma_apply_volume_factor_pcm_frames_u8(ma_uint8* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
27965 {
27966  ma_copy_and_apply_volume_factor_pcm_frames_u8(pPCMFrames, pPCMFrames, frameCount, channels, factor);
27967 }
27968 
27969 MA_API void ma_apply_volume_factor_pcm_frames_s16(ma_int16* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
27970 {
27971  ma_copy_and_apply_volume_factor_pcm_frames_s16(pPCMFrames, pPCMFrames, frameCount, channels, factor);
27972 }
27973 
27974 MA_API void ma_apply_volume_factor_pcm_frames_s24(void* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
27975 {
27976  ma_copy_and_apply_volume_factor_pcm_frames_s24(pPCMFrames, pPCMFrames, frameCount, channels, factor);
27977 }
27978 
27979 MA_API void ma_apply_volume_factor_pcm_frames_s32(ma_int32* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
27980 {
27981  ma_copy_and_apply_volume_factor_pcm_frames_s32(pPCMFrames, pPCMFrames, frameCount, channels, factor);
27982 }
27983 
27984 MA_API void ma_apply_volume_factor_pcm_frames_f32(float* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
27985 {
27986  ma_copy_and_apply_volume_factor_pcm_frames_f32(pPCMFrames, pPCMFrames, frameCount, channels, factor);
27987 }
27988 
27989 MA_API void ma_apply_volume_factor_pcm_frames(void* pPCMFrames, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor)
27990 {
27991  ma_copy_and_apply_volume_factor_pcm_frames(pPCMFrames, pPCMFrames, frameCount, format, channels, factor);
27992 }
27993 
27994 
27995 MA_API float ma_factor_to_gain_db(float factor)
27996 {
27997  return (float)(20*ma_log10f(factor));
27998 }
27999 
28000 MA_API float ma_gain_db_to_factor(float gain)
28001 {
28002  return (float)ma_powf(10, gain/20.0f);
28003 }
28004 
28005 
28006 /**************************************************************************************************************************************************************
28007 
28008 Format Conversion
28009 
28010 **************************************************************************************************************************************************************/
28011 
28013 {
28014  return (ma_int16)(x * 32767.0f);
28015 }
28016 
28018 {
28019  return (ma_int16)((ma_int16)x - 128);
28020 }
28021 
28023 {
28024  return (ma_int64)(((ma_uint64)x[0] << 40) | ((ma_uint64)x[1] << 48) | ((ma_uint64)x[2] << 56)) >> 40; /* Make sure the sign bits are maintained. */
28025 }
28026 
28028 {
28029  s24[0] = (ma_uint8)((x & 0x000000FF) >> 0);
28030  s24[1] = (ma_uint8)((x & 0x0000FF00) >> 8);
28031  s24[2] = (ma_uint8)((x & 0x00FF0000) >> 16);
28032 }
28033 
28034 
28036 {
28037  return (ma_uint8)(ma_clamp(x, -128, 127) + 128);
28038 }
28039 
28041 {
28042  return (ma_int16)ma_clamp(x, -32768, 32767);
28043 }
28044 
28046 {
28047  return (ma_int64)ma_clamp(x, -8388608, 8388607);
28048 }
28049 
28051 {
28052  /* This dance is to silence warnings with -std=c89. A good compiler should be able to optimize this away. */
28053  ma_int64 clipMin;
28054  ma_int64 clipMax;
28055  clipMin = -((ma_int64)2147483647 + 1);
28056  clipMax = (ma_int64)2147483647;
28057 
28058  return (ma_int32)ma_clamp(x, clipMin, clipMax);
28059 }
28060 
28061 
28062 /* u8 */
28063 MA_API void ma_pcm_u8_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28064 {
28065  (void)ditherMode;
28066  ma_copy_memory_64(dst, src, count * sizeof(ma_uint8));
28067 }
28068 
28069 
28070 static MA_INLINE void ma_pcm_u8_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28071 {
28072  ma_int16* dst_s16 = (ma_int16*)dst;
28073  const ma_uint8* src_u8 = (const ma_uint8*)src;
28074 
28075  ma_uint64 i;
28076  for (i = 0; i < count; i += 1) {
28077  ma_int16 x = src_u8[i];
28078  x = (ma_int16)(x - 128);
28079  x = (ma_int16)(x << 8);
28080  dst_s16[i] = x;
28081  }
28082 
28083  (void)ditherMode;
28084 }
28085 
28086 static MA_INLINE void ma_pcm_u8_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28087 {
28088  ma_pcm_u8_to_s16__reference(dst, src, count, ditherMode);
28089 }
28090 
28091 #if defined(MA_SUPPORT_SSE2)
28092 static MA_INLINE void ma_pcm_u8_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28093 {
28094  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
28095 }
28096 #endif
28097 #if defined(MA_SUPPORT_AVX2)
28098 static MA_INLINE void ma_pcm_u8_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28099 {
28100  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
28101 }
28102 #endif
28103 #if defined(MA_SUPPORT_NEON)
28104 static MA_INLINE void ma_pcm_u8_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28105 {
28106  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
28107 }
28108 #endif
28109 
28110 MA_API void ma_pcm_u8_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28111 {
28112 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28113  ma_pcm_u8_to_s16__reference(dst, src, count, ditherMode);
28114 #else
28115  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28116  if (ma_has_avx2()) {
28117  ma_pcm_u8_to_s16__avx2(dst, src, count, ditherMode);
28118  } else
28119  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28120  if (ma_has_sse2()) {
28121  ma_pcm_u8_to_s16__sse2(dst, src, count, ditherMode);
28122  } else
28123  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28124  if (ma_has_neon()) {
28125  ma_pcm_u8_to_s16__neon(dst, src, count, ditherMode);
28126  } else
28127  #endif
28128  {
28129  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
28130  }
28131 #endif
28132 }
28133 
28134 
28135 static MA_INLINE void ma_pcm_u8_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28136 {
28137  ma_uint8* dst_s24 = (ma_uint8*)dst;
28138  const ma_uint8* src_u8 = (const ma_uint8*)src;
28139 
28140  ma_uint64 i;
28141  for (i = 0; i < count; i += 1) {
28142  ma_int16 x = src_u8[i];
28143  x = (ma_int16)(x - 128);
28144 
28145  dst_s24[i*3+0] = 0;
28146  dst_s24[i*3+1] = 0;
28147  dst_s24[i*3+2] = (ma_uint8)((ma_int8)x);
28148  }
28149 
28150  (void)ditherMode;
28151 }
28152 
28153 static MA_INLINE void ma_pcm_u8_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28154 {
28155  ma_pcm_u8_to_s24__reference(dst, src, count, ditherMode);
28156 }
28157 
28158 #if defined(MA_SUPPORT_SSE2)
28159 static MA_INLINE void ma_pcm_u8_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28160 {
28161  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
28162 }
28163 #endif
28164 #if defined(MA_SUPPORT_AVX2)
28165 static MA_INLINE void ma_pcm_u8_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28166 {
28167  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
28168 }
28169 #endif
28170 #if defined(MA_SUPPORT_NEON)
28171 static MA_INLINE void ma_pcm_u8_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28172 {
28173  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
28174 }
28175 #endif
28176 
28177 MA_API void ma_pcm_u8_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28178 {
28179 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28180  ma_pcm_u8_to_s24__reference(dst, src, count, ditherMode);
28181 #else
28182  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28183  if (ma_has_avx2()) {
28184  ma_pcm_u8_to_s24__avx2(dst, src, count, ditherMode);
28185  } else
28186  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28187  if (ma_has_sse2()) {
28188  ma_pcm_u8_to_s24__sse2(dst, src, count, ditherMode);
28189  } else
28190  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28191  if (ma_has_neon()) {
28192  ma_pcm_u8_to_s24__neon(dst, src, count, ditherMode);
28193  } else
28194  #endif
28195  {
28196  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
28197  }
28198 #endif
28199 }
28200 
28201 
28202 static MA_INLINE void ma_pcm_u8_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28203 {
28204  ma_int32* dst_s32 = (ma_int32*)dst;
28205  const ma_uint8* src_u8 = (const ma_uint8*)src;
28206 
28207  ma_uint64 i;
28208  for (i = 0; i < count; i += 1) {
28209  ma_int32 x = src_u8[i];
28210  x = x - 128;
28211  x = x << 24;
28212  dst_s32[i] = x;
28213  }
28214 
28215  (void)ditherMode;
28216 }
28217 
28218 static MA_INLINE void ma_pcm_u8_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28219 {
28220  ma_pcm_u8_to_s32__reference(dst, src, count, ditherMode);
28221 }
28222 
28223 #if defined(MA_SUPPORT_SSE2)
28224 static MA_INLINE void ma_pcm_u8_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28225 {
28226  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
28227 }
28228 #endif
28229 #if defined(MA_SUPPORT_AVX2)
28230 static MA_INLINE void ma_pcm_u8_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28231 {
28232  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
28233 }
28234 #endif
28235 #if defined(MA_SUPPORT_NEON)
28236 static MA_INLINE void ma_pcm_u8_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28237 {
28238  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
28239 }
28240 #endif
28241 
28242 MA_API void ma_pcm_u8_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28243 {
28244 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28245  ma_pcm_u8_to_s32__reference(dst, src, count, ditherMode);
28246 #else
28247  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28248  if (ma_has_avx2()) {
28249  ma_pcm_u8_to_s32__avx2(dst, src, count, ditherMode);
28250  } else
28251  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28252  if (ma_has_sse2()) {
28253  ma_pcm_u8_to_s32__sse2(dst, src, count, ditherMode);
28254  } else
28255  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28256  if (ma_has_neon()) {
28257  ma_pcm_u8_to_s32__neon(dst, src, count, ditherMode);
28258  } else
28259  #endif
28260  {
28261  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
28262  }
28263 #endif
28264 }
28265 
28266 
28267 static MA_INLINE void ma_pcm_u8_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28268 {
28269  float* dst_f32 = (float*)dst;
28270  const ma_uint8* src_u8 = (const ma_uint8*)src;
28271 
28272  ma_uint64 i;
28273  for (i = 0; i < count; i += 1) {
28274  float x = (float)src_u8[i];
28275  x = x * 0.00784313725490196078f; /* 0..255 to 0..2 */
28276  x = x - 1; /* 0..2 to -1..1 */
28277 
28278  dst_f32[i] = x;
28279  }
28280 
28281  (void)ditherMode;
28282 }
28283 
28284 static MA_INLINE void ma_pcm_u8_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28285 {
28286  ma_pcm_u8_to_f32__reference(dst, src, count, ditherMode);
28287 }
28288 
28289 #if defined(MA_SUPPORT_SSE2)
28290 static MA_INLINE void ma_pcm_u8_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28291 {
28292  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
28293 }
28294 #endif
28295 #if defined(MA_SUPPORT_AVX2)
28296 static MA_INLINE void ma_pcm_u8_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28297 {
28298  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
28299 }
28300 #endif
28301 #if defined(MA_SUPPORT_NEON)
28302 static MA_INLINE void ma_pcm_u8_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28303 {
28304  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
28305 }
28306 #endif
28307 
28308 MA_API void ma_pcm_u8_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28309 {
28310 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28311  ma_pcm_u8_to_f32__reference(dst, src, count, ditherMode);
28312 #else
28313  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28314  if (ma_has_avx2()) {
28315  ma_pcm_u8_to_f32__avx2(dst, src, count, ditherMode);
28316  } else
28317  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28318  if (ma_has_sse2()) {
28319  ma_pcm_u8_to_f32__sse2(dst, src, count, ditherMode);
28320  } else
28321  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28322  if (ma_has_neon()) {
28323  ma_pcm_u8_to_f32__neon(dst, src, count, ditherMode);
28324  } else
28325  #endif
28326  {
28327  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
28328  }
28329 #endif
28330 }
28331 
28332 
28333 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28334 static MA_INLINE void ma_pcm_interleave_u8__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
28335 {
28336  ma_uint8* dst_u8 = (ma_uint8*)dst;
28337  const ma_uint8** src_u8 = (const ma_uint8**)src;
28338 
28339  ma_uint64 iFrame;
28340  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28341  ma_uint32 iChannel;
28342  for (iChannel = 0; iChannel < channels; iChannel += 1) {
28343  dst_u8[iFrame*channels + iChannel] = src_u8[iChannel][iFrame];
28344  }
28345  }
28346 }
28347 #else
28348 static MA_INLINE void ma_pcm_interleave_u8__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
28349 {
28350  ma_uint8* dst_u8 = (ma_uint8*)dst;
28351  const ma_uint8** src_u8 = (const ma_uint8**)src;
28352 
28353  if (channels == 1) {
28354  ma_copy_memory_64(dst, src[0], frameCount * sizeof(ma_uint8));
28355  } else if (channels == 2) {
28356  ma_uint64 iFrame;
28357  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28358  dst_u8[iFrame*2 + 0] = src_u8[0][iFrame];
28359  dst_u8[iFrame*2 + 1] = src_u8[1][iFrame];
28360  }
28361  } else {
28362  ma_uint64 iFrame;
28363  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28364  ma_uint32 iChannel;
28365  for (iChannel = 0; iChannel < channels; iChannel += 1) {
28366  dst_u8[iFrame*channels + iChannel] = src_u8[iChannel][iFrame];
28367  }
28368  }
28369  }
28370 }
28371 #endif
28372 
28373 MA_API void ma_pcm_interleave_u8(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
28374 {
28375 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28376  ma_pcm_interleave_u8__reference(dst, src, frameCount, channels);
28377 #else
28378  ma_pcm_interleave_u8__optimized(dst, src, frameCount, channels);
28379 #endif
28380 }
28381 
28382 
28383 static MA_INLINE void ma_pcm_deinterleave_u8__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
28384 {
28385  ma_uint8** dst_u8 = (ma_uint8**)dst;
28386  const ma_uint8* src_u8 = (const ma_uint8*)src;
28387 
28388  ma_uint64 iFrame;
28389  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28390  ma_uint32 iChannel;
28391  for (iChannel = 0; iChannel < channels; iChannel += 1) {
28392  dst_u8[iChannel][iFrame] = src_u8[iFrame*channels + iChannel];
28393  }
28394  }
28395 }
28396 
28397 static MA_INLINE void ma_pcm_deinterleave_u8__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
28398 {
28399  ma_pcm_deinterleave_u8__reference(dst, src, frameCount, channels);
28400 }
28401 
28402 MA_API void ma_pcm_deinterleave_u8(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
28403 {
28404 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28405  ma_pcm_deinterleave_u8__reference(dst, src, frameCount, channels);
28406 #else
28407  ma_pcm_deinterleave_u8__optimized(dst, src, frameCount, channels);
28408 #endif
28409 }
28410 
28411 
28412 /* s16 */
28413 static MA_INLINE void ma_pcm_s16_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28414 {
28415  ma_uint8* dst_u8 = (ma_uint8*)dst;
28416  const ma_int16* src_s16 = (const ma_int16*)src;
28417 
28418  if (ditherMode == ma_dither_mode_none) {
28419  ma_uint64 i;
28420  for (i = 0; i < count; i += 1) {
28421  ma_int16 x = src_s16[i];
28422  x = (ma_int16)(x >> 8);
28423  x = (ma_int16)(x + 128);
28424  dst_u8[i] = (ma_uint8)x;
28425  }
28426  } else {
28427  ma_uint64 i;
28428  for (i = 0; i < count; i += 1) {
28429  ma_int16 x = src_s16[i];
28430 
28431  /* Dither. Don't overflow. */
28432  ma_int32 dither = ma_dither_s32(ditherMode, -0x80, 0x7F);
28433  if ((x + dither) <= 0x7FFF) {
28434  x = (ma_int16)(x + dither);
28435  } else {
28436  x = 0x7FFF;
28437  }
28438 
28439  x = (ma_int16)(x >> 8);
28440  x = (ma_int16)(x + 128);
28441  dst_u8[i] = (ma_uint8)x;
28442  }
28443  }
28444 }
28445 
28446 static MA_INLINE void ma_pcm_s16_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28447 {
28448  ma_pcm_s16_to_u8__reference(dst, src, count, ditherMode);
28449 }
28450 
28451 #if defined(MA_SUPPORT_SSE2)
28452 static MA_INLINE void ma_pcm_s16_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28453 {
28454  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
28455 }
28456 #endif
28457 #if defined(MA_SUPPORT_AVX2)
28458 static MA_INLINE void ma_pcm_s16_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28459 {
28460  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
28461 }
28462 #endif
28463 #if defined(MA_SUPPORT_NEON)
28464 static MA_INLINE void ma_pcm_s16_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28465 {
28466  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
28467 }
28468 #endif
28469 
28470 MA_API void ma_pcm_s16_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28471 {
28472 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28473  ma_pcm_s16_to_u8__reference(dst, src, count, ditherMode);
28474 #else
28475  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28476  if (ma_has_avx2()) {
28477  ma_pcm_s16_to_u8__avx2(dst, src, count, ditherMode);
28478  } else
28479  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28480  if (ma_has_sse2()) {
28481  ma_pcm_s16_to_u8__sse2(dst, src, count, ditherMode);
28482  } else
28483  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28484  if (ma_has_neon()) {
28485  ma_pcm_s16_to_u8__neon(dst, src, count, ditherMode);
28486  } else
28487  #endif
28488  {
28489  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
28490  }
28491 #endif
28492 }
28493 
28494 
28495 MA_API void ma_pcm_s16_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28496 {
28497  (void)ditherMode;
28498  ma_copy_memory_64(dst, src, count * sizeof(ma_int16));
28499 }
28500 
28501 
28502 static MA_INLINE void ma_pcm_s16_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28503 {
28504  ma_uint8* dst_s24 = (ma_uint8*)dst;
28505  const ma_int16* src_s16 = (const ma_int16*)src;
28506 
28507  ma_uint64 i;
28508  for (i = 0; i < count; i += 1) {
28509  dst_s24[i*3+0] = 0;
28510  dst_s24[i*3+1] = (ma_uint8)(src_s16[i] & 0xFF);
28511  dst_s24[i*3+2] = (ma_uint8)(src_s16[i] >> 8);
28512  }
28513 
28514  (void)ditherMode;
28515 }
28516 
28517 static MA_INLINE void ma_pcm_s16_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28518 {
28519  ma_pcm_s16_to_s24__reference(dst, src, count, ditherMode);
28520 }
28521 
28522 #if defined(MA_SUPPORT_SSE2)
28523 static MA_INLINE void ma_pcm_s16_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28524 {
28525  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
28526 }
28527 #endif
28528 #if defined(MA_SUPPORT_AVX2)
28529 static MA_INLINE void ma_pcm_s16_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28530 {
28531  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
28532 }
28533 #endif
28534 #if defined(MA_SUPPORT_NEON)
28535 static MA_INLINE void ma_pcm_s16_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28536 {
28537  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
28538 }
28539 #endif
28540 
28541 MA_API void ma_pcm_s16_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28542 {
28543 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28544  ma_pcm_s16_to_s24__reference(dst, src, count, ditherMode);
28545 #else
28546  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28547  if (ma_has_avx2()) {
28548  ma_pcm_s16_to_s24__avx2(dst, src, count, ditherMode);
28549  } else
28550  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28551  if (ma_has_sse2()) {
28552  ma_pcm_s16_to_s24__sse2(dst, src, count, ditherMode);
28553  } else
28554  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28555  if (ma_has_neon()) {
28556  ma_pcm_s16_to_s24__neon(dst, src, count, ditherMode);
28557  } else
28558  #endif
28559  {
28560  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
28561  }
28562 #endif
28563 }
28564 
28565 
28566 static MA_INLINE void ma_pcm_s16_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28567 {
28568  ma_int32* dst_s32 = (ma_int32*)dst;
28569  const ma_int16* src_s16 = (const ma_int16*)src;
28570 
28571  ma_uint64 i;
28572  for (i = 0; i < count; i += 1) {
28573  dst_s32[i] = src_s16[i] << 16;
28574  }
28575 
28576  (void)ditherMode;
28577 }
28578 
28579 static MA_INLINE void ma_pcm_s16_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28580 {
28581  ma_pcm_s16_to_s32__reference(dst, src, count, ditherMode);
28582 }
28583 
28584 #if defined(MA_SUPPORT_SSE2)
28585 static MA_INLINE void ma_pcm_s16_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28586 {
28587  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
28588 }
28589 #endif
28590 #if defined(MA_SUPPORT_AVX2)
28591 static MA_INLINE void ma_pcm_s16_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28592 {
28593  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
28594 }
28595 #endif
28596 #if defined(MA_SUPPORT_NEON)
28597 static MA_INLINE void ma_pcm_s16_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28598 {
28599  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
28600 }
28601 #endif
28602 
28603 MA_API void ma_pcm_s16_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28604 {
28605 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28606  ma_pcm_s16_to_s32__reference(dst, src, count, ditherMode);
28607 #else
28608  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28609  if (ma_has_avx2()) {
28610  ma_pcm_s16_to_s32__avx2(dst, src, count, ditherMode);
28611  } else
28612  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28613  if (ma_has_sse2()) {
28614  ma_pcm_s16_to_s32__sse2(dst, src, count, ditherMode);
28615  } else
28616  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28617  if (ma_has_neon()) {
28618  ma_pcm_s16_to_s32__neon(dst, src, count, ditherMode);
28619  } else
28620  #endif
28621  {
28622  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
28623  }
28624 #endif
28625 }
28626 
28627 
28628 static MA_INLINE void ma_pcm_s16_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28629 {
28630  float* dst_f32 = (float*)dst;
28631  const ma_int16* src_s16 = (const ma_int16*)src;
28632 
28633  ma_uint64 i;
28634  for (i = 0; i < count; i += 1) {
28635  float x = (float)src_s16[i];
28636 
28637 #if 0
28638  /* The accurate way. */
28639  x = x + 32768.0f; /* -32768..32767 to 0..65535 */
28640  x = x * 0.00003051804379339284f; /* 0..65535 to 0..2 */
28641  x = x - 1; /* 0..2 to -1..1 */
28642 #else
28643  /* The fast way. */
28644  x = x * 0.000030517578125f; /* -32768..32767 to -1..0.999969482421875 */
28645 #endif
28646 
28647  dst_f32[i] = x;
28648  }
28649 
28650  (void)ditherMode;
28651 }
28652 
28653 static MA_INLINE void ma_pcm_s16_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28654 {
28655  ma_pcm_s16_to_f32__reference(dst, src, count, ditherMode);
28656 }
28657 
28658 #if defined(MA_SUPPORT_SSE2)
28659 static MA_INLINE void ma_pcm_s16_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28660 {
28661  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
28662 }
28663 #endif
28664 #if defined(MA_SUPPORT_AVX2)
28665 static MA_INLINE void ma_pcm_s16_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28666 {
28667  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
28668 }
28669 #endif
28670 #if defined(MA_SUPPORT_NEON)
28671 static MA_INLINE void ma_pcm_s16_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28672 {
28673  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
28674 }
28675 #endif
28676 
28677 MA_API void ma_pcm_s16_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28678 {
28679 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28680  ma_pcm_s16_to_f32__reference(dst, src, count, ditherMode);
28681 #else
28682  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28683  if (ma_has_avx2()) {
28684  ma_pcm_s16_to_f32__avx2(dst, src, count, ditherMode);
28685  } else
28686  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28687  if (ma_has_sse2()) {
28688  ma_pcm_s16_to_f32__sse2(dst, src, count, ditherMode);
28689  } else
28690  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28691  if (ma_has_neon()) {
28692  ma_pcm_s16_to_f32__neon(dst, src, count, ditherMode);
28693  } else
28694  #endif
28695  {
28696  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
28697  }
28698 #endif
28699 }
28700 
28701 
28702 static MA_INLINE void ma_pcm_interleave_s16__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
28703 {
28704  ma_int16* dst_s16 = (ma_int16*)dst;
28705  const ma_int16** src_s16 = (const ma_int16**)src;
28706 
28707  ma_uint64 iFrame;
28708  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28709  ma_uint32 iChannel;
28710  for (iChannel = 0; iChannel < channels; iChannel += 1) {
28711  dst_s16[iFrame*channels + iChannel] = src_s16[iChannel][iFrame];
28712  }
28713  }
28714 }
28715 
28716 static MA_INLINE void ma_pcm_interleave_s16__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
28717 {
28718  ma_pcm_interleave_s16__reference(dst, src, frameCount, channels);
28719 }
28720 
28721 MA_API void ma_pcm_interleave_s16(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
28722 {
28723 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28724  ma_pcm_interleave_s16__reference(dst, src, frameCount, channels);
28725 #else
28726  ma_pcm_interleave_s16__optimized(dst, src, frameCount, channels);
28727 #endif
28728 }
28729 
28730 
28731 static MA_INLINE void ma_pcm_deinterleave_s16__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
28732 {
28733  ma_int16** dst_s16 = (ma_int16**)dst;
28734  const ma_int16* src_s16 = (const ma_int16*)src;
28735 
28736  ma_uint64 iFrame;
28737  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28738  ma_uint32 iChannel;
28739  for (iChannel = 0; iChannel < channels; iChannel += 1) {
28740  dst_s16[iChannel][iFrame] = src_s16[iFrame*channels + iChannel];
28741  }
28742  }
28743 }
28744 
28745 static MA_INLINE void ma_pcm_deinterleave_s16__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
28746 {
28747  ma_pcm_deinterleave_s16__reference(dst, src, frameCount, channels);
28748 }
28749 
28750 MA_API void ma_pcm_deinterleave_s16(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
28751 {
28752 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28753  ma_pcm_deinterleave_s16__reference(dst, src, frameCount, channels);
28754 #else
28755  ma_pcm_deinterleave_s16__optimized(dst, src, frameCount, channels);
28756 #endif
28757 }
28758 
28759 
28760 /* s24 */
28761 static MA_INLINE void ma_pcm_s24_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28762 {
28763  ma_uint8* dst_u8 = (ma_uint8*)dst;
28764  const ma_uint8* src_s24 = (const ma_uint8*)src;
28765 
28766  if (ditherMode == ma_dither_mode_none) {
28767  ma_uint64 i;
28768  for (i = 0; i < count; i += 1) {
28769  dst_u8[i] = (ma_uint8)((ma_int8)src_s24[i*3 + 2] + 128);
28770  }
28771  } else {
28772  ma_uint64 i;
28773  for (i = 0; i < count; i += 1) {
28774  ma_int32 x = (ma_int32)(((ma_uint32)(src_s24[i*3+0]) << 8) | ((ma_uint32)(src_s24[i*3+1]) << 16) | ((ma_uint32)(src_s24[i*3+2])) << 24);
28775 
28776  /* Dither. Don't overflow. */
28777  ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
28778  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
28779  x = x + dither;
28780  } else {
28781  x = 0x7FFFFFFF;
28782  }
28783 
28784  x = x >> 24;
28785  x = x + 128;
28786  dst_u8[i] = (ma_uint8)x;
28787  }
28788  }
28789 }
28790 
28791 static MA_INLINE void ma_pcm_s24_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28792 {
28793  ma_pcm_s24_to_u8__reference(dst, src, count, ditherMode);
28794 }
28795 
28796 #if defined(MA_SUPPORT_SSE2)
28797 static MA_INLINE void ma_pcm_s24_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28798 {
28799  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
28800 }
28801 #endif
28802 #if defined(MA_SUPPORT_AVX2)
28803 static MA_INLINE void ma_pcm_s24_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28804 {
28805  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
28806 }
28807 #endif
28808 #if defined(MA_SUPPORT_NEON)
28809 static MA_INLINE void ma_pcm_s24_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28810 {
28811  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
28812 }
28813 #endif
28814 
28815 MA_API void ma_pcm_s24_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28816 {
28817 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28818  ma_pcm_s24_to_u8__reference(dst, src, count, ditherMode);
28819 #else
28820  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28821  if (ma_has_avx2()) {
28822  ma_pcm_s24_to_u8__avx2(dst, src, count, ditherMode);
28823  } else
28824  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28825  if (ma_has_sse2()) {
28826  ma_pcm_s24_to_u8__sse2(dst, src, count, ditherMode);
28827  } else
28828  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28829  if (ma_has_neon()) {
28830  ma_pcm_s24_to_u8__neon(dst, src, count, ditherMode);
28831  } else
28832  #endif
28833  {
28834  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
28835  }
28836 #endif
28837 }
28838 
28839 
28840 static MA_INLINE void ma_pcm_s24_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28841 {
28842  ma_int16* dst_s16 = (ma_int16*)dst;
28843  const ma_uint8* src_s24 = (const ma_uint8*)src;
28844 
28845  if (ditherMode == ma_dither_mode_none) {
28846  ma_uint64 i;
28847  for (i = 0; i < count; i += 1) {
28848  ma_uint16 dst_lo = ((ma_uint16)src_s24[i*3 + 1]);
28849  ma_uint16 dst_hi = (ma_uint16)((ma_uint16)src_s24[i*3 + 2] << 8);
28850  dst_s16[i] = (ma_int16)(dst_lo | dst_hi);
28851  }
28852  } else {
28853  ma_uint64 i;
28854  for (i = 0; i < count; i += 1) {
28855  ma_int32 x = (ma_int32)(((ma_uint32)(src_s24[i*3+0]) << 8) | ((ma_uint32)(src_s24[i*3+1]) << 16) | ((ma_uint32)(src_s24[i*3+2])) << 24);
28856 
28857  /* Dither. Don't overflow. */
28858  ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
28859  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
28860  x = x + dither;
28861  } else {
28862  x = 0x7FFFFFFF;
28863  }
28864 
28865  x = x >> 16;
28866  dst_s16[i] = (ma_int16)x;
28867  }
28868  }
28869 }
28870 
28871 static MA_INLINE void ma_pcm_s24_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28872 {
28873  ma_pcm_s24_to_s16__reference(dst, src, count, ditherMode);
28874 }
28875 
28876 #if defined(MA_SUPPORT_SSE2)
28877 static MA_INLINE void ma_pcm_s24_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28878 {
28879  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
28880 }
28881 #endif
28882 #if defined(MA_SUPPORT_AVX2)
28883 static MA_INLINE void ma_pcm_s24_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28884 {
28885  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
28886 }
28887 #endif
28888 #if defined(MA_SUPPORT_NEON)
28889 static MA_INLINE void ma_pcm_s24_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28890 {
28891  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
28892 }
28893 #endif
28894 
28895 MA_API void ma_pcm_s24_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28896 {
28897 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28898  ma_pcm_s24_to_s16__reference(dst, src, count, ditherMode);
28899 #else
28900  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28901  if (ma_has_avx2()) {
28902  ma_pcm_s24_to_s16__avx2(dst, src, count, ditherMode);
28903  } else
28904  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28905  if (ma_has_sse2()) {
28906  ma_pcm_s24_to_s16__sse2(dst, src, count, ditherMode);
28907  } else
28908  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28909  if (ma_has_neon()) {
28910  ma_pcm_s24_to_s16__neon(dst, src, count, ditherMode);
28911  } else
28912  #endif
28913  {
28914  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
28915  }
28916 #endif
28917 }
28918 
28919 
28920 MA_API void ma_pcm_s24_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28921 {
28922  (void)ditherMode;
28923 
28924  ma_copy_memory_64(dst, src, count * 3);
28925 }
28926 
28927 
28928 static MA_INLINE void ma_pcm_s24_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28929 {
28930  ma_int32* dst_s32 = (ma_int32*)dst;
28931  const ma_uint8* src_s24 = (const ma_uint8*)src;
28932 
28933  ma_uint64 i;
28934  for (i = 0; i < count; i += 1) {
28935  dst_s32[i] = (ma_int32)(((ma_uint32)(src_s24[i*3+0]) << 8) | ((ma_uint32)(src_s24[i*3+1]) << 16) | ((ma_uint32)(src_s24[i*3+2])) << 24);
28936  }
28937 
28938  (void)ditherMode;
28939 }
28940 
28941 static MA_INLINE void ma_pcm_s24_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28942 {
28943  ma_pcm_s24_to_s32__reference(dst, src, count, ditherMode);
28944 }
28945 
28946 #if defined(MA_SUPPORT_SSE2)
28947 static MA_INLINE void ma_pcm_s24_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28948 {
28949  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
28950 }
28951 #endif
28952 #if defined(MA_SUPPORT_AVX2)
28953 static MA_INLINE void ma_pcm_s24_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28954 {
28955  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
28956 }
28957 #endif
28958 #if defined(MA_SUPPORT_NEON)
28959 static MA_INLINE void ma_pcm_s24_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28960 {
28961  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
28962 }
28963 #endif
28964 
28965 MA_API void ma_pcm_s24_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28966 {
28967 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28968  ma_pcm_s24_to_s32__reference(dst, src, count, ditherMode);
28969 #else
28970  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
28971  if (ma_has_avx2()) {
28972  ma_pcm_s24_to_s32__avx2(dst, src, count, ditherMode);
28973  } else
28974  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
28975  if (ma_has_sse2()) {
28976  ma_pcm_s24_to_s32__sse2(dst, src, count, ditherMode);
28977  } else
28978  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
28979  if (ma_has_neon()) {
28980  ma_pcm_s24_to_s32__neon(dst, src, count, ditherMode);
28981  } else
28982  #endif
28983  {
28984  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
28985  }
28986 #endif
28987 }
28988 
28989 
28990 static MA_INLINE void ma_pcm_s24_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
28991 {
28992  float* dst_f32 = (float*)dst;
28993  const ma_uint8* src_s24 = (const ma_uint8*)src;
28994 
28995  ma_uint64 i;
28996  for (i = 0; i < count; i += 1) {
28997  float x = (float)(((ma_int32)(((ma_uint32)(src_s24[i*3+0]) << 8) | ((ma_uint32)(src_s24[i*3+1]) << 16) | ((ma_uint32)(src_s24[i*3+2])) << 24)) >> 8);
28998 
28999 #if 0
29000  /* The accurate way. */
29001  x = x + 8388608.0f; /* -8388608..8388607 to 0..16777215 */
29002  x = x * 0.00000011920929665621f; /* 0..16777215 to 0..2 */
29003  x = x - 1; /* 0..2 to -1..1 */
29004 #else
29005  /* The fast way. */
29006  x = x * 0.00000011920928955078125f; /* -8388608..8388607 to -1..0.999969482421875 */
29007 #endif
29008 
29009  dst_f32[i] = x;
29010  }
29011 
29012  (void)ditherMode;
29013 }
29014 
29015 static MA_INLINE void ma_pcm_s24_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29016 {
29017  ma_pcm_s24_to_f32__reference(dst, src, count, ditherMode);
29018 }
29019 
29020 #if defined(MA_SUPPORT_SSE2)
29021 static MA_INLINE void ma_pcm_s24_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29022 {
29023  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
29024 }
29025 #endif
29026 #if defined(MA_SUPPORT_AVX2)
29027 static MA_INLINE void ma_pcm_s24_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29028 {
29029  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
29030 }
29031 #endif
29032 #if defined(MA_SUPPORT_NEON)
29033 static MA_INLINE void ma_pcm_s24_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29034 {
29035  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
29036 }
29037 #endif
29038 
29039 MA_API void ma_pcm_s24_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29040 {
29041 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29042  ma_pcm_s24_to_f32__reference(dst, src, count, ditherMode);
29043 #else
29044  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29045  if (ma_has_avx2()) {
29046  ma_pcm_s24_to_f32__avx2(dst, src, count, ditherMode);
29047  } else
29048  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29049  if (ma_has_sse2()) {
29050  ma_pcm_s24_to_f32__sse2(dst, src, count, ditherMode);
29051  } else
29052  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
29053  if (ma_has_neon()) {
29054  ma_pcm_s24_to_f32__neon(dst, src, count, ditherMode);
29055  } else
29056  #endif
29057  {
29058  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
29059  }
29060 #endif
29061 }
29062 
29063 
29064 static MA_INLINE void ma_pcm_interleave_s24__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
29065 {
29066  ma_uint8* dst8 = (ma_uint8*)dst;
29067  const ma_uint8** src8 = (const ma_uint8**)src;
29068 
29069  ma_uint64 iFrame;
29070  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
29071  ma_uint32 iChannel;
29072  for (iChannel = 0; iChannel < channels; iChannel += 1) {
29073  dst8[iFrame*3*channels + iChannel*3 + 0] = src8[iChannel][iFrame*3 + 0];
29074  dst8[iFrame*3*channels + iChannel*3 + 1] = src8[iChannel][iFrame*3 + 1];
29075  dst8[iFrame*3*channels + iChannel*3 + 2] = src8[iChannel][iFrame*3 + 2];
29076  }
29077  }
29078 }
29079 
29080 static MA_INLINE void ma_pcm_interleave_s24__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
29081 {
29082  ma_pcm_interleave_s24__reference(dst, src, frameCount, channels);
29083 }
29084 
29085 MA_API void ma_pcm_interleave_s24(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
29086 {
29087 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29088  ma_pcm_interleave_s24__reference(dst, src, frameCount, channels);
29089 #else
29090  ma_pcm_interleave_s24__optimized(dst, src, frameCount, channels);
29091 #endif
29092 }
29093 
29094 
29095 static MA_INLINE void ma_pcm_deinterleave_s24__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
29096 {
29097  ma_uint8** dst8 = (ma_uint8**)dst;
29098  const ma_uint8* src8 = (const ma_uint8*)src;
29099 
29100  ma_uint32 iFrame;
29101  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
29102  ma_uint32 iChannel;
29103  for (iChannel = 0; iChannel < channels; iChannel += 1) {
29104  dst8[iChannel][iFrame*3 + 0] = src8[iFrame*3*channels + iChannel*3 + 0];
29105  dst8[iChannel][iFrame*3 + 1] = src8[iFrame*3*channels + iChannel*3 + 1];
29106  dst8[iChannel][iFrame*3 + 2] = src8[iFrame*3*channels + iChannel*3 + 2];
29107  }
29108  }
29109 }
29110 
29111 static MA_INLINE void ma_pcm_deinterleave_s24__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
29112 {
29113  ma_pcm_deinterleave_s24__reference(dst, src, frameCount, channels);
29114 }
29115 
29116 MA_API void ma_pcm_deinterleave_s24(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
29117 {
29118 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29119  ma_pcm_deinterleave_s24__reference(dst, src, frameCount, channels);
29120 #else
29121  ma_pcm_deinterleave_s24__optimized(dst, src, frameCount, channels);
29122 #endif
29123 }
29124 
29125 
29126 
29127 /* s32 */
29128 static MA_INLINE void ma_pcm_s32_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29129 {
29130  ma_uint8* dst_u8 = (ma_uint8*)dst;
29131  const ma_int32* src_s32 = (const ma_int32*)src;
29132 
29133  if (ditherMode == ma_dither_mode_none) {
29134  ma_uint64 i;
29135  for (i = 0; i < count; i += 1) {
29136  ma_int32 x = src_s32[i];
29137  x = x >> 24;
29138  x = x + 128;
29139  dst_u8[i] = (ma_uint8)x;
29140  }
29141  } else {
29142  ma_uint64 i;
29143  for (i = 0; i < count; i += 1) {
29144  ma_int32 x = src_s32[i];
29145 
29146  /* Dither. Don't overflow. */
29147  ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
29148  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
29149  x = x + dither;
29150  } else {
29151  x = 0x7FFFFFFF;
29152  }
29153 
29154  x = x >> 24;
29155  x = x + 128;
29156  dst_u8[i] = (ma_uint8)x;
29157  }
29158  }
29159 }
29160 
29161 static MA_INLINE void ma_pcm_s32_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29162 {
29163  ma_pcm_s32_to_u8__reference(dst, src, count, ditherMode);
29164 }
29165 
29166 #if defined(MA_SUPPORT_SSE2)
29167 static MA_INLINE void ma_pcm_s32_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29168 {
29169  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
29170 }
29171 #endif
29172 #if defined(MA_SUPPORT_AVX2)
29173 static MA_INLINE void ma_pcm_s32_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29174 {
29175  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
29176 }
29177 #endif
29178 #if defined(MA_SUPPORT_NEON)
29179 static MA_INLINE void ma_pcm_s32_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29180 {
29181  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
29182 }
29183 #endif
29184 
29185 MA_API void ma_pcm_s32_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29186 {
29187 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29188  ma_pcm_s32_to_u8__reference(dst, src, count, ditherMode);
29189 #else
29190  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29191  if (ma_has_avx2()) {
29192  ma_pcm_s32_to_u8__avx2(dst, src, count, ditherMode);
29193  } else
29194  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29195  if (ma_has_sse2()) {
29196  ma_pcm_s32_to_u8__sse2(dst, src, count, ditherMode);
29197  } else
29198  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
29199  if (ma_has_neon()) {
29200  ma_pcm_s32_to_u8__neon(dst, src, count, ditherMode);
29201  } else
29202  #endif
29203  {
29204  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
29205  }
29206 #endif
29207 }
29208 
29209 
29210 static MA_INLINE void ma_pcm_s32_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29211 {
29212  ma_int16* dst_s16 = (ma_int16*)dst;
29213  const ma_int32* src_s32 = (const ma_int32*)src;
29214 
29215  if (ditherMode == ma_dither_mode_none) {
29216  ma_uint64 i;
29217  for (i = 0; i < count; i += 1) {
29218  ma_int32 x = src_s32[i];
29219  x = x >> 16;
29220  dst_s16[i] = (ma_int16)x;
29221  }
29222  } else {
29223  ma_uint64 i;
29224  for (i = 0; i < count; i += 1) {
29225  ma_int32 x = src_s32[i];
29226 
29227  /* Dither. Don't overflow. */
29228  ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
29229  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
29230  x = x + dither;
29231  } else {
29232  x = 0x7FFFFFFF;
29233  }
29234 
29235  x = x >> 16;
29236  dst_s16[i] = (ma_int16)x;
29237  }
29238  }
29239 }
29240 
29241 static MA_INLINE void ma_pcm_s32_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29242 {
29243  ma_pcm_s32_to_s16__reference(dst, src, count, ditherMode);
29244 }
29245 
29246 #if defined(MA_SUPPORT_SSE2)
29247 static MA_INLINE void ma_pcm_s32_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29248 {
29249  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
29250 }
29251 #endif
29252 #if defined(MA_SUPPORT_AVX2)
29253 static MA_INLINE void ma_pcm_s32_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29254 {
29255  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
29256 }
29257 #endif
29258 #if defined(MA_SUPPORT_NEON)
29259 static MA_INLINE void ma_pcm_s32_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29260 {
29261  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
29262 }
29263 #endif
29264 
29265 MA_API void ma_pcm_s32_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29266 {
29267 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29268  ma_pcm_s32_to_s16__reference(dst, src, count, ditherMode);
29269 #else
29270  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29271  if (ma_has_avx2()) {
29272  ma_pcm_s32_to_s16__avx2(dst, src, count, ditherMode);
29273  } else
29274  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29275  if (ma_has_sse2()) {
29276  ma_pcm_s32_to_s16__sse2(dst, src, count, ditherMode);
29277  } else
29278  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
29279  if (ma_has_neon()) {
29280  ma_pcm_s32_to_s16__neon(dst, src, count, ditherMode);
29281  } else
29282  #endif
29283  {
29284  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
29285  }
29286 #endif
29287 }
29288 
29289 
29290 static MA_INLINE void ma_pcm_s32_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29291 {
29292  ma_uint8* dst_s24 = (ma_uint8*)dst;
29293  const ma_int32* src_s32 = (const ma_int32*)src;
29294 
29295  ma_uint64 i;
29296  for (i = 0; i < count; i += 1) {
29297  ma_uint32 x = (ma_uint32)src_s32[i];
29298  dst_s24[i*3+0] = (ma_uint8)((x & 0x0000FF00) >> 8);
29299  dst_s24[i*3+1] = (ma_uint8)((x & 0x00FF0000) >> 16);
29300  dst_s24[i*3+2] = (ma_uint8)((x & 0xFF000000) >> 24);
29301  }
29302 
29303  (void)ditherMode; /* No dithering for s32 -> s24. */
29304 }
29305 
29306 static MA_INLINE void ma_pcm_s32_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29307 {
29308  ma_pcm_s32_to_s24__reference(dst, src, count, ditherMode);
29309 }
29310 
29311 #if defined(MA_SUPPORT_SSE2)
29312 static MA_INLINE void ma_pcm_s32_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29313 {
29314  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
29315 }
29316 #endif
29317 #if defined(MA_SUPPORT_AVX2)
29318 static MA_INLINE void ma_pcm_s32_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29319 {
29320  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
29321 }
29322 #endif
29323 #if defined(MA_SUPPORT_NEON)
29324 static MA_INLINE void ma_pcm_s32_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29325 {
29326  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
29327 }
29328 #endif
29329 
29330 MA_API void ma_pcm_s32_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29331 {
29332 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29333  ma_pcm_s32_to_s24__reference(dst, src, count, ditherMode);
29334 #else
29335  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29336  if (ma_has_avx2()) {
29337  ma_pcm_s32_to_s24__avx2(dst, src, count, ditherMode);
29338  } else
29339  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29340  if (ma_has_sse2()) {
29341  ma_pcm_s32_to_s24__sse2(dst, src, count, ditherMode);
29342  } else
29343  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
29344  if (ma_has_neon()) {
29345  ma_pcm_s32_to_s24__neon(dst, src, count, ditherMode);
29346  } else
29347  #endif
29348  {
29349  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
29350  }
29351 #endif
29352 }
29353 
29354 
29355 MA_API void ma_pcm_s32_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29356 {
29357  (void)ditherMode;
29358 
29359  ma_copy_memory_64(dst, src, count * sizeof(ma_int32));
29360 }
29361 
29362 
29363 static MA_INLINE void ma_pcm_s32_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29364 {
29365  float* dst_f32 = (float*)dst;
29366  const ma_int32* src_s32 = (const ma_int32*)src;
29367 
29368  ma_uint64 i;
29369  for (i = 0; i < count; i += 1) {
29370  double x = src_s32[i];
29371 
29372 #if 0
29373  x = x + 2147483648.0;
29374  x = x * 0.0000000004656612873077392578125;
29375  x = x - 1;
29376 #else
29377  x = x / 2147483648.0;
29378 #endif
29379 
29380  dst_f32[i] = (float)x;
29381  }
29382 
29383  (void)ditherMode; /* No dithering for s32 -> f32. */
29384 }
29385 
29386 static MA_INLINE void ma_pcm_s32_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29387 {
29388  ma_pcm_s32_to_f32__reference(dst, src, count, ditherMode);
29389 }
29390 
29391 #if defined(MA_SUPPORT_SSE2)
29392 static MA_INLINE void ma_pcm_s32_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29393 {
29394  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
29395 }
29396 #endif
29397 #if defined(MA_SUPPORT_AVX2)
29398 static MA_INLINE void ma_pcm_s32_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29399 {
29400  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
29401 }
29402 #endif
29403 #if defined(MA_SUPPORT_NEON)
29404 static MA_INLINE void ma_pcm_s32_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29405 {
29406  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
29407 }
29408 #endif
29409 
29410 MA_API void ma_pcm_s32_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29411 {
29412 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29413  ma_pcm_s32_to_f32__reference(dst, src, count, ditherMode);
29414 #else
29415  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29416  if (ma_has_avx2()) {
29417  ma_pcm_s32_to_f32__avx2(dst, src, count, ditherMode);
29418  } else
29419  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29420  if (ma_has_sse2()) {
29421  ma_pcm_s32_to_f32__sse2(dst, src, count, ditherMode);
29422  } else
29423  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
29424  if (ma_has_neon()) {
29425  ma_pcm_s32_to_f32__neon(dst, src, count, ditherMode);
29426  } else
29427  #endif
29428  {
29429  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
29430  }
29431 #endif
29432 }
29433 
29434 
29435 static MA_INLINE void ma_pcm_interleave_s32__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
29436 {
29437  ma_int32* dst_s32 = (ma_int32*)dst;
29438  const ma_int32** src_s32 = (const ma_int32**)src;
29439 
29440  ma_uint64 iFrame;
29441  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
29442  ma_uint32 iChannel;
29443  for (iChannel = 0; iChannel < channels; iChannel += 1) {
29444  dst_s32[iFrame*channels + iChannel] = src_s32[iChannel][iFrame];
29445  }
29446  }
29447 }
29448 
29449 static MA_INLINE void ma_pcm_interleave_s32__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
29450 {
29451  ma_pcm_interleave_s32__reference(dst, src, frameCount, channels);
29452 }
29453 
29454 MA_API void ma_pcm_interleave_s32(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
29455 {
29456 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29457  ma_pcm_interleave_s32__reference(dst, src, frameCount, channels);
29458 #else
29459  ma_pcm_interleave_s32__optimized(dst, src, frameCount, channels);
29460 #endif
29461 }
29462 
29463 
29464 static MA_INLINE void ma_pcm_deinterleave_s32__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
29465 {
29466  ma_int32** dst_s32 = (ma_int32**)dst;
29467  const ma_int32* src_s32 = (const ma_int32*)src;
29468 
29469  ma_uint64 iFrame;
29470  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
29471  ma_uint32 iChannel;
29472  for (iChannel = 0; iChannel < channels; iChannel += 1) {
29473  dst_s32[iChannel][iFrame] = src_s32[iFrame*channels + iChannel];
29474  }
29475  }
29476 }
29477 
29478 static MA_INLINE void ma_pcm_deinterleave_s32__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
29479 {
29480  ma_pcm_deinterleave_s32__reference(dst, src, frameCount, channels);
29481 }
29482 
29483 MA_API void ma_pcm_deinterleave_s32(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
29484 {
29485 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29486  ma_pcm_deinterleave_s32__reference(dst, src, frameCount, channels);
29487 #else
29488  ma_pcm_deinterleave_s32__optimized(dst, src, frameCount, channels);
29489 #endif
29490 }
29491 
29492 
29493 /* f32 */
29494 static MA_INLINE void ma_pcm_f32_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29495 {
29496  ma_uint64 i;
29497 
29498  ma_uint8* dst_u8 = (ma_uint8*)dst;
29499  const float* src_f32 = (const float*)src;
29500 
29501  float ditherMin = 0;
29502  float ditherMax = 0;
29503  if (ditherMode != ma_dither_mode_none) {
29504  ditherMin = 1.0f / -128;
29505  ditherMax = 1.0f / 127;
29506  }
29507 
29508  for (i = 0; i < count; i += 1) {
29509  float x = src_f32[i];
29510  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29511  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
29512  x = x + 1; /* -1..1 to 0..2 */
29513  x = x * 127.5f; /* 0..2 to 0..255 */
29514 
29515  dst_u8[i] = (ma_uint8)x;
29516  }
29517 }
29518 
29519 static MA_INLINE void ma_pcm_f32_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29520 {
29521  ma_pcm_f32_to_u8__reference(dst, src, count, ditherMode);
29522 }
29523 
29524 #if defined(MA_SUPPORT_SSE2)
29525 static MA_INLINE void ma_pcm_f32_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29526 {
29527  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
29528 }
29529 #endif
29530 #if defined(MA_SUPPORT_AVX2)
29531 static MA_INLINE void ma_pcm_f32_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29532 {
29533  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
29534 }
29535 #endif
29536 #if defined(MA_SUPPORT_NEON)
29537 static MA_INLINE void ma_pcm_f32_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29538 {
29539  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
29540 }
29541 #endif
29542 
29543 MA_API void ma_pcm_f32_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29544 {
29545 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29546  ma_pcm_f32_to_u8__reference(dst, src, count, ditherMode);
29547 #else
29548  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29549  if (ma_has_avx2()) {
29550  ma_pcm_f32_to_u8__avx2(dst, src, count, ditherMode);
29551  } else
29552  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29553  if (ma_has_sse2()) {
29554  ma_pcm_f32_to_u8__sse2(dst, src, count, ditherMode);
29555  } else
29556  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
29557  if (ma_has_neon()) {
29558  ma_pcm_f32_to_u8__neon(dst, src, count, ditherMode);
29559  } else
29560  #endif
29561  {
29562  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
29563  }
29564 #endif
29565 }
29566 
29567 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29568 static MA_INLINE void ma_pcm_f32_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29569 {
29570  ma_uint64 i;
29571 
29572  ma_int16* dst_s16 = (ma_int16*)dst;
29573  const float* src_f32 = (const float*)src;
29574 
29575  float ditherMin = 0;
29576  float ditherMax = 0;
29577  if (ditherMode != ma_dither_mode_none) {
29578  ditherMin = 1.0f / -32768;
29579  ditherMax = 1.0f / 32767;
29580  }
29581 
29582  for (i = 0; i < count; i += 1) {
29583  float x = src_f32[i];
29584  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29585  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
29586 
29587 #if 0
29588  /* The accurate way. */
29589  x = x + 1; /* -1..1 to 0..2 */
29590  x = x * 32767.5f; /* 0..2 to 0..65535 */
29591  x = x - 32768.0f; /* 0...65535 to -32768..32767 */
29592 #else
29593  /* The fast way. */
29594  x = x * 32767.0f; /* -1..1 to -32767..32767 */
29595 #endif
29596 
29597  dst_s16[i] = (ma_int16)x;
29598  }
29599 }
29600 #else
29601 static MA_INLINE void ma_pcm_f32_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29602 {
29603  ma_uint64 i;
29604  ma_uint64 i4;
29605  ma_uint64 count4;
29606 
29607  ma_int16* dst_s16 = (ma_int16*)dst;
29608  const float* src_f32 = (const float*)src;
29609 
29610  float ditherMin = 0;
29611  float ditherMax = 0;
29612  if (ditherMode != ma_dither_mode_none) {
29613  ditherMin = 1.0f / -32768;
29614  ditherMax = 1.0f / 32767;
29615  }
29616 
29617  /* Unrolled. */
29618  i = 0;
29619  count4 = count >> 2;
29620  for (i4 = 0; i4 < count4; i4 += 1) {
29621  float d0 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
29622  float d1 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
29623  float d2 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
29624  float d3 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
29625 
29626  float x0 = src_f32[i+0];
29627  float x1 = src_f32[i+1];
29628  float x2 = src_f32[i+2];
29629  float x3 = src_f32[i+3];
29630 
29631  x0 = x0 + d0;
29632  x1 = x1 + d1;
29633  x2 = x2 + d2;
29634  x3 = x3 + d3;
29635 
29636  x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
29637  x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
29638  x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
29639  x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
29640 
29641  x0 = x0 * 32767.0f;
29642  x1 = x1 * 32767.0f;
29643  x2 = x2 * 32767.0f;
29644  x3 = x3 * 32767.0f;
29645 
29646  dst_s16[i+0] = (ma_int16)x0;
29647  dst_s16[i+1] = (ma_int16)x1;
29648  dst_s16[i+2] = (ma_int16)x2;
29649  dst_s16[i+3] = (ma_int16)x3;
29650 
29651  i += 4;
29652  }
29653 
29654  /* Leftover. */
29655  for (; i < count; i += 1) {
29656  float x = src_f32[i];
29657  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29658  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
29659  x = x * 32767.0f; /* -1..1 to -32767..32767 */
29660 
29661  dst_s16[i] = (ma_int16)x;
29662  }
29663 }
29664 
29665 #if defined(MA_SUPPORT_SSE2)
29666 static MA_INLINE void ma_pcm_f32_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29667 {
29668  ma_uint64 i;
29669  ma_uint64 i8;
29670  ma_uint64 count8;
29671  ma_int16* dst_s16;
29672  const float* src_f32;
29673  float ditherMin;
29674  float ditherMax;
29675 
29676  /* Both the input and output buffers need to be aligned to 16 bytes. */
29677  if ((((ma_uintptr)dst & 15) != 0) || (((ma_uintptr)src & 15) != 0)) {
29678  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
29679  return;
29680  }
29681 
29682  dst_s16 = (ma_int16*)dst;
29683  src_f32 = (const float*)src;
29684 
29685  ditherMin = 0;
29686  ditherMax = 0;
29687  if (ditherMode != ma_dither_mode_none) {
29688  ditherMin = 1.0f / -32768;
29689  ditherMax = 1.0f / 32767;
29690  }
29691 
29692  i = 0;
29693 
29694  /* SSE2. SSE allows us to output 8 s16's at a time which means our loop is unrolled 8 times. */
29695  count8 = count >> 3;
29696  for (i8 = 0; i8 < count8; i8 += 1) {
29697  __m128 d0;
29698  __m128 d1;
29699  __m128 x0;
29700  __m128 x1;
29701 
29702  if (ditherMode == ma_dither_mode_none) {
29703  d0 = _mm_set1_ps(0);
29704  d1 = _mm_set1_ps(0);
29705  } else if (ditherMode == ma_dither_mode_rectangle) {
29706  d0 = _mm_set_ps(
29707  ma_dither_f32_rectangle(ditherMin, ditherMax),
29708  ma_dither_f32_rectangle(ditherMin, ditherMax),
29709  ma_dither_f32_rectangle(ditherMin, ditherMax),
29710  ma_dither_f32_rectangle(ditherMin, ditherMax)
29711  );
29712  d1 = _mm_set_ps(
29713  ma_dither_f32_rectangle(ditherMin, ditherMax),
29714  ma_dither_f32_rectangle(ditherMin, ditherMax),
29715  ma_dither_f32_rectangle(ditherMin, ditherMax),
29716  ma_dither_f32_rectangle(ditherMin, ditherMax)
29717  );
29718  } else {
29719  d0 = _mm_set_ps(
29720  ma_dither_f32_triangle(ditherMin, ditherMax),
29721  ma_dither_f32_triangle(ditherMin, ditherMax),
29722  ma_dither_f32_triangle(ditherMin, ditherMax),
29723  ma_dither_f32_triangle(ditherMin, ditherMax)
29724  );
29725  d1 = _mm_set_ps(
29726  ma_dither_f32_triangle(ditherMin, ditherMax),
29727  ma_dither_f32_triangle(ditherMin, ditherMax),
29728  ma_dither_f32_triangle(ditherMin, ditherMax),
29729  ma_dither_f32_triangle(ditherMin, ditherMax)
29730  );
29731  }
29732 
29733  x0 = *((__m128*)(src_f32 + i) + 0);
29734  x1 = *((__m128*)(src_f32 + i) + 1);
29735 
29736  x0 = _mm_add_ps(x0, d0);
29737  x1 = _mm_add_ps(x1, d1);
29738 
29739  x0 = _mm_mul_ps(x0, _mm_set1_ps(32767.0f));
29740  x1 = _mm_mul_ps(x1, _mm_set1_ps(32767.0f));
29741 
29742  _mm_stream_si128(((__m128i*)(dst_s16 + i)), _mm_packs_epi32(_mm_cvttps_epi32(x0), _mm_cvttps_epi32(x1)));
29743 
29744  i += 8;
29745  }
29746 
29747 
29748  /* Leftover. */
29749  for (; i < count; i += 1) {
29750  float x = src_f32[i];
29751  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29752  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
29753  x = x * 32767.0f; /* -1..1 to -32767..32767 */
29754 
29755  dst_s16[i] = (ma_int16)x;
29756  }
29757 }
29758 #endif /* SSE2 */
29759 
29760 #if defined(MA_SUPPORT_AVX2)
29761 static MA_INLINE void ma_pcm_f32_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29762 {
29763  ma_uint64 i;
29764  ma_uint64 i16;
29765  ma_uint64 count16;
29766  ma_int16* dst_s16;
29767  const float* src_f32;
29768  float ditherMin;
29769  float ditherMax;
29770 
29771  /* Both the input and output buffers need to be aligned to 32 bytes. */
29772  if ((((ma_uintptr)dst & 31) != 0) || (((ma_uintptr)src & 31) != 0)) {
29773  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
29774  return;
29775  }
29776 
29777  dst_s16 = (ma_int16*)dst;
29778  src_f32 = (const float*)src;
29779 
29780  ditherMin = 0;
29781  ditherMax = 0;
29782  if (ditherMode != ma_dither_mode_none) {
29783  ditherMin = 1.0f / -32768;
29784  ditherMax = 1.0f / 32767;
29785  }
29786 
29787  i = 0;
29788 
29789  /* AVX2. AVX2 allows us to output 16 s16's at a time which means our loop is unrolled 16 times. */
29790  count16 = count >> 4;
29791  for (i16 = 0; i16 < count16; i16 += 1) {
29792  __m256 d0;
29793  __m256 d1;
29794  __m256 x0;
29795  __m256 x1;
29796  __m256i i0;
29797  __m256i i1;
29798  __m256i p0;
29799  __m256i p1;
29800  __m256i r;
29801 
29802  if (ditherMode == ma_dither_mode_none) {
29803  d0 = _mm256_set1_ps(0);
29804  d1 = _mm256_set1_ps(0);
29805  } else if (ditherMode == ma_dither_mode_rectangle) {
29806  d0 = _mm256_set_ps(
29807  ma_dither_f32_rectangle(ditherMin, ditherMax),
29808  ma_dither_f32_rectangle(ditherMin, ditherMax),
29809  ma_dither_f32_rectangle(ditherMin, ditherMax),
29810  ma_dither_f32_rectangle(ditherMin, ditherMax),
29811  ma_dither_f32_rectangle(ditherMin, ditherMax),
29812  ma_dither_f32_rectangle(ditherMin, ditherMax),
29813  ma_dither_f32_rectangle(ditherMin, ditherMax),
29814  ma_dither_f32_rectangle(ditherMin, ditherMax)
29815  );
29816  d1 = _mm256_set_ps(
29817  ma_dither_f32_rectangle(ditherMin, ditherMax),
29818  ma_dither_f32_rectangle(ditherMin, ditherMax),
29819  ma_dither_f32_rectangle(ditherMin, ditherMax),
29820  ma_dither_f32_rectangle(ditherMin, ditherMax),
29821  ma_dither_f32_rectangle(ditherMin, ditherMax),
29822  ma_dither_f32_rectangle(ditherMin, ditherMax),
29823  ma_dither_f32_rectangle(ditherMin, ditherMax),
29824  ma_dither_f32_rectangle(ditherMin, ditherMax)
29825  );
29826  } else {
29827  d0 = _mm256_set_ps(
29828  ma_dither_f32_triangle(ditherMin, ditherMax),
29829  ma_dither_f32_triangle(ditherMin, ditherMax),
29830  ma_dither_f32_triangle(ditherMin, ditherMax),
29831  ma_dither_f32_triangle(ditherMin, ditherMax),
29832  ma_dither_f32_triangle(ditherMin, ditherMax),
29833  ma_dither_f32_triangle(ditherMin, ditherMax),
29834  ma_dither_f32_triangle(ditherMin, ditherMax),
29835  ma_dither_f32_triangle(ditherMin, ditherMax)
29836  );
29837  d1 = _mm256_set_ps(
29838  ma_dither_f32_triangle(ditherMin, ditherMax),
29839  ma_dither_f32_triangle(ditherMin, ditherMax),
29840  ma_dither_f32_triangle(ditherMin, ditherMax),
29841  ma_dither_f32_triangle(ditherMin, ditherMax),
29842  ma_dither_f32_triangle(ditherMin, ditherMax),
29843  ma_dither_f32_triangle(ditherMin, ditherMax),
29844  ma_dither_f32_triangle(ditherMin, ditherMax),
29845  ma_dither_f32_triangle(ditherMin, ditherMax)
29846  );
29847  }
29848 
29849  x0 = *((__m256*)(src_f32 + i) + 0);
29850  x1 = *((__m256*)(src_f32 + i) + 1);
29851 
29852  x0 = _mm256_add_ps(x0, d0);
29853  x1 = _mm256_add_ps(x1, d1);
29854 
29855  x0 = _mm256_mul_ps(x0, _mm256_set1_ps(32767.0f));
29856  x1 = _mm256_mul_ps(x1, _mm256_set1_ps(32767.0f));
29857 
29858  /* Computing the final result is a little more complicated for AVX2 than SSE2. */
29859  i0 = _mm256_cvttps_epi32(x0);
29860  i1 = _mm256_cvttps_epi32(x1);
29861  p0 = _mm256_permute2x128_si256(i0, i1, 0 | 32);
29862  p1 = _mm256_permute2x128_si256(i0, i1, 1 | 48);
29863  r = _mm256_packs_epi32(p0, p1);
29864 
29865  _mm256_stream_si256(((__m256i*)(dst_s16 + i)), r);
29866 
29867  i += 16;
29868  }
29869 
29870 
29871  /* Leftover. */
29872  for (; i < count; i += 1) {
29873  float x = src_f32[i];
29874  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29875  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
29876  x = x * 32767.0f; /* -1..1 to -32767..32767 */
29877 
29878  dst_s16[i] = (ma_int16)x;
29879  }
29880 }
29881 #endif /* AVX2 */
29882 
29883 #if defined(MA_SUPPORT_NEON)
29884 static MA_INLINE void ma_pcm_f32_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29885 {
29886  ma_uint64 i;
29887  ma_uint64 i8;
29888  ma_uint64 count8;
29889  ma_int16* dst_s16;
29890  const float* src_f32;
29891  float ditherMin;
29892  float ditherMax;
29893 
29894  if (!ma_has_neon()) {
29895  return ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
29896  }
29897 
29898  /* Both the input and output buffers need to be aligned to 16 bytes. */
29899  if ((((ma_uintptr)dst & 15) != 0) || (((ma_uintptr)src & 15) != 0)) {
29900  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
29901  return;
29902  }
29903 
29904  dst_s16 = (ma_int16*)dst;
29905  src_f32 = (const float*)src;
29906 
29907  ditherMin = 0;
29908  ditherMax = 0;
29909  if (ditherMode != ma_dither_mode_none) {
29910  ditherMin = 1.0f / -32768;
29911  ditherMax = 1.0f / 32767;
29912  }
29913 
29914  i = 0;
29915 
29916  /* NEON. NEON allows us to output 8 s16's at a time which means our loop is unrolled 8 times. */
29917  count8 = count >> 3;
29918  for (i8 = 0; i8 < count8; i8 += 1) {
29919  float32x4_t d0;
29920  float32x4_t d1;
29921  float32x4_t x0;
29922  float32x4_t x1;
29923  int32x4_t i0;
29924  int32x4_t i1;
29925 
29926  if (ditherMode == ma_dither_mode_none) {
29927  d0 = vmovq_n_f32(0);
29928  d1 = vmovq_n_f32(0);
29929  } else if (ditherMode == ma_dither_mode_rectangle) {
29930  float d0v[4];
29931  d0v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29932  d0v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29933  d0v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29934  d0v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29935  d0 = vld1q_f32(d0v);
29936 
29937  float d1v[4];
29938  d1v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29939  d1v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29940  d1v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29941  d1v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29942  d1 = vld1q_f32(d1v);
29943  } else {
29944  float d0v[4];
29945  d0v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
29946  d0v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
29947  d0v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
29948  d0v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
29949  d0 = vld1q_f32(d0v);
29950 
29951  float d1v[4];
29952  d1v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
29953  d1v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
29954  d1v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
29955  d1v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
29956  d1 = vld1q_f32(d1v);
29957  }
29958 
29959  x0 = *((float32x4_t*)(src_f32 + i) + 0);
29960  x1 = *((float32x4_t*)(src_f32 + i) + 1);
29961 
29962  x0 = vaddq_f32(x0, d0);
29963  x1 = vaddq_f32(x1, d1);
29964 
29965  x0 = vmulq_n_f32(x0, 32767.0f);
29966  x1 = vmulq_n_f32(x1, 32767.0f);
29967 
29968  i0 = vcvtq_s32_f32(x0);
29969  i1 = vcvtq_s32_f32(x1);
29970  *((int16x8_t*)(dst_s16 + i)) = vcombine_s16(vqmovn_s32(i0), vqmovn_s32(i1));
29971 
29972  i += 8;
29973  }
29974 
29975 
29976  /* Leftover. */
29977  for (; i < count; i += 1) {
29978  float x = src_f32[i];
29979  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29980  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
29981  x = x * 32767.0f; /* -1..1 to -32767..32767 */
29982 
29983  dst_s16[i] = (ma_int16)x;
29984  }
29985 }
29986 #endif /* Neon */
29987 #endif /* MA_USE_REFERENCE_CONVERSION_APIS */
29988 
29989 MA_API void ma_pcm_f32_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
29990 {
29991 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29992  ma_pcm_f32_to_s16__reference(dst, src, count, ditherMode);
29993 #else
29994  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
29995  if (ma_has_avx2()) {
29996  ma_pcm_f32_to_s16__avx2(dst, src, count, ditherMode);
29997  } else
29998  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
29999  if (ma_has_sse2()) {
30000  ma_pcm_f32_to_s16__sse2(dst, src, count, ditherMode);
30001  } else
30002  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
30003  if (ma_has_neon()) {
30004  ma_pcm_f32_to_s16__neon(dst, src, count, ditherMode);
30005  } else
30006  #endif
30007  {
30008  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
30009  }
30010 #endif
30011 }
30012 
30013 
30014 static MA_INLINE void ma_pcm_f32_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30015 {
30016  ma_uint8* dst_s24 = (ma_uint8*)dst;
30017  const float* src_f32 = (const float*)src;
30018 
30019  ma_uint64 i;
30020  for (i = 0; i < count; i += 1) {
30021  ma_int32 r;
30022  float x = src_f32[i];
30023  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
30024 
30025 #if 0
30026  /* The accurate way. */
30027  x = x + 1; /* -1..1 to 0..2 */
30028  x = x * 8388607.5f; /* 0..2 to 0..16777215 */
30029  x = x - 8388608.0f; /* 0..16777215 to -8388608..8388607 */
30030 #else
30031  /* The fast way. */
30032  x = x * 8388607.0f; /* -1..1 to -8388607..8388607 */
30033 #endif
30034 
30035  r = (ma_int32)x;
30036  dst_s24[(i*3)+0] = (ma_uint8)((r & 0x0000FF) >> 0);
30037  dst_s24[(i*3)+1] = (ma_uint8)((r & 0x00FF00) >> 8);
30038  dst_s24[(i*3)+2] = (ma_uint8)((r & 0xFF0000) >> 16);
30039  }
30040 
30041  (void)ditherMode; /* No dithering for f32 -> s24. */
30042 }
30043 
30044 static MA_INLINE void ma_pcm_f32_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30045 {
30046  ma_pcm_f32_to_s24__reference(dst, src, count, ditherMode);
30047 }
30048 
30049 #if defined(MA_SUPPORT_SSE2)
30050 static MA_INLINE void ma_pcm_f32_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30051 {
30052  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
30053 }
30054 #endif
30055 #if defined(MA_SUPPORT_AVX2)
30056 static MA_INLINE void ma_pcm_f32_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30057 {
30058  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
30059 }
30060 #endif
30061 #if defined(MA_SUPPORT_NEON)
30062 static MA_INLINE void ma_pcm_f32_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30063 {
30064  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
30065 }
30066 #endif
30067 
30068 MA_API void ma_pcm_f32_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30069 {
30070 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
30071  ma_pcm_f32_to_s24__reference(dst, src, count, ditherMode);
30072 #else
30073  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
30074  if (ma_has_avx2()) {
30075  ma_pcm_f32_to_s24__avx2(dst, src, count, ditherMode);
30076  } else
30077  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
30078  if (ma_has_sse2()) {
30079  ma_pcm_f32_to_s24__sse2(dst, src, count, ditherMode);
30080  } else
30081  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
30082  if (ma_has_neon()) {
30083  ma_pcm_f32_to_s24__neon(dst, src, count, ditherMode);
30084  } else
30085  #endif
30086  {
30087  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
30088  }
30089 #endif
30090 }
30091 
30092 
30093 static MA_INLINE void ma_pcm_f32_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30094 {
30095  ma_int32* dst_s32 = (ma_int32*)dst;
30096  const float* src_f32 = (const float*)src;
30097 
30098  ma_uint32 i;
30099  for (i = 0; i < count; i += 1) {
30100  double x = src_f32[i];
30101  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
30102 
30103 #if 0
30104  /* The accurate way. */
30105  x = x + 1; /* -1..1 to 0..2 */
30106  x = x * 2147483647.5; /* 0..2 to 0..4294967295 */
30107  x = x - 2147483648.0; /* 0...4294967295 to -2147483648..2147483647 */
30108 #else
30109  /* The fast way. */
30110  x = x * 2147483647.0; /* -1..1 to -2147483647..2147483647 */
30111 #endif
30112 
30113  dst_s32[i] = (ma_int32)x;
30114  }
30115 
30116  (void)ditherMode; /* No dithering for f32 -> s32. */
30117 }
30118 
30119 static MA_INLINE void ma_pcm_f32_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30120 {
30121  ma_pcm_f32_to_s32__reference(dst, src, count, ditherMode);
30122 }
30123 
30124 #if defined(MA_SUPPORT_SSE2)
30125 static MA_INLINE void ma_pcm_f32_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30126 {
30127  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
30128 }
30129 #endif
30130 #if defined(MA_SUPPORT_AVX2)
30131 static MA_INLINE void ma_pcm_f32_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30132 {
30133  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
30134 }
30135 #endif
30136 #if defined(MA_SUPPORT_NEON)
30137 static MA_INLINE void ma_pcm_f32_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30138 {
30139  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
30140 }
30141 #endif
30142 
30143 MA_API void ma_pcm_f32_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30144 {
30145 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
30146  ma_pcm_f32_to_s32__reference(dst, src, count, ditherMode);
30147 #else
30148  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
30149  if (ma_has_avx2()) {
30150  ma_pcm_f32_to_s32__avx2(dst, src, count, ditherMode);
30151  } else
30152  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
30153  if (ma_has_sse2()) {
30154  ma_pcm_f32_to_s32__sse2(dst, src, count, ditherMode);
30155  } else
30156  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
30157  if (ma_has_neon()) {
30158  ma_pcm_f32_to_s32__neon(dst, src, count, ditherMode);
30159  } else
30160  #endif
30161  {
30162  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
30163  }
30164 #endif
30165 }
30166 
30167 
30168 MA_API void ma_pcm_f32_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
30169 {
30170  (void)ditherMode;
30171 
30172  ma_copy_memory_64(dst, src, count * sizeof(float));
30173 }
30174 
30175 
30176 static void ma_pcm_interleave_f32__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
30177 {
30178  float* dst_f32 = (float*)dst;
30179  const float** src_f32 = (const float**)src;
30180 
30181  ma_uint64 iFrame;
30182  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
30183  ma_uint32 iChannel;
30184  for (iChannel = 0; iChannel < channels; iChannel += 1) {
30185  dst_f32[iFrame*channels + iChannel] = src_f32[iChannel][iFrame];
30186  }
30187  }
30188 }
30189 
30190 static void ma_pcm_interleave_f32__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
30191 {
30192  ma_pcm_interleave_f32__reference(dst, src, frameCount, channels);
30193 }
30194 
30195 MA_API void ma_pcm_interleave_f32(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
30196 {
30197 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
30198  ma_pcm_interleave_f32__reference(dst, src, frameCount, channels);
30199 #else
30200  ma_pcm_interleave_f32__optimized(dst, src, frameCount, channels);
30201 #endif
30202 }
30203 
30204 
30205 static void ma_pcm_deinterleave_f32__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
30206 {
30207  float** dst_f32 = (float**)dst;
30208  const float* src_f32 = (const float*)src;
30209 
30210  ma_uint64 iFrame;
30211  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
30212  ma_uint32 iChannel;
30213  for (iChannel = 0; iChannel < channels; iChannel += 1) {
30214  dst_f32[iChannel][iFrame] = src_f32[iFrame*channels + iChannel];
30215  }
30216  }
30217 }
30218 
30219 static void ma_pcm_deinterleave_f32__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
30220 {
30221  ma_pcm_deinterleave_f32__reference(dst, src, frameCount, channels);
30222 }
30223 
30224 MA_API void ma_pcm_deinterleave_f32(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
30225 {
30226 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
30227  ma_pcm_deinterleave_f32__reference(dst, src, frameCount, channels);
30228 #else
30229  ma_pcm_deinterleave_f32__optimized(dst, src, frameCount, channels);
30230 #endif
30231 }
30232 
30233 
30234 MA_API void ma_pcm_convert(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode)
30235 {
30236  if (formatOut == formatIn) {
30237  ma_copy_memory_64(pOut, pIn, sampleCount * ma_get_bytes_per_sample(formatOut));
30238  return;
30239  }
30240 
30241  switch (formatIn)
30242  {
30243  case ma_format_u8:
30244  {
30245  switch (formatOut)
30246  {
30247  case ma_format_s16: ma_pcm_u8_to_s16(pOut, pIn, sampleCount, ditherMode); return;
30248  case ma_format_s24: ma_pcm_u8_to_s24(pOut, pIn, sampleCount, ditherMode); return;
30249  case ma_format_s32: ma_pcm_u8_to_s32(pOut, pIn, sampleCount, ditherMode); return;
30250  case ma_format_f32: ma_pcm_u8_to_f32(pOut, pIn, sampleCount, ditherMode); return;
30251  default: break;
30252  }
30253  } break;
30254 
30255  case ma_format_s16:
30256  {
30257  switch (formatOut)
30258  {
30259  case ma_format_u8: ma_pcm_s16_to_u8( pOut, pIn, sampleCount, ditherMode); return;
30260  case ma_format_s24: ma_pcm_s16_to_s24(pOut, pIn, sampleCount, ditherMode); return;
30261  case ma_format_s32: ma_pcm_s16_to_s32(pOut, pIn, sampleCount, ditherMode); return;
30262  case ma_format_f32: ma_pcm_s16_to_f32(pOut, pIn, sampleCount, ditherMode); return;
30263  default: break;
30264  }
30265  } break;
30266 
30267  case ma_format_s24:
30268  {
30269  switch (formatOut)
30270  {
30271  case ma_format_u8: ma_pcm_s24_to_u8( pOut, pIn, sampleCount, ditherMode); return;
30272  case ma_format_s16: ma_pcm_s24_to_s16(pOut, pIn, sampleCount, ditherMode); return;
30273  case ma_format_s32: ma_pcm_s24_to_s32(pOut, pIn, sampleCount, ditherMode); return;
30274  case ma_format_f32: ma_pcm_s24_to_f32(pOut, pIn, sampleCount, ditherMode); return;
30275  default: break;
30276  }
30277  } break;
30278 
30279  case ma_format_s32:
30280  {
30281  switch (formatOut)
30282  {
30283  case ma_format_u8: ma_pcm_s32_to_u8( pOut, pIn, sampleCount, ditherMode); return;
30284  case ma_format_s16: ma_pcm_s32_to_s16(pOut, pIn, sampleCount, ditherMode); return;
30285  case ma_format_s24: ma_pcm_s32_to_s24(pOut, pIn, sampleCount, ditherMode); return;
30286  case ma_format_f32: ma_pcm_s32_to_f32(pOut, pIn, sampleCount, ditherMode); return;
30287  default: break;
30288  }
30289  } break;
30290 
30291  case ma_format_f32:
30292  {
30293  switch (formatOut)
30294  {
30295  case ma_format_u8: ma_pcm_f32_to_u8( pOut, pIn, sampleCount, ditherMode); return;
30296  case ma_format_s16: ma_pcm_f32_to_s16(pOut, pIn, sampleCount, ditherMode); return;
30297  case ma_format_s24: ma_pcm_f32_to_s24(pOut, pIn, sampleCount, ditherMode); return;
30298  case ma_format_s32: ma_pcm_f32_to_s32(pOut, pIn, sampleCount, ditherMode); return;
30299  default: break;
30300  }
30301  } break;
30302 
30303  default: break;
30304  }
30305 }
30306 
30307 MA_API void ma_convert_pcm_frames_format(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 frameCount, ma_uint32 channels, ma_dither_mode ditherMode)
30308 {
30309  ma_pcm_convert(pOut, formatOut, pIn, formatIn, frameCount * channels, ditherMode);
30310 }
30311 
30312 MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void* pInterleavedPCMFrames, void** ppDeinterleavedPCMFrames)
30313 {
30314  if (pInterleavedPCMFrames == NULL || ppDeinterleavedPCMFrames == NULL) {
30315  return; /* Invalid args. */
30316  }
30317 
30318  /* For efficiency we do this per format. */
30319  switch (format) {
30320  case ma_format_s16:
30321  {
30322  const ma_int16* pSrcS16 = (const ma_int16*)pInterleavedPCMFrames;
30323  ma_uint64 iPCMFrame;
30324  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
30325  ma_uint32 iChannel;
30326  for (iChannel = 0; iChannel < channels; ++iChannel) {
30327  ma_int16* pDstS16 = (ma_int16*)ppDeinterleavedPCMFrames[iChannel];
30328  pDstS16[iPCMFrame] = pSrcS16[iPCMFrame*channels+iChannel];
30329  }
30330  }
30331  } break;
30332 
30333  case ma_format_f32:
30334  {
30335  const float* pSrcF32 = (const float*)pInterleavedPCMFrames;
30336  ma_uint64 iPCMFrame;
30337  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
30338  ma_uint32 iChannel;
30339  for (iChannel = 0; iChannel < channels; ++iChannel) {
30340  float* pDstF32 = (float*)ppDeinterleavedPCMFrames[iChannel];
30341  pDstF32[iPCMFrame] = pSrcF32[iPCMFrame*channels+iChannel];
30342  }
30343  }
30344  } break;
30345 
30346  default:
30347  {
30348  ma_uint32 sampleSizeInBytes = ma_get_bytes_per_sample(format);
30349  ma_uint64 iPCMFrame;
30350  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
30351  ma_uint32 iChannel;
30352  for (iChannel = 0; iChannel < channels; ++iChannel) {
30353  void* pDst = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
30354  const void* pSrc = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*channels+iChannel)*sampleSizeInBytes);
30355  memcpy(pDst, pSrc, sampleSizeInBytes);
30356  }
30357  }
30358  } break;
30359  }
30360 }
30361 
30362 MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void** ppDeinterleavedPCMFrames, void* pInterleavedPCMFrames)
30363 {
30364  switch (format)
30365  {
30366  case ma_format_s16:
30367  {
30368  ma_int16* pDstS16 = (ma_int16*)pInterleavedPCMFrames;
30369  ma_uint64 iPCMFrame;
30370  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
30371  ma_uint32 iChannel;
30372  for (iChannel = 0; iChannel < channels; ++iChannel) {
30373  const ma_int16* pSrcS16 = (const ma_int16*)ppDeinterleavedPCMFrames[iChannel];
30374  pDstS16[iPCMFrame*channels+iChannel] = pSrcS16[iPCMFrame];
30375  }
30376  }
30377  } break;
30378 
30379  case ma_format_f32:
30380  {
30381  float* pDstF32 = (float*)pInterleavedPCMFrames;
30382  ma_uint64 iPCMFrame;
30383  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
30384  ma_uint32 iChannel;
30385  for (iChannel = 0; iChannel < channels; ++iChannel) {
30386  const float* pSrcF32 = (const float*)ppDeinterleavedPCMFrames[iChannel];
30387  pDstF32[iPCMFrame*channels+iChannel] = pSrcF32[iPCMFrame];
30388  }
30389  }
30390  } break;
30391 
30392  default:
30393  {
30394  ma_uint32 sampleSizeInBytes = ma_get_bytes_per_sample(format);
30395  ma_uint64 iPCMFrame;
30396  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
30397  ma_uint32 iChannel;
30398  for (iChannel = 0; iChannel < channels; ++iChannel) {
30399  void* pDst = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*channels+iChannel)*sampleSizeInBytes);
30400  const void* pSrc = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
30401  memcpy(pDst, pSrc, sampleSizeInBytes);
30402  }
30403  }
30404  } break;
30405  }
30406 }
30407 
30408 
30409 /**************************************************************************************************************************************************************
30410 
30411 Biquad Filter
30412 
30413 **************************************************************************************************************************************************************/
30414 #ifndef MA_BIQUAD_FIXED_POINT_SHIFT
30415 #define MA_BIQUAD_FIXED_POINT_SHIFT 14
30416 #endif
30417 
30419 {
30420  return (ma_int32)(x * (1 << MA_BIQUAD_FIXED_POINT_SHIFT));
30421 }
30422 
30423 MA_API ma_biquad_config ma_biquad_config_init(ma_format format, ma_uint32 channels, double b0, double b1, double b2, double a0, double a1, double a2)
30424 {
30426 
30428  config.format = format;
30429  config.channels = channels;
30430  config.b0 = b0;
30431  config.b1 = b1;
30432  config.b2 = b2;
30433  config.a0 = a0;
30434  config.a1 = a1;
30435  config.a2 = a2;
30436 
30437  return config;
30438 }
30439 
30441 {
30442  if (pBQ == NULL) {
30443  return MA_INVALID_ARGS;
30444  }
30445 
30446  MA_ZERO_OBJECT(pBQ);
30447 
30448  if (pConfig == NULL) {
30449  return MA_INVALID_ARGS;
30450  }
30451 
30452  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
30453  return MA_INVALID_ARGS;
30454  }
30455 
30456  return ma_biquad_reinit(pConfig, pBQ);
30457 }
30458 
30460 {
30461  if (pBQ == NULL || pConfig == NULL) {
30462  return MA_INVALID_ARGS;
30463  }
30464 
30465  if (pConfig->a0 == 0) {
30466  return MA_INVALID_ARGS; /* Division by zero. */
30467  }
30468 
30469  /* Only supporting f32 and s16. */
30470  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
30471  return MA_INVALID_ARGS;
30472  }
30473 
30474  /* The format cannot be changed after initialization. */
30475  if (pBQ->format != ma_format_unknown && pBQ->format != pConfig->format) {
30476  return MA_INVALID_OPERATION;
30477  }
30478 
30479  /* The channel count cannot be changed after initialization. */
30480  if (pBQ->channels != 0 && pBQ->channels != pConfig->channels) {
30481  return MA_INVALID_OPERATION;
30482  }
30483 
30484 
30485  pBQ->format = pConfig->format;
30486  pBQ->channels = pConfig->channels;
30487 
30488  /* Normalize. */
30489  if (pConfig->format == ma_format_f32) {
30490  pBQ->b0.f32 = (float)(pConfig->b0 / pConfig->a0);
30491  pBQ->b1.f32 = (float)(pConfig->b1 / pConfig->a0);
30492  pBQ->b2.f32 = (float)(pConfig->b2 / pConfig->a0);
30493  pBQ->a1.f32 = (float)(pConfig->a1 / pConfig->a0);
30494  pBQ->a2.f32 = (float)(pConfig->a2 / pConfig->a0);
30495  } else {
30496  pBQ->b0.s32 = ma_biquad_float_to_fp(pConfig->b0 / pConfig->a0);
30497  pBQ->b1.s32 = ma_biquad_float_to_fp(pConfig->b1 / pConfig->a0);
30498  pBQ->b2.s32 = ma_biquad_float_to_fp(pConfig->b2 / pConfig->a0);
30499  pBQ->a1.s32 = ma_biquad_float_to_fp(pConfig->a1 / pConfig->a0);
30500  pBQ->a2.s32 = ma_biquad_float_to_fp(pConfig->a2 / pConfig->a0);
30501  }
30502 
30503  return MA_SUCCESS;
30504 }
30505 
30507 {
30508  ma_uint32 c;
30509  const ma_uint32 channels = pBQ->channels;
30510  const float b0 = pBQ->b0.f32;
30511  const float b1 = pBQ->b1.f32;
30512  const float b2 = pBQ->b2.f32;
30513  const float a1 = pBQ->a1.f32;
30514  const float a2 = pBQ->a2.f32;
30515 
30516  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
30517  for (c = 0; c < channels; c += 1) {
30518  float r1 = pBQ->r1[c].f32;
30519  float r2 = pBQ->r2[c].f32;
30520  float x = pX[c];
30521  float y;
30522 
30523  y = b0*x + r1;
30524  r1 = b1*x - a1*y + r2;
30525  r2 = b2*x - a2*y;
30526 
30527  pY[c] = y;
30528  pBQ->r1[c].f32 = r1;
30529  pBQ->r2[c].f32 = r2;
30530  }
30531 }
30532 
30533 static MA_INLINE void ma_biquad_process_pcm_frame_f32(ma_biquad* pBQ, float* pY, const float* pX)
30534 {
30536 }
30537 
30539 {
30540  ma_uint32 c;
30541  const ma_uint32 channels = pBQ->channels;
30542  const ma_int32 b0 = pBQ->b0.s32;
30543  const ma_int32 b1 = pBQ->b1.s32;
30544  const ma_int32 b2 = pBQ->b2.s32;
30545  const ma_int32 a1 = pBQ->a1.s32;
30546  const ma_int32 a2 = pBQ->a2.s32;
30547 
30548  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
30549  for (c = 0; c < channels; c += 1) {
30550  ma_int32 r1 = pBQ->r1[c].s32;
30551  ma_int32 r2 = pBQ->r2[c].s32;
30552  ma_int32 x = pX[c];
30553  ma_int32 y;
30554 
30555  y = (b0*x + r1) >> MA_BIQUAD_FIXED_POINT_SHIFT;
30556  r1 = (b1*x - a1*y + r2);
30557  r2 = (b2*x - a2*y);
30558 
30559  pY[c] = (ma_int16)ma_clamp(y, -32768, 32767);
30560  pBQ->r1[c].s32 = r1;
30561  pBQ->r2[c].s32 = r2;
30562  }
30563 }
30564 
30566 {
30568 }
30569 
30570 MA_API ma_result ma_biquad_process_pcm_frames(ma_biquad* pBQ, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
30571 {
30572  ma_uint32 n;
30573 
30574  if (pBQ == NULL || pFramesOut == NULL || pFramesIn == NULL) {
30575  return MA_INVALID_ARGS;
30576  }
30577 
30578  /* Note that the logic below needs to support in-place filtering. That is, it must support the case where pFramesOut and pFramesIn are the same. */
30579 
30580  if (pBQ->format == ma_format_f32) {
30581  /* */ float* pY = ( float*)pFramesOut;
30582  const float* pX = (const float*)pFramesIn;
30583 
30584  for (n = 0; n < frameCount; n += 1) {
30586  pY += pBQ->channels;
30587  pX += pBQ->channels;
30588  }
30589  } else if (pBQ->format == ma_format_s16) {
30590  /* */ ma_int16* pY = ( ma_int16*)pFramesOut;
30591  const ma_int16* pX = (const ma_int16*)pFramesIn;
30592 
30593  for (n = 0; n < frameCount; n += 1) {
30595  pY += pBQ->channels;
30596  pX += pBQ->channels;
30597  }
30598  } else {
30600  return MA_INVALID_ARGS; /* Format not supported. Should never hit this because it's checked in ma_biquad_init() and ma_biquad_reinit(). */
30601  }
30602 
30603  return MA_SUCCESS;
30604 }
30605 
30607 {
30608  if (pBQ == NULL) {
30609  return 0;
30610  }
30611 
30612  return 2;
30613 }
30614 
30615 
30616 /**************************************************************************************************************************************************************
30617 
30618 Low-Pass Filter
30619 
30620 **************************************************************************************************************************************************************/
30621 MA_API ma_lpf1_config ma_lpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency)
30622 {
30624 
30626  config.format = format;
30627  config.channels = channels;
30628  config.sampleRate = sampleRate;
30629  config.cutoffFrequency = cutoffFrequency;
30630  config.q = 0.5;
30631 
30632  return config;
30633 }
30634 
30635 MA_API ma_lpf2_config ma_lpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
30636 {
30638 
30640  config.format = format;
30641  config.channels = channels;
30642  config.sampleRate = sampleRate;
30643  config.cutoffFrequency = cutoffFrequency;
30644  config.q = q;
30645 
30646  /* Q cannot be 0 or else it'll result in a division by 0. In this case just default to 0.707107. */
30647  if (config.q == 0) {
30648  config.q = 0.707107;
30649  }
30650 
30651  return config;
30652 }
30653 
30654 
30656 {
30657  if (pLPF == NULL) {
30658  return MA_INVALID_ARGS;
30659  }
30660 
30661  MA_ZERO_OBJECT(pLPF);
30662 
30663  if (pConfig == NULL) {
30664  return MA_INVALID_ARGS;
30665  }
30666 
30667  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
30668  return MA_INVALID_ARGS;
30669  }
30670 
30671  return ma_lpf1_reinit(pConfig, pLPF);
30672 }
30673 
30675 {
30676  double a;
30677 
30678  if (pLPF == NULL || pConfig == NULL) {
30679  return MA_INVALID_ARGS;
30680  }
30681 
30682  /* Only supporting f32 and s16. */
30683  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
30684  return MA_INVALID_ARGS;
30685  }
30686 
30687  /* The format cannot be changed after initialization. */
30688  if (pLPF->format != ma_format_unknown && pLPF->format != pConfig->format) {
30689  return MA_INVALID_OPERATION;
30690  }
30691 
30692  /* The channel count cannot be changed after initialization. */
30693  if (pLPF->channels != 0 && pLPF->channels != pConfig->channels) {
30694  return MA_INVALID_OPERATION;
30695  }
30696 
30697  pLPF->format = pConfig->format;
30698  pLPF->channels = pConfig->channels;
30699 
30700  a = ma_expd(-2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate);
30701  if (pConfig->format == ma_format_f32) {
30702  pLPF->a.f32 = (float)a;
30703  } else {
30704  pLPF->a.s32 = ma_biquad_float_to_fp(a);
30705  }
30706 
30707  return MA_SUCCESS;
30708 }
30709 
30710 static MA_INLINE void ma_lpf1_process_pcm_frame_f32(ma_lpf1* pLPF, float* pY, const float* pX)
30711 {
30712  ma_uint32 c;
30713  const ma_uint32 channels = pLPF->channels;
30714  const float a = pLPF->a.f32;
30715  const float b = 1 - a;
30716 
30717  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
30718  for (c = 0; c < channels; c += 1) {
30719  float r1 = pLPF->r1[c].f32;
30720  float x = pX[c];
30721  float y;
30722 
30723  y = b*x + a*r1;
30724 
30725  pY[c] = y;
30726  pLPF->r1[c].f32 = y;
30727  }
30728 }
30729 
30731 {
30732  ma_uint32 c;
30733  const ma_uint32 channels = pLPF->channels;
30734  const ma_int32 a = pLPF->a.s32;
30735  const ma_int32 b = ((1 << MA_BIQUAD_FIXED_POINT_SHIFT) - a);
30736 
30737  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
30738  for (c = 0; c < channels; c += 1) {
30739  ma_int32 r1 = pLPF->r1[c].s32;
30740  ma_int32 x = pX[c];
30741  ma_int32 y;
30742 
30743  y = (b*x + a*r1) >> MA_BIQUAD_FIXED_POINT_SHIFT;
30744 
30745  pY[c] = (ma_int16)y;
30746  pLPF->r1[c].s32 = (ma_int32)y;
30747  }
30748 }
30749 
30750 MA_API ma_result ma_lpf1_process_pcm_frames(ma_lpf1* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
30751 {
30752  ma_uint32 n;
30753 
30754  if (pLPF == NULL || pFramesOut == NULL || pFramesIn == NULL) {
30755  return MA_INVALID_ARGS;
30756  }
30757 
30758  /* Note that the logic below needs to support in-place filtering. That is, it must support the case where pFramesOut and pFramesIn are the same. */
30759 
30760  if (pLPF->format == ma_format_f32) {
30761  /* */ float* pY = ( float*)pFramesOut;
30762  const float* pX = (const float*)pFramesIn;
30763 
30764  for (n = 0; n < frameCount; n += 1) {
30765  ma_lpf1_process_pcm_frame_f32(pLPF, pY, pX);
30766  pY += pLPF->channels;
30767  pX += pLPF->channels;
30768  }
30769  } else if (pLPF->format == ma_format_s16) {
30770  /* */ ma_int16* pY = ( ma_int16*)pFramesOut;
30771  const ma_int16* pX = (const ma_int16*)pFramesIn;
30772 
30773  for (n = 0; n < frameCount; n += 1) {
30774  ma_lpf1_process_pcm_frame_s16(pLPF, pY, pX);
30775  pY += pLPF->channels;
30776  pX += pLPF->channels;
30777  }
30778  } else {
30780  return MA_INVALID_ARGS; /* Format not supported. Should never hit this because it's checked in ma_biquad_init() and ma_biquad_reinit(). */
30781  }
30782 
30783  return MA_SUCCESS;
30784 }
30785 
30787 {
30788  if (pLPF == NULL) {
30789  return 0;
30790  }
30791 
30792  return 1;
30793 }
30794 
30795 
30797 {
30798  ma_biquad_config bqConfig;
30799  double q;
30800  double w;
30801  double s;
30802  double c;
30803  double a;
30804 
30805  MA_ASSERT(pConfig != NULL);
30806 
30807  q = pConfig->q;
30808  w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
30809  s = ma_sind(w);
30810  c = ma_cosd(w);
30811  a = s / (2*q);
30812 
30813  bqConfig.b0 = (1 - c) / 2;
30814  bqConfig.b1 = 1 - c;
30815  bqConfig.b2 = (1 - c) / 2;
30816  bqConfig.a0 = 1 + a;
30817  bqConfig.a1 = -2 * c;
30818  bqConfig.a2 = 1 - a;
30819 
30820  bqConfig.format = pConfig->format;
30821  bqConfig.channels = pConfig->channels;
30822 
30823  return bqConfig;
30824 }
30825 
30827 {
30828  ma_result result;
30829  ma_biquad_config bqConfig;
30830 
30831  if (pLPF == NULL) {
30832  return MA_INVALID_ARGS;
30833  }
30834 
30835  MA_ZERO_OBJECT(pLPF);
30836 
30837  if (pConfig == NULL) {
30838  return MA_INVALID_ARGS;
30839  }
30840 
30841  bqConfig = ma_lpf2__get_biquad_config(pConfig);
30842  result = ma_biquad_init(&bqConfig, &pLPF->bq);
30843  if (result != MA_SUCCESS) {
30844  return result;
30845  }
30846 
30847  return MA_SUCCESS;
30848 }
30849 
30851 {
30852  ma_result result;
30853  ma_biquad_config bqConfig;
30854 
30855  if (pLPF == NULL || pConfig == NULL) {
30856  return MA_INVALID_ARGS;
30857  }
30858 
30859  bqConfig = ma_lpf2__get_biquad_config(pConfig);
30860  result = ma_biquad_reinit(&bqConfig, &pLPF->bq);
30861  if (result != MA_SUCCESS) {
30862  return result;
30863  }
30864 
30865  return MA_SUCCESS;
30866 }
30867 
30868 static MA_INLINE void ma_lpf2_process_pcm_frame_s16(ma_lpf2* pLPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
30869 {
30870  ma_biquad_process_pcm_frame_s16(&pLPF->bq, pFrameOut, pFrameIn);
30871 }
30872 
30873 static MA_INLINE void ma_lpf2_process_pcm_frame_f32(ma_lpf2* pLPF, float* pFrameOut, const float* pFrameIn)
30874 {
30875  ma_biquad_process_pcm_frame_f32(&pLPF->bq, pFrameOut, pFrameIn);
30876 }
30877 
30878 MA_API ma_result ma_lpf2_process_pcm_frames(ma_lpf2* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
30879 {
30880  if (pLPF == NULL) {
30881  return MA_INVALID_ARGS;
30882  }
30883 
30884  return ma_biquad_process_pcm_frames(&pLPF->bq, pFramesOut, pFramesIn, frameCount);
30885 }
30886 
30888 {
30889  if (pLPF == NULL) {
30890  return 0;
30891  }
30892 
30893  return ma_biquad_get_latency(&pLPF->bq);
30894 }
30895 
30896 
30897 MA_API ma_lpf_config ma_lpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
30898 {
30900 
30902  config.format = format;
30903  config.channels = channels;
30904  config.sampleRate = sampleRate;
30905  config.cutoffFrequency = cutoffFrequency;
30906  config.order = ma_min(order, MA_MAX_FILTER_ORDER);
30907 
30908  return config;
30909 }
30910 
30912 {
30913  ma_result result;
30914  ma_uint32 lpf1Count;
30915  ma_uint32 lpf2Count;
30916  ma_uint32 ilpf1;
30917  ma_uint32 ilpf2;
30918 
30919  if (pLPF == NULL || pConfig == NULL) {
30920  return MA_INVALID_ARGS;
30921  }
30922 
30923  /* Only supporting f32 and s16. */
30924  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
30925  return MA_INVALID_ARGS;
30926  }
30927 
30928  /* The format cannot be changed after initialization. */
30929  if (pLPF->format != ma_format_unknown && pLPF->format != pConfig->format) {
30930  return MA_INVALID_OPERATION;
30931  }
30932 
30933  /* The channel count cannot be changed after initialization. */
30934  if (pLPF->channels != 0 && pLPF->channels != pConfig->channels) {
30935  return MA_INVALID_OPERATION;
30936  }
30937 
30938  if (pConfig->order > MA_MAX_FILTER_ORDER) {
30939  return MA_INVALID_ARGS;
30940  }
30941 
30942  lpf1Count = pConfig->order % 2;
30943  lpf2Count = pConfig->order / 2;
30944 
30945  MA_ASSERT(lpf1Count <= ma_countof(pLPF->lpf1));
30946  MA_ASSERT(lpf2Count <= ma_countof(pLPF->lpf2));
30947 
30948  /* The filter order can't change between reinits. */
30949  if (!isNew) {
30950  if (pLPF->lpf1Count != lpf1Count || pLPF->lpf2Count != lpf2Count) {
30951  return MA_INVALID_OPERATION;
30952  }
30953  }
30954 
30955  for (ilpf1 = 0; ilpf1 < lpf1Count; ilpf1 += 1) {
30956  ma_lpf1_config lpf1Config = ma_lpf1_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency);
30957 
30958  if (isNew) {
30959  result = ma_lpf1_init(&lpf1Config, &pLPF->lpf1[ilpf1]);
30960  } else {
30961  result = ma_lpf1_reinit(&lpf1Config, &pLPF->lpf1[ilpf1]);
30962  }
30963 
30964  if (result != MA_SUCCESS) {
30965  return result;
30966  }
30967  }
30968 
30969  for (ilpf2 = 0; ilpf2 < lpf2Count; ilpf2 += 1) {
30970  ma_lpf2_config lpf2Config;
30971  double q;
30972  double a;
30973 
30974  /* Tempting to use 0.707107, but won't result in a Butterworth filter if the order is > 2. */
30975  if (lpf1Count == 1) {
30976  a = (1 + ilpf2*1) * (MA_PI_D/(pConfig->order*1)); /* Odd order. */
30977  } else {
30978  a = (1 + ilpf2*2) * (MA_PI_D/(pConfig->order*2)); /* Even order. */
30979  }
30980  q = 1 / (2*ma_cosd(a));
30981 
30982  lpf2Config = ma_lpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
30983 
30984  if (isNew) {
30985  result = ma_lpf2_init(&lpf2Config, &pLPF->lpf2[ilpf2]);
30986  } else {
30987  result = ma_lpf2_reinit(&lpf2Config, &pLPF->lpf2[ilpf2]);
30988  }
30989 
30990  if (result != MA_SUCCESS) {
30991  return result;
30992  }
30993  }
30994 
30995  pLPF->lpf1Count = lpf1Count;
30996  pLPF->lpf2Count = lpf2Count;
30997  pLPF->format = pConfig->format;
30998  pLPF->channels = pConfig->channels;
30999  pLPF->sampleRate = pConfig->sampleRate;
31000 
31001  return MA_SUCCESS;
31002 }
31003 
31005 {
31006  if (pLPF == NULL) {
31007  return MA_INVALID_ARGS;
31008  }
31009 
31010  MA_ZERO_OBJECT(pLPF);
31011 
31012  if (pConfig == NULL) {
31013  return MA_INVALID_ARGS;
31014  }
31015 
31016  return ma_lpf_reinit__internal(pConfig, pLPF, /*isNew*/MA_TRUE);
31017 }
31018 
31020 {
31021  return ma_lpf_reinit__internal(pConfig, pLPF, /*isNew*/MA_FALSE);
31022 }
31023 
31024 static MA_INLINE void ma_lpf_process_pcm_frame_f32(ma_lpf* pLPF, float* pY, const void* pX)
31025 {
31026  ma_uint32 ilpf1;
31027  ma_uint32 ilpf2;
31028 
31029  MA_ASSERT(pLPF->format == ma_format_f32);
31030 
31031  MA_COPY_MEMORY(pY, pX, ma_get_bytes_per_frame(pLPF->format, pLPF->channels));
31032 
31033  for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
31034  ma_lpf1_process_pcm_frame_f32(&pLPF->lpf1[ilpf1], pY, pY);
31035  }
31036 
31037  for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
31038  ma_lpf2_process_pcm_frame_f32(&pLPF->lpf2[ilpf2], pY, pY);
31039  }
31040 }
31041 
31043 {
31044  ma_uint32 ilpf1;
31045  ma_uint32 ilpf2;
31046 
31047  MA_ASSERT(pLPF->format == ma_format_s16);
31048 
31049  MA_COPY_MEMORY(pY, pX, ma_get_bytes_per_frame(pLPF->format, pLPF->channels));
31050 
31051  for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
31052  ma_lpf1_process_pcm_frame_s16(&pLPF->lpf1[ilpf1], pY, pY);
31053  }
31054 
31055  for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
31056  ma_lpf2_process_pcm_frame_s16(&pLPF->lpf2[ilpf2], pY, pY);
31057  }
31058 }
31059 
31060 MA_API ma_result ma_lpf_process_pcm_frames(ma_lpf* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
31061 {
31062  ma_result result;
31063  ma_uint32 ilpf1;
31064  ma_uint32 ilpf2;
31065 
31066  if (pLPF == NULL) {
31067  return MA_INVALID_ARGS;
31068  }
31069 
31070  /* Faster path for in-place. */
31071  if (pFramesOut == pFramesIn) {
31072  for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
31073  result = ma_lpf1_process_pcm_frames(&pLPF->lpf1[ilpf1], pFramesOut, pFramesOut, frameCount);
31074  if (result != MA_SUCCESS) {
31075  return result;
31076  }
31077  }
31078 
31079  for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
31080  result = ma_lpf2_process_pcm_frames(&pLPF->lpf2[ilpf2], pFramesOut, pFramesOut, frameCount);
31081  if (result != MA_SUCCESS) {
31082  return result;
31083  }
31084  }
31085  }
31086 
31087  /* Slightly slower path for copying. */
31088  if (pFramesOut != pFramesIn) {
31089  ma_uint32 iFrame;
31090 
31091  /* */ if (pLPF->format == ma_format_f32) {
31092  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
31093  const float* pFramesInF32 = (const float*)pFramesIn;
31094 
31095  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
31096  ma_lpf_process_pcm_frame_f32(pLPF, pFramesOutF32, pFramesInF32);
31097  pFramesOutF32 += pLPF->channels;
31098  pFramesInF32 += pLPF->channels;
31099  }
31100  } else if (pLPF->format == ma_format_s16) {
31101  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
31102  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
31103 
31104  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
31105  ma_lpf_process_pcm_frame_s16(pLPF, pFramesOutS16, pFramesInS16);
31106  pFramesOutS16 += pLPF->channels;
31107  pFramesInS16 += pLPF->channels;
31108  }
31109  } else {
31111  return MA_INVALID_OPERATION; /* Should never hit this. */
31112  }
31113  }
31114 
31115  return MA_SUCCESS;
31116 }
31117 
31119 {
31120  if (pLPF == NULL) {
31121  return 0;
31122  }
31123 
31124  return pLPF->lpf2Count*2 + pLPF->lpf1Count;
31125 }
31126 
31127 
31128 /**************************************************************************************************************************************************************
31129 
31130 High-Pass Filtering
31131 
31132 **************************************************************************************************************************************************************/
31133 MA_API ma_hpf1_config ma_hpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency)
31134 {
31136 
31138  config.format = format;
31139  config.channels = channels;
31140  config.sampleRate = sampleRate;
31141  config.cutoffFrequency = cutoffFrequency;
31142 
31143  return config;
31144 }
31145 
31146 MA_API ma_hpf2_config ma_hpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
31147 {
31149 
31151  config.format = format;
31152  config.channels = channels;
31153  config.sampleRate = sampleRate;
31154  config.cutoffFrequency = cutoffFrequency;
31155  config.q = q;
31156 
31157  /* Q cannot be 0 or else it'll result in a division by 0. In this case just default to 0.707107. */
31158  if (config.q == 0) {
31159  config.q = 0.707107;
31160  }
31161 
31162  return config;
31163 }
31164 
31165 
31167 {
31168  if (pHPF == NULL) {
31169  return MA_INVALID_ARGS;
31170  }
31171 
31172  MA_ZERO_OBJECT(pHPF);
31173 
31174  if (pConfig == NULL) {
31175  return MA_INVALID_ARGS;
31176  }
31177 
31178  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
31179  return MA_INVALID_ARGS;
31180  }
31181 
31182  return ma_hpf1_reinit(pConfig, pHPF);
31183 }
31184 
31186 {
31187  double a;
31188 
31189  if (pHPF == NULL || pConfig == NULL) {
31190  return MA_INVALID_ARGS;
31191  }
31192 
31193  /* Only supporting f32 and s16. */
31194  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
31195  return MA_INVALID_ARGS;
31196  }
31197 
31198  /* The format cannot be changed after initialization. */
31199  if (pHPF->format != ma_format_unknown && pHPF->format != pConfig->format) {
31200  return MA_INVALID_OPERATION;
31201  }
31202 
31203  /* The channel count cannot be changed after initialization. */
31204  if (pHPF->channels != 0 && pHPF->channels != pConfig->channels) {
31205  return MA_INVALID_OPERATION;
31206  }
31207 
31208  pHPF->format = pConfig->format;
31209  pHPF->channels = pConfig->channels;
31210 
31211  a = ma_expd(-2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate);
31212  if (pConfig->format == ma_format_f32) {
31213  pHPF->a.f32 = (float)a;
31214  } else {
31215  pHPF->a.s32 = ma_biquad_float_to_fp(a);
31216  }
31217 
31218  return MA_SUCCESS;
31219 }
31220 
31221 static MA_INLINE void ma_hpf1_process_pcm_frame_f32(ma_hpf1* pHPF, float* pY, const float* pX)
31222 {
31223  ma_uint32 c;
31224  const ma_uint32 channels = pHPF->channels;
31225  const float a = 1 - pHPF->a.f32;
31226  const float b = 1 - a;
31227 
31228  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
31229  for (c = 0; c < channels; c += 1) {
31230  float r1 = pHPF->r1[c].f32;
31231  float x = pX[c];
31232  float y;
31233 
31234  y = b*x - a*r1;
31235 
31236  pY[c] = y;
31237  pHPF->r1[c].f32 = y;
31238  }
31239 }
31240 
31242 {
31243  ma_uint32 c;
31244  const ma_uint32 channels = pHPF->channels;
31245  const ma_int32 a = ((1 << MA_BIQUAD_FIXED_POINT_SHIFT) - pHPF->a.s32);
31246  const ma_int32 b = ((1 << MA_BIQUAD_FIXED_POINT_SHIFT) - a);
31247 
31248  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
31249  for (c = 0; c < channels; c += 1) {
31250  ma_int32 r1 = pHPF->r1[c].s32;
31251  ma_int32 x = pX[c];
31252  ma_int32 y;
31253 
31254  y = (b*x - a*r1) >> MA_BIQUAD_FIXED_POINT_SHIFT;
31255 
31256  pY[c] = (ma_int16)y;
31257  pHPF->r1[c].s32 = (ma_int32)y;
31258  }
31259 }
31260 
31261 MA_API ma_result ma_hpf1_process_pcm_frames(ma_hpf1* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
31262 {
31263  ma_uint32 n;
31264 
31265  if (pHPF == NULL || pFramesOut == NULL || pFramesIn == NULL) {
31266  return MA_INVALID_ARGS;
31267  }
31268 
31269  /* Note that the logic below needs to support in-place filtering. That is, it must support the case where pFramesOut and pFramesIn are the same. */
31270 
31271  if (pHPF->format == ma_format_f32) {
31272  /* */ float* pY = ( float*)pFramesOut;
31273  const float* pX = (const float*)pFramesIn;
31274 
31275  for (n = 0; n < frameCount; n += 1) {
31276  ma_hpf1_process_pcm_frame_f32(pHPF, pY, pX);
31277  pY += pHPF->channels;
31278  pX += pHPF->channels;
31279  }
31280  } else if (pHPF->format == ma_format_s16) {
31281  /* */ ma_int16* pY = ( ma_int16*)pFramesOut;
31282  const ma_int16* pX = (const ma_int16*)pFramesIn;
31283 
31284  for (n = 0; n < frameCount; n += 1) {
31285  ma_hpf1_process_pcm_frame_s16(pHPF, pY, pX);
31286  pY += pHPF->channels;
31287  pX += pHPF->channels;
31288  }
31289  } else {
31291  return MA_INVALID_ARGS; /* Format not supported. Should never hit this because it's checked in ma_biquad_init() and ma_biquad_reinit(). */
31292  }
31293 
31294  return MA_SUCCESS;
31295 }
31296 
31298 {
31299  if (pHPF == NULL) {
31300  return 0;
31301  }
31302 
31303  return 1;
31304 }
31305 
31306 
31308 {
31309  ma_biquad_config bqConfig;
31310  double q;
31311  double w;
31312  double s;
31313  double c;
31314  double a;
31315 
31316  MA_ASSERT(pConfig != NULL);
31317 
31318  q = pConfig->q;
31319  w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
31320  s = ma_sind(w);
31321  c = ma_cosd(w);
31322  a = s / (2*q);
31323 
31324  bqConfig.b0 = (1 + c) / 2;
31325  bqConfig.b1 = -(1 + c);
31326  bqConfig.b2 = (1 + c) / 2;
31327  bqConfig.a0 = 1 + a;
31328  bqConfig.a1 = -2 * c;
31329  bqConfig.a2 = 1 - a;
31330 
31331  bqConfig.format = pConfig->format;
31332  bqConfig.channels = pConfig->channels;
31333 
31334  return bqConfig;
31335 }
31336 
31338 {
31339  ma_result result;
31340  ma_biquad_config bqConfig;
31341 
31342  if (pHPF == NULL) {
31343  return MA_INVALID_ARGS;
31344  }
31345 
31346  MA_ZERO_OBJECT(pHPF);
31347 
31348  if (pConfig == NULL) {
31349  return MA_INVALID_ARGS;
31350  }
31351 
31352  bqConfig = ma_hpf2__get_biquad_config(pConfig);
31353  result = ma_biquad_init(&bqConfig, &pHPF->bq);
31354  if (result != MA_SUCCESS) {
31355  return result;
31356  }
31357 
31358  return MA_SUCCESS;
31359 }
31360 
31362 {
31363  ma_result result;
31364  ma_biquad_config bqConfig;
31365 
31366  if (pHPF == NULL || pConfig == NULL) {
31367  return MA_INVALID_ARGS;
31368  }
31369 
31370  bqConfig = ma_hpf2__get_biquad_config(pConfig);
31371  result = ma_biquad_reinit(&bqConfig, &pHPF->bq);
31372  if (result != MA_SUCCESS) {
31373  return result;
31374  }
31375 
31376  return MA_SUCCESS;
31377 }
31378 
31379 static MA_INLINE void ma_hpf2_process_pcm_frame_s16(ma_hpf2* pHPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
31380 {
31381  ma_biquad_process_pcm_frame_s16(&pHPF->bq, pFrameOut, pFrameIn);
31382 }
31383 
31384 static MA_INLINE void ma_hpf2_process_pcm_frame_f32(ma_hpf2* pHPF, float* pFrameOut, const float* pFrameIn)
31385 {
31386  ma_biquad_process_pcm_frame_f32(&pHPF->bq, pFrameOut, pFrameIn);
31387 }
31388 
31389 MA_API ma_result ma_hpf2_process_pcm_frames(ma_hpf2* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
31390 {
31391  if (pHPF == NULL) {
31392  return MA_INVALID_ARGS;
31393  }
31394 
31395  return ma_biquad_process_pcm_frames(&pHPF->bq, pFramesOut, pFramesIn, frameCount);
31396 }
31397 
31399 {
31400  if (pHPF == NULL) {
31401  return 0;
31402  }
31403 
31404  return ma_biquad_get_latency(&pHPF->bq);
31405 }
31406 
31407 
31408 MA_API ma_hpf_config ma_hpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
31409 {
31411 
31413  config.format = format;
31414  config.channels = channels;
31415  config.sampleRate = sampleRate;
31416  config.cutoffFrequency = cutoffFrequency;
31417  config.order = ma_min(order, MA_MAX_FILTER_ORDER);
31418 
31419  return config;
31420 }
31421 
31423 {
31424  ma_result result;
31425  ma_uint32 hpf1Count;
31426  ma_uint32 hpf2Count;
31427  ma_uint32 ihpf1;
31428  ma_uint32 ihpf2;
31429 
31430  if (pHPF == NULL || pConfig == NULL) {
31431  return MA_INVALID_ARGS;
31432  }
31433 
31434  /* Only supporting f32 and s16. */
31435  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
31436  return MA_INVALID_ARGS;
31437  }
31438 
31439  /* The format cannot be changed after initialization. */
31440  if (pHPF->format != ma_format_unknown && pHPF->format != pConfig->format) {
31441  return MA_INVALID_OPERATION;
31442  }
31443 
31444  /* The channel count cannot be changed after initialization. */
31445  if (pHPF->channels != 0 && pHPF->channels != pConfig->channels) {
31446  return MA_INVALID_OPERATION;
31447  }
31448 
31449  if (pConfig->order > MA_MAX_FILTER_ORDER) {
31450  return MA_INVALID_ARGS;
31451  }
31452 
31453  hpf1Count = pConfig->order % 2;
31454  hpf2Count = pConfig->order / 2;
31455 
31456  MA_ASSERT(hpf1Count <= ma_countof(pHPF->hpf1));
31457  MA_ASSERT(hpf2Count <= ma_countof(pHPF->hpf2));
31458 
31459  /* The filter order can't change between reinits. */
31460  if (!isNew) {
31461  if (pHPF->hpf1Count != hpf1Count || pHPF->hpf2Count != hpf2Count) {
31462  return MA_INVALID_OPERATION;
31463  }
31464  }
31465 
31466  for (ihpf1 = 0; ihpf1 < hpf1Count; ihpf1 += 1) {
31467  ma_hpf1_config hpf1Config = ma_hpf1_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency);
31468 
31469  if (isNew) {
31470  result = ma_hpf1_init(&hpf1Config, &pHPF->hpf1[ihpf1]);
31471  } else {
31472  result = ma_hpf1_reinit(&hpf1Config, &pHPF->hpf1[ihpf1]);
31473  }
31474 
31475  if (result != MA_SUCCESS) {
31476  return result;
31477  }
31478  }
31479 
31480  for (ihpf2 = 0; ihpf2 < hpf2Count; ihpf2 += 1) {
31481  ma_hpf2_config hpf2Config;
31482  double q;
31483  double a;
31484 
31485  /* Tempting to use 0.707107, but won't result in a Butterworth filter if the order is > 2. */
31486  if (hpf1Count == 1) {
31487  a = (1 + ihpf2*1) * (MA_PI_D/(pConfig->order*1)); /* Odd order. */
31488  } else {
31489  a = (1 + ihpf2*2) * (MA_PI_D/(pConfig->order*2)); /* Even order. */
31490  }
31491  q = 1 / (2*ma_cosd(a));
31492 
31493  hpf2Config = ma_hpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
31494 
31495  if (isNew) {
31496  result = ma_hpf2_init(&hpf2Config, &pHPF->hpf2[ihpf2]);
31497  } else {
31498  result = ma_hpf2_reinit(&hpf2Config, &pHPF->hpf2[ihpf2]);
31499  }
31500 
31501  if (result != MA_SUCCESS) {
31502  return result;
31503  }
31504  }
31505 
31506  pHPF->hpf1Count = hpf1Count;
31507  pHPF->hpf2Count = hpf2Count;
31508  pHPF->format = pConfig->format;
31509  pHPF->channels = pConfig->channels;
31510  pHPF->sampleRate = pConfig->sampleRate;
31511 
31512  return MA_SUCCESS;
31513 }
31514 
31516 {
31517  if (pHPF == NULL) {
31518  return MA_INVALID_ARGS;
31519  }
31520 
31521  MA_ZERO_OBJECT(pHPF);
31522 
31523  if (pConfig == NULL) {
31524  return MA_INVALID_ARGS;
31525  }
31526 
31527  return ma_hpf_reinit__internal(pConfig, pHPF, /*isNew*/MA_TRUE);
31528 }
31529 
31531 {
31532  return ma_hpf_reinit__internal(pConfig, pHPF, /*isNew*/MA_FALSE);
31533 }
31534 
31535 MA_API ma_result ma_hpf_process_pcm_frames(ma_hpf* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
31536 {
31537  ma_result result;
31538  ma_uint32 ihpf1;
31539  ma_uint32 ihpf2;
31540 
31541  if (pHPF == NULL) {
31542  return MA_INVALID_ARGS;
31543  }
31544 
31545  /* Faster path for in-place. */
31546  if (pFramesOut == pFramesIn) {
31547  for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
31548  result = ma_hpf1_process_pcm_frames(&pHPF->hpf1[ihpf1], pFramesOut, pFramesOut, frameCount);
31549  if (result != MA_SUCCESS) {
31550  return result;
31551  }
31552  }
31553 
31554  for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
31555  result = ma_hpf2_process_pcm_frames(&pHPF->hpf2[ihpf2], pFramesOut, pFramesOut, frameCount);
31556  if (result != MA_SUCCESS) {
31557  return result;
31558  }
31559  }
31560  }
31561 
31562  /* Slightly slower path for copying. */
31563  if (pFramesOut != pFramesIn) {
31564  ma_uint32 iFrame;
31565 
31566  /* */ if (pHPF->format == ma_format_f32) {
31567  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
31568  const float* pFramesInF32 = (const float*)pFramesIn;
31569 
31570  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
31571  MA_COPY_MEMORY(pFramesOutF32, pFramesInF32, ma_get_bytes_per_frame(pHPF->format, pHPF->channels));
31572 
31573  for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
31574  ma_hpf1_process_pcm_frame_f32(&pHPF->hpf1[ihpf1], pFramesOutF32, pFramesOutF32);
31575  }
31576 
31577  for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
31578  ma_hpf2_process_pcm_frame_f32(&pHPF->hpf2[ihpf2], pFramesOutF32, pFramesOutF32);
31579  }
31580 
31581  pFramesOutF32 += pHPF->channels;
31582  pFramesInF32 += pHPF->channels;
31583  }
31584  } else if (pHPF->format == ma_format_s16) {
31585  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
31586  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
31587 
31588  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
31589  MA_COPY_MEMORY(pFramesOutS16, pFramesInS16, ma_get_bytes_per_frame(pHPF->format, pHPF->channels));
31590 
31591  for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
31592  ma_hpf1_process_pcm_frame_s16(&pHPF->hpf1[ihpf1], pFramesOutS16, pFramesOutS16);
31593  }
31594 
31595  for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
31596  ma_hpf2_process_pcm_frame_s16(&pHPF->hpf2[ihpf2], pFramesOutS16, pFramesOutS16);
31597  }
31598 
31599  pFramesOutS16 += pHPF->channels;
31600  pFramesInS16 += pHPF->channels;
31601  }
31602  } else {
31604  return MA_INVALID_OPERATION; /* Should never hit this. */
31605  }
31606  }
31607 
31608  return MA_SUCCESS;
31609 }
31610 
31612 {
31613  if (pHPF == NULL) {
31614  return 0;
31615  }
31616 
31617  return pHPF->hpf2Count*2 + pHPF->hpf1Count;
31618 }
31619 
31620 
31621 /**************************************************************************************************************************************************************
31622 
31623 Band-Pass Filtering
31624 
31625 **************************************************************************************************************************************************************/
31626 MA_API ma_bpf2_config ma_bpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
31627 {
31629 
31631  config.format = format;
31632  config.channels = channels;
31633  config.sampleRate = sampleRate;
31634  config.cutoffFrequency = cutoffFrequency;
31635  config.q = q;
31636 
31637  /* Q cannot be 0 or else it'll result in a division by 0. In this case just default to 0.707107. */
31638  if (config.q == 0) {
31639  config.q = 0.707107;
31640  }
31641 
31642  return config;
31643 }
31644 
31645 
31647 {
31648  ma_biquad_config bqConfig;
31649  double q;
31650  double w;
31651  double s;
31652  double c;
31653  double a;
31654 
31655  MA_ASSERT(pConfig != NULL);
31656 
31657  q = pConfig->q;
31658  w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
31659  s = ma_sind(w);
31660  c = ma_cosd(w);
31661  a = s / (2*q);
31662 
31663  bqConfig.b0 = q * a;
31664  bqConfig.b1 = 0;
31665  bqConfig.b2 = -q * a;
31666  bqConfig.a0 = 1 + a;
31667  bqConfig.a1 = -2 * c;
31668  bqConfig.a2 = 1 - a;
31669 
31670  bqConfig.format = pConfig->format;
31671  bqConfig.channels = pConfig->channels;
31672 
31673  return bqConfig;
31674 }
31675 
31677 {
31678  ma_result result;
31679  ma_biquad_config bqConfig;
31680 
31681  if (pBPF == NULL) {
31682  return MA_INVALID_ARGS;
31683  }
31684 
31685  MA_ZERO_OBJECT(pBPF);
31686 
31687  if (pConfig == NULL) {
31688  return MA_INVALID_ARGS;
31689  }
31690 
31691  bqConfig = ma_bpf2__get_biquad_config(pConfig);
31692  result = ma_biquad_init(&bqConfig, &pBPF->bq);
31693  if (result != MA_SUCCESS) {
31694  return result;
31695  }
31696 
31697  return MA_SUCCESS;
31698 }
31699 
31701 {
31702  ma_result result;
31703  ma_biquad_config bqConfig;
31704 
31705  if (pBPF == NULL || pConfig == NULL) {
31706  return MA_INVALID_ARGS;
31707  }
31708 
31709  bqConfig = ma_bpf2__get_biquad_config(pConfig);
31710  result = ma_biquad_reinit(&bqConfig, &pBPF->bq);
31711  if (result != MA_SUCCESS) {
31712  return result;
31713  }
31714 
31715  return MA_SUCCESS;
31716 }
31717 
31718 static MA_INLINE void ma_bpf2_process_pcm_frame_s16(ma_bpf2* pBPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
31719 {
31720  ma_biquad_process_pcm_frame_s16(&pBPF->bq, pFrameOut, pFrameIn);
31721 }
31722 
31723 static MA_INLINE void ma_bpf2_process_pcm_frame_f32(ma_bpf2* pBPF, float* pFrameOut, const float* pFrameIn)
31724 {
31725  ma_biquad_process_pcm_frame_f32(&pBPF->bq, pFrameOut, pFrameIn);
31726 }
31727 
31728 MA_API ma_result ma_bpf2_process_pcm_frames(ma_bpf2* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
31729 {
31730  if (pBPF == NULL) {
31731  return MA_INVALID_ARGS;
31732  }
31733 
31734  return ma_biquad_process_pcm_frames(&pBPF->bq, pFramesOut, pFramesIn, frameCount);
31735 }
31736 
31738 {
31739  if (pBPF == NULL) {
31740  return 0;
31741  }
31742 
31743  return ma_biquad_get_latency(&pBPF->bq);
31744 }
31745 
31746 
31747 MA_API ma_bpf_config ma_bpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
31748 {
31750 
31752  config.format = format;
31753  config.channels = channels;
31754  config.sampleRate = sampleRate;
31755  config.cutoffFrequency = cutoffFrequency;
31756  config.order = ma_min(order, MA_MAX_FILTER_ORDER);
31757 
31758  return config;
31759 }
31760 
31762 {
31763  ma_result result;
31764  ma_uint32 bpf2Count;
31765  ma_uint32 ibpf2;
31766 
31767  if (pBPF == NULL || pConfig == NULL) {
31768  return MA_INVALID_ARGS;
31769  }
31770 
31771  /* Only supporting f32 and s16. */
31772  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
31773  return MA_INVALID_ARGS;
31774  }
31775 
31776  /* The format cannot be changed after initialization. */
31777  if (pBPF->format != ma_format_unknown && pBPF->format != pConfig->format) {
31778  return MA_INVALID_OPERATION;
31779  }
31780 
31781  /* The channel count cannot be changed after initialization. */
31782  if (pBPF->channels != 0 && pBPF->channels != pConfig->channels) {
31783  return MA_INVALID_OPERATION;
31784  }
31785 
31786  if (pConfig->order > MA_MAX_FILTER_ORDER) {
31787  return MA_INVALID_ARGS;
31788  }
31789 
31790  /* We must have an even number of order. */
31791  if ((pConfig->order & 0x1) != 0) {
31792  return MA_INVALID_ARGS;
31793  }
31794 
31795  bpf2Count = pConfig->order / 2;
31796 
31797  MA_ASSERT(bpf2Count <= ma_countof(pBPF->bpf2));
31798 
31799  /* The filter order can't change between reinits. */
31800  if (!isNew) {
31801  if (pBPF->bpf2Count != bpf2Count) {
31802  return MA_INVALID_OPERATION;
31803  }
31804  }
31805 
31806  for (ibpf2 = 0; ibpf2 < bpf2Count; ibpf2 += 1) {
31807  ma_bpf2_config bpf2Config;
31808  double q;
31809 
31810  /* TODO: Calculate Q to make this a proper Butterworth filter. */
31811  q = 0.707107;
31812 
31813  bpf2Config = ma_bpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
31814 
31815  if (isNew) {
31816  result = ma_bpf2_init(&bpf2Config, &pBPF->bpf2[ibpf2]);
31817  } else {
31818  result = ma_bpf2_reinit(&bpf2Config, &pBPF->bpf2[ibpf2]);
31819  }
31820 
31821  if (result != MA_SUCCESS) {
31822  return result;
31823  }
31824  }
31825 
31826  pBPF->bpf2Count = bpf2Count;
31827  pBPF->format = pConfig->format;
31828  pBPF->channels = pConfig->channels;
31829 
31830  return MA_SUCCESS;
31831 }
31832 
31834 {
31835  if (pBPF == NULL) {
31836  return MA_INVALID_ARGS;
31837  }
31838 
31839  MA_ZERO_OBJECT(pBPF);
31840 
31841  if (pConfig == NULL) {
31842  return MA_INVALID_ARGS;
31843  }
31844 
31845  return ma_bpf_reinit__internal(pConfig, pBPF, /*isNew*/MA_TRUE);
31846 }
31847 
31849 {
31850  return ma_bpf_reinit__internal(pConfig, pBPF, /*isNew*/MA_FALSE);
31851 }
31852 
31853 MA_API ma_result ma_bpf_process_pcm_frames(ma_bpf* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
31854 {
31855  ma_result result;
31856  ma_uint32 ibpf2;
31857 
31858  if (pBPF == NULL) {
31859  return MA_INVALID_ARGS;
31860  }
31861 
31862  /* Faster path for in-place. */
31863  if (pFramesOut == pFramesIn) {
31864  for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
31865  result = ma_bpf2_process_pcm_frames(&pBPF->bpf2[ibpf2], pFramesOut, pFramesOut, frameCount);
31866  if (result != MA_SUCCESS) {
31867  return result;
31868  }
31869  }
31870  }
31871 
31872  /* Slightly slower path for copying. */
31873  if (pFramesOut != pFramesIn) {
31874  ma_uint32 iFrame;
31875 
31876  /* */ if (pBPF->format == ma_format_f32) {
31877  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
31878  const float* pFramesInF32 = (const float*)pFramesIn;
31879 
31880  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
31881  MA_COPY_MEMORY(pFramesOutF32, pFramesInF32, ma_get_bytes_per_frame(pBPF->format, pBPF->channels));
31882 
31883  for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
31884  ma_bpf2_process_pcm_frame_f32(&pBPF->bpf2[ibpf2], pFramesOutF32, pFramesOutF32);
31885  }
31886 
31887  pFramesOutF32 += pBPF->channels;
31888  pFramesInF32 += pBPF->channels;
31889  }
31890  } else if (pBPF->format == ma_format_s16) {
31891  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
31892  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
31893 
31894  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
31895  MA_COPY_MEMORY(pFramesOutS16, pFramesInS16, ma_get_bytes_per_frame(pBPF->format, pBPF->channels));
31896 
31897  for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
31898  ma_bpf2_process_pcm_frame_s16(&pBPF->bpf2[ibpf2], pFramesOutS16, pFramesOutS16);
31899  }
31900 
31901  pFramesOutS16 += pBPF->channels;
31902  pFramesInS16 += pBPF->channels;
31903  }
31904  } else {
31906  return MA_INVALID_OPERATION; /* Should never hit this. */
31907  }
31908  }
31909 
31910  return MA_SUCCESS;
31911 }
31912 
31914 {
31915  if (pBPF == NULL) {
31916  return 0;
31917  }
31918 
31919  return pBPF->bpf2Count*2;
31920 }
31921 
31922 
31923 /**************************************************************************************************************************************************************
31924 
31925 Notching Filter
31926 
31927 **************************************************************************************************************************************************************/
31928 MA_API ma_notch2_config ma_notch2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency)
31929 {
31931 
31933  config.format = format;
31934  config.channels = channels;
31935  config.sampleRate = sampleRate;
31936  config.q = q;
31937  config.frequency = frequency;
31938 
31939  if (config.q == 0) {
31940  config.q = 0.707107;
31941  }
31942 
31943  return config;
31944 }
31945 
31946 
31948 {
31949  ma_biquad_config bqConfig;
31950  double q;
31951  double w;
31952  double s;
31953  double c;
31954  double a;
31955 
31956  MA_ASSERT(pConfig != NULL);
31957 
31958  q = pConfig->q;
31959  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
31960  s = ma_sind(w);
31961  c = ma_cosd(w);
31962  a = s / (2*q);
31963 
31964  bqConfig.b0 = 1;
31965  bqConfig.b1 = -2 * c;
31966  bqConfig.b2 = 1;
31967  bqConfig.a0 = 1 + a;
31968  bqConfig.a1 = -2 * c;
31969  bqConfig.a2 = 1 - a;
31970 
31971  bqConfig.format = pConfig->format;
31972  bqConfig.channels = pConfig->channels;
31973 
31974  return bqConfig;
31975 }
31976 
31978 {
31979  ma_result result;
31980  ma_biquad_config bqConfig;
31981 
31982  if (pFilter == NULL) {
31983  return MA_INVALID_ARGS;
31984  }
31985 
31986  MA_ZERO_OBJECT(pFilter);
31987 
31988  if (pConfig == NULL) {
31989  return MA_INVALID_ARGS;
31990  }
31991 
31992  bqConfig = ma_notch2__get_biquad_config(pConfig);
31993  result = ma_biquad_init(&bqConfig, &pFilter->bq);
31994  if (result != MA_SUCCESS) {
31995  return result;
31996  }
31997 
31998  return MA_SUCCESS;
31999 }
32000 
32002 {
32003  ma_result result;
32004  ma_biquad_config bqConfig;
32005 
32006  if (pFilter == NULL || pConfig == NULL) {
32007  return MA_INVALID_ARGS;
32008  }
32009 
32010  bqConfig = ma_notch2__get_biquad_config(pConfig);
32011  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
32012  if (result != MA_SUCCESS) {
32013  return result;
32014  }
32015 
32016  return MA_SUCCESS;
32017 }
32018 
32019 static MA_INLINE void ma_notch2_process_pcm_frame_s16(ma_notch2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
32020 {
32021  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
32022 }
32023 
32024 static MA_INLINE void ma_notch2_process_pcm_frame_f32(ma_notch2* pFilter, float* pFrameOut, const float* pFrameIn)
32025 {
32026  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
32027 }
32028 
32029 MA_API ma_result ma_notch2_process_pcm_frames(ma_notch2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
32030 {
32031  if (pFilter == NULL) {
32032  return MA_INVALID_ARGS;
32033  }
32034 
32035  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
32036 }
32037 
32039 {
32040  if (pFilter == NULL) {
32041  return 0;
32042  }
32043 
32044  return ma_biquad_get_latency(&pFilter->bq);
32045 }
32046 
32047 
32048 
32049 /**************************************************************************************************************************************************************
32050 
32051 Peaking EQ Filter
32052 
32053 **************************************************************************************************************************************************************/
32054 MA_API ma_peak2_config ma_peak2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
32055 {
32057 
32059  config.format = format;
32060  config.channels = channels;
32061  config.sampleRate = sampleRate;
32062  config.gainDB = gainDB;
32063  config.q = q;
32064  config.frequency = frequency;
32065 
32066  if (config.q == 0) {
32067  config.q = 0.707107;
32068  }
32069 
32070  return config;
32071 }
32072 
32073 
32075 {
32076  ma_biquad_config bqConfig;
32077  double q;
32078  double w;
32079  double s;
32080  double c;
32081  double a;
32082  double A;
32083 
32084  MA_ASSERT(pConfig != NULL);
32085 
32086  q = pConfig->q;
32087  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
32088  s = ma_sind(w);
32089  c = ma_cosd(w);
32090  a = s / (2*q);
32091  A = ma_powd(10, (pConfig->gainDB / 40));
32092 
32093  bqConfig.b0 = 1 + (a * A);
32094  bqConfig.b1 = -2 * c;
32095  bqConfig.b2 = 1 - (a * A);
32096  bqConfig.a0 = 1 + (a / A);
32097  bqConfig.a1 = -2 * c;
32098  bqConfig.a2 = 1 - (a / A);
32099 
32100  bqConfig.format = pConfig->format;
32101  bqConfig.channels = pConfig->channels;
32102 
32103  return bqConfig;
32104 }
32105 
32107 {
32108  ma_result result;
32109  ma_biquad_config bqConfig;
32110 
32111  if (pFilter == NULL) {
32112  return MA_INVALID_ARGS;
32113  }
32114 
32115  MA_ZERO_OBJECT(pFilter);
32116 
32117  if (pConfig == NULL) {
32118  return MA_INVALID_ARGS;
32119  }
32120 
32121  bqConfig = ma_peak2__get_biquad_config(pConfig);
32122  result = ma_biquad_init(&bqConfig, &pFilter->bq);
32123  if (result != MA_SUCCESS) {
32124  return result;
32125  }
32126 
32127  return MA_SUCCESS;
32128 }
32129 
32131 {
32132  ma_result result;
32133  ma_biquad_config bqConfig;
32134 
32135  if (pFilter == NULL || pConfig == NULL) {
32136  return MA_INVALID_ARGS;
32137  }
32138 
32139  bqConfig = ma_peak2__get_biquad_config(pConfig);
32140  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
32141  if (result != MA_SUCCESS) {
32142  return result;
32143  }
32144 
32145  return MA_SUCCESS;
32146 }
32147 
32148 static MA_INLINE void ma_peak2_process_pcm_frame_s16(ma_peak2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
32149 {
32150  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
32151 }
32152 
32153 static MA_INLINE void ma_peak2_process_pcm_frame_f32(ma_peak2* pFilter, float* pFrameOut, const float* pFrameIn)
32154 {
32155  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
32156 }
32157 
32158 MA_API ma_result ma_peak2_process_pcm_frames(ma_peak2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
32159 {
32160  if (pFilter == NULL) {
32161  return MA_INVALID_ARGS;
32162  }
32163 
32164  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
32165 }
32166 
32168 {
32169  if (pFilter == NULL) {
32170  return 0;
32171  }
32172 
32173  return ma_biquad_get_latency(&pFilter->bq);
32174 }
32175 
32176 
32177 /**************************************************************************************************************************************************************
32178 
32179 Low Shelf Filter
32180 
32181 **************************************************************************************************************************************************************/
32182 MA_API ma_loshelf2_config ma_loshelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency)
32183 {
32185 
32187  config.format = format;
32188  config.channels = channels;
32189  config.sampleRate = sampleRate;
32190  config.gainDB = gainDB;
32191  config.shelfSlope = shelfSlope;
32192  config.frequency = frequency;
32193 
32194  return config;
32195 }
32196 
32197 
32199 {
32200  ma_biquad_config bqConfig;
32201  double w;
32202  double s;
32203  double c;
32204  double A;
32205  double S;
32206  double a;
32207  double sqrtA;
32208 
32209  MA_ASSERT(pConfig != NULL);
32210 
32211  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
32212  s = ma_sind(w);
32213  c = ma_cosd(w);
32214  A = ma_powd(10, (pConfig->gainDB / 40));
32215  S = pConfig->shelfSlope;
32216  a = s/2 * ma_sqrtd((A + 1/A) * (1/S - 1) + 2);
32217  sqrtA = 2*ma_sqrtd(A)*a;
32218 
32219  bqConfig.b0 = A * ((A + 1) - (A - 1)*c + sqrtA);
32220  bqConfig.b1 = 2 * A * ((A - 1) - (A + 1)*c);
32221  bqConfig.b2 = A * ((A + 1) - (A - 1)*c - sqrtA);
32222  bqConfig.a0 = (A + 1) + (A - 1)*c + sqrtA;
32223  bqConfig.a1 = -2 * ((A - 1) + (A + 1)*c);
32224  bqConfig.a2 = (A + 1) + (A - 1)*c - sqrtA;
32225 
32226  bqConfig.format = pConfig->format;
32227  bqConfig.channels = pConfig->channels;
32228 
32229  return bqConfig;
32230 }
32231 
32233 {
32234  ma_result result;
32235  ma_biquad_config bqConfig;
32236 
32237  if (pFilter == NULL) {
32238  return MA_INVALID_ARGS;
32239  }
32240 
32241  MA_ZERO_OBJECT(pFilter);
32242 
32243  if (pConfig == NULL) {
32244  return MA_INVALID_ARGS;
32245  }
32246 
32247  bqConfig = ma_loshelf2__get_biquad_config(pConfig);
32248  result = ma_biquad_init(&bqConfig, &pFilter->bq);
32249  if (result != MA_SUCCESS) {
32250  return result;
32251  }
32252 
32253  return MA_SUCCESS;
32254 }
32255 
32257 {
32258  ma_result result;
32259  ma_biquad_config bqConfig;
32260 
32261  if (pFilter == NULL || pConfig == NULL) {
32262  return MA_INVALID_ARGS;
32263  }
32264 
32265  bqConfig = ma_loshelf2__get_biquad_config(pConfig);
32266  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
32267  if (result != MA_SUCCESS) {
32268  return result;
32269  }
32270 
32271  return MA_SUCCESS;
32272 }
32273 
32274 static MA_INLINE void ma_loshelf2_process_pcm_frame_s16(ma_loshelf2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
32275 {
32276  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
32277 }
32278 
32279 static MA_INLINE void ma_loshelf2_process_pcm_frame_f32(ma_loshelf2* pFilter, float* pFrameOut, const float* pFrameIn)
32280 {
32281  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
32282 }
32283 
32284 MA_API ma_result ma_loshelf2_process_pcm_frames(ma_loshelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
32285 {
32286  if (pFilter == NULL) {
32287  return MA_INVALID_ARGS;
32288  }
32289 
32290  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
32291 }
32292 
32294 {
32295  if (pFilter == NULL) {
32296  return 0;
32297  }
32298 
32299  return ma_biquad_get_latency(&pFilter->bq);
32300 }
32301 
32302 
32303 /**************************************************************************************************************************************************************
32304 
32305 High Shelf Filter
32306 
32307 **************************************************************************************************************************************************************/
32308 MA_API ma_hishelf2_config ma_hishelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency)
32309 {
32311 
32313  config.format = format;
32314  config.channels = channels;
32315  config.sampleRate = sampleRate;
32316  config.gainDB = gainDB;
32317  config.shelfSlope = shelfSlope;
32318  config.frequency = frequency;
32319 
32320  return config;
32321 }
32322 
32323 
32325 {
32326  ma_biquad_config bqConfig;
32327  double w;
32328  double s;
32329  double c;
32330  double A;
32331  double S;
32332  double a;
32333  double sqrtA;
32334 
32335  MA_ASSERT(pConfig != NULL);
32336 
32337  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
32338  s = ma_sind(w);
32339  c = ma_cosd(w);
32340  A = ma_powd(10, (pConfig->gainDB / 40));
32341  S = pConfig->shelfSlope;
32342  a = s/2 * ma_sqrtd((A + 1/A) * (1/S - 1) + 2);
32343  sqrtA = 2*ma_sqrtd(A)*a;
32344 
32345  bqConfig.b0 = A * ((A + 1) + (A - 1)*c + sqrtA);
32346  bqConfig.b1 = -2 * A * ((A - 1) + (A + 1)*c);
32347  bqConfig.b2 = A * ((A + 1) + (A - 1)*c - sqrtA);
32348  bqConfig.a0 = (A + 1) - (A - 1)*c + sqrtA;
32349  bqConfig.a1 = 2 * ((A - 1) - (A + 1)*c);
32350  bqConfig.a2 = (A + 1) - (A - 1)*c - sqrtA;
32351 
32352  bqConfig.format = pConfig->format;
32353  bqConfig.channels = pConfig->channels;
32354 
32355  return bqConfig;
32356 }
32357 
32359 {
32360  ma_result result;
32361  ma_biquad_config bqConfig;
32362 
32363  if (pFilter == NULL) {
32364  return MA_INVALID_ARGS;
32365  }
32366 
32367  MA_ZERO_OBJECT(pFilter);
32368 
32369  if (pConfig == NULL) {
32370  return MA_INVALID_ARGS;
32371  }
32372 
32373  bqConfig = ma_hishelf2__get_biquad_config(pConfig);
32374  result = ma_biquad_init(&bqConfig, &pFilter->bq);
32375  if (result != MA_SUCCESS) {
32376  return result;
32377  }
32378 
32379  return MA_SUCCESS;
32380 }
32381 
32383 {
32384  ma_result result;
32385  ma_biquad_config bqConfig;
32386 
32387  if (pFilter == NULL || pConfig == NULL) {
32388  return MA_INVALID_ARGS;
32389  }
32390 
32391  bqConfig = ma_hishelf2__get_biquad_config(pConfig);
32392  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
32393  if (result != MA_SUCCESS) {
32394  return result;
32395  }
32396 
32397  return MA_SUCCESS;
32398 }
32399 
32400 static MA_INLINE void ma_hishelf2_process_pcm_frame_s16(ma_hishelf2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
32401 {
32402  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
32403 }
32404 
32405 static MA_INLINE void ma_hishelf2_process_pcm_frame_f32(ma_hishelf2* pFilter, float* pFrameOut, const float* pFrameIn)
32406 {
32407  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
32408 }
32409 
32410 MA_API ma_result ma_hishelf2_process_pcm_frames(ma_hishelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
32411 {
32412  if (pFilter == NULL) {
32413  return MA_INVALID_ARGS;
32414  }
32415 
32416  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
32417 }
32418 
32420 {
32421  if (pFilter == NULL) {
32422  return 0;
32423  }
32424 
32425  return ma_biquad_get_latency(&pFilter->bq);
32426 }
32427 
32428 
32429 
32430 /**************************************************************************************************************************************************************
32431 
32432 Resampling
32433 
32434 **************************************************************************************************************************************************************/
32436 {
32439  config.format = format;
32440  config.channels = channels;
32441  config.sampleRateIn = sampleRateIn;
32442  config.sampleRateOut = sampleRateOut;
32444  config.lpfNyquistFactor = 1;
32445 
32446  return config;
32447 }
32448 
32449 static void ma_linear_resampler_adjust_timer_for_new_rate(ma_linear_resampler* pResampler, ma_uint32 oldSampleRateOut, ma_uint32 newSampleRateOut)
32450 {
32451  /*
32452  So what's happening here? Basically we need to adjust the fractional component of the time advance based on the new rate. The old time advance will
32453  be based on the old sample rate, but we are needing to adjust it to that it's based on the new sample rate.
32454  */
32455  ma_uint32 oldRateTimeWhole = pResampler->inTimeFrac / oldSampleRateOut; /* <-- This should almost never be anything other than 0, but leaving it here to make this more general and robust just in case. */
32456  ma_uint32 oldRateTimeFract = pResampler->inTimeFrac % oldSampleRateOut;
32457 
32458  pResampler->inTimeFrac =
32459  (oldRateTimeWhole * newSampleRateOut) +
32460  ((oldRateTimeFract * newSampleRateOut) / oldSampleRateOut);
32461 
32462  /* Make sure the fractional part is less than the output sample rate. */
32463  pResampler->inTimeInt += pResampler->inTimeFrac / pResampler->config.sampleRateOut;
32464  pResampler->inTimeFrac = pResampler->inTimeFrac % pResampler->config.sampleRateOut;
32465 }
32466 
32467 static ma_result ma_linear_resampler_set_rate_internal(ma_linear_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_bool32 isResamplerAlreadyInitialized)
32468 {
32469  ma_result result;
32470  ma_uint32 gcf;
32471  ma_uint32 lpfSampleRate;
32472  double lpfCutoffFrequency;
32473  ma_lpf_config lpfConfig;
32474  ma_uint32 oldSampleRateOut; /* Required for adjusting time advance down the bottom. */
32475 
32476  if (pResampler == NULL) {
32477  return MA_INVALID_ARGS;
32478  }
32479 
32480  if (sampleRateIn == 0 || sampleRateOut == 0) {
32481  return MA_INVALID_ARGS;
32482  }
32483 
32484  oldSampleRateOut = pResampler->config.sampleRateOut;
32485 
32486  pResampler->config.sampleRateIn = sampleRateIn;
32487  pResampler->config.sampleRateOut = sampleRateOut;
32488 
32489  /* Simplify the sample rate. */
32490  gcf = ma_gcf_u32(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut);
32491  pResampler->config.sampleRateIn /= gcf;
32492  pResampler->config.sampleRateOut /= gcf;
32493 
32494  /* Always initialize the low-pass filter, even when the order is 0. */
32495  if (pResampler->config.lpfOrder > MA_MAX_FILTER_ORDER) {
32496  return MA_INVALID_ARGS;
32497  }
32498 
32499  lpfSampleRate = (ma_uint32)(ma_max(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut));
32500  lpfCutoffFrequency = ( double)(ma_min(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut) * 0.5 * pResampler->config.lpfNyquistFactor);
32501 
32502  lpfConfig = ma_lpf_config_init(pResampler->config.format, pResampler->config.channels, lpfSampleRate, lpfCutoffFrequency, pResampler->config.lpfOrder);
32503 
32504  /*
32505  If the resampler is alreay initialized we don't want to do a fresh initialization of the low-pass filter because it will result in the cached frames
32506  getting cleared. Instead we re-initialize the filter which will maintain any cached frames.
32507  */
32508  if (isResamplerAlreadyInitialized) {
32509  result = ma_lpf_reinit(&lpfConfig, &pResampler->lpf);
32510  } else {
32511  result = ma_lpf_init(&lpfConfig, &pResampler->lpf);
32512  }
32513 
32514  if (result != MA_SUCCESS) {
32515  return result;
32516  }
32517 
32518 
32519  pResampler->inAdvanceInt = pResampler->config.sampleRateIn / pResampler->config.sampleRateOut;
32520  pResampler->inAdvanceFrac = pResampler->config.sampleRateIn % pResampler->config.sampleRateOut;
32521 
32522  /* Our timer was based on the old rate. We need to adjust it so that it's based on the new rate. */
32523  ma_linear_resampler_adjust_timer_for_new_rate(pResampler, oldSampleRateOut, pResampler->config.sampleRateOut);
32524 
32525  return MA_SUCCESS;
32526 }
32527 
32529 {
32530  ma_result result;
32531 
32532  if (pResampler == NULL) {
32533  return MA_INVALID_ARGS;
32534  }
32535 
32536  MA_ZERO_OBJECT(pResampler);
32537 
32538  if (pConfig == NULL) {
32539  return MA_INVALID_ARGS;
32540  }
32541 
32542  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
32543  return MA_INVALID_ARGS;
32544  }
32545 
32546  pResampler->config = *pConfig;
32547 
32548  /* Setting the rate will set up the filter and time advances for us. */
32549  result = ma_linear_resampler_set_rate_internal(pResampler, pConfig->sampleRateIn, pConfig->sampleRateOut, /* isResamplerAlreadyInitialized = */ MA_FALSE);
32550  if (result != MA_SUCCESS) {
32551  return result;
32552  }
32553 
32554  pResampler->inTimeInt = 1; /* Set this to one to force an input sample to always be loaded for the first output frame. */
32555  pResampler->inTimeFrac = 0;
32556 
32557  return MA_SUCCESS;
32558 }
32559 
32561 {
32562  if (pResampler == NULL) {
32563  return;
32564  }
32565 }
32566 
32568 {
32569  ma_int32 b;
32570  ma_int32 c;
32571  ma_int32 r;
32572 
32573  MA_ASSERT(a <= (1<<shift));
32574 
32575  b = x * ((1<<shift) - a);
32576  c = y * a;
32577  r = b + c;
32578 
32579  return (ma_int16)(r >> shift);
32580 }
32581 
32583 {
32584  ma_uint32 c;
32585  ma_uint32 a;
32586  const ma_uint32 channels = pResampler->config.channels;
32587  const ma_uint32 shift = 12;
32588 
32589  MA_ASSERT(pResampler != NULL);
32590  MA_ASSERT(pFrameOut != NULL);
32591 
32592  a = (pResampler->inTimeFrac << shift) / pResampler->config.sampleRateOut;
32593 
32594  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
32595  for (c = 0; c < channels; c += 1) {
32596  ma_int16 s = ma_linear_resampler_mix_s16(pResampler->x0.s16[c], pResampler->x1.s16[c], a, shift);
32597  pFrameOut[c] = s;
32598  }
32599 }
32600 
32601 
32603 {
32604  ma_uint32 c;
32605  float a;
32606  const ma_uint32 channels = pResampler->config.channels;
32607 
32608  MA_ASSERT(pResampler != NULL);
32609  MA_ASSERT(pFrameOut != NULL);
32610 
32611  a = (float)pResampler->inTimeFrac / pResampler->config.sampleRateOut;
32612 
32613  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
32614  for (c = 0; c < channels; c += 1) {
32615  float s = ma_mix_f32_fast(pResampler->x0.f32[c], pResampler->x1.f32[c], a);
32616  pFrameOut[c] = s;
32617  }
32618 }
32619 
32620 static ma_result ma_linear_resampler_process_pcm_frames_s16_downsample(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32621 {
32622  const ma_int16* pFramesInS16;
32623  /* */ ma_int16* pFramesOutS16;
32624  ma_uint64 frameCountIn;
32625  ma_uint64 frameCountOut;
32626  ma_uint64 framesProcessedIn;
32627  ma_uint64 framesProcessedOut;
32628 
32629  MA_ASSERT(pResampler != NULL);
32630  MA_ASSERT(pFrameCountIn != NULL);
32631  MA_ASSERT(pFrameCountOut != NULL);
32632 
32633  pFramesInS16 = (const ma_int16*)pFramesIn;
32634  pFramesOutS16 = ( ma_int16*)pFramesOut;
32635  frameCountIn = *pFrameCountIn;
32636  frameCountOut = *pFrameCountOut;
32637  framesProcessedIn = 0;
32638  framesProcessedOut = 0;
32639 
32640  while (framesProcessedOut < frameCountOut) {
32641  /* Before interpolating we need to load the buffers. When doing this we need to ensure we run every input sample through the filter. */
32642  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
32643  ma_uint32 iChannel;
32644 
32645  if (pFramesInS16 != NULL) {
32646  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32647  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
32648  pResampler->x1.s16[iChannel] = pFramesInS16[iChannel];
32649  }
32650  pFramesInS16 += pResampler->config.channels;
32651  } else {
32652  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32653  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
32654  pResampler->x1.s16[iChannel] = 0;
32655  }
32656  }
32657 
32658  /* Filter. */
32659  ma_lpf_process_pcm_frame_s16(&pResampler->lpf, pResampler->x1.s16, pResampler->x1.s16);
32660 
32661  framesProcessedIn += 1;
32662  pResampler->inTimeInt -= 1;
32663  }
32664 
32665  if (pResampler->inTimeInt > 0) {
32666  break; /* Ran out of input data. */
32667  }
32668 
32669  /* Getting here means the frames have been loaded and filtered and we can generate the next output frame. */
32670  if (pFramesOutS16 != NULL) {
32671  MA_ASSERT(pResampler->inTimeInt == 0);
32672  ma_linear_resampler_interpolate_frame_s16(pResampler, pFramesOutS16);
32673 
32674  pFramesOutS16 += pResampler->config.channels;
32675  }
32676 
32677  framesProcessedOut += 1;
32678 
32679  /* Advance time forward. */
32680  pResampler->inTimeInt += pResampler->inAdvanceInt;
32681  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
32682  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
32683  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
32684  pResampler->inTimeInt += 1;
32685  }
32686  }
32687 
32688  *pFrameCountIn = framesProcessedIn;
32689  *pFrameCountOut = framesProcessedOut;
32690 
32691  return MA_SUCCESS;
32692 }
32693 
32694 static ma_result ma_linear_resampler_process_pcm_frames_s16_upsample(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32695 {
32696  const ma_int16* pFramesInS16;
32697  /* */ ma_int16* pFramesOutS16;
32698  ma_uint64 frameCountIn;
32699  ma_uint64 frameCountOut;
32700  ma_uint64 framesProcessedIn;
32701  ma_uint64 framesProcessedOut;
32702 
32703  MA_ASSERT(pResampler != NULL);
32704  MA_ASSERT(pFrameCountIn != NULL);
32705  MA_ASSERT(pFrameCountOut != NULL);
32706 
32707  pFramesInS16 = (const ma_int16*)pFramesIn;
32708  pFramesOutS16 = ( ma_int16*)pFramesOut;
32709  frameCountIn = *pFrameCountIn;
32710  frameCountOut = *pFrameCountOut;
32711  framesProcessedIn = 0;
32712  framesProcessedOut = 0;
32713 
32714  while (framesProcessedOut < frameCountOut) {
32715  /* Before interpolating we need to load the buffers. */
32716  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
32717  ma_uint32 iChannel;
32718 
32719  if (pFramesInS16 != NULL) {
32720  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32721  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
32722  pResampler->x1.s16[iChannel] = pFramesInS16[iChannel];
32723  }
32724  pFramesInS16 += pResampler->config.channels;
32725  } else {
32726  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32727  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
32728  pResampler->x1.s16[iChannel] = 0;
32729  }
32730  }
32731 
32732  framesProcessedIn += 1;
32733  pResampler->inTimeInt -= 1;
32734  }
32735 
32736  if (pResampler->inTimeInt > 0) {
32737  break; /* Ran out of input data. */
32738  }
32739 
32740  /* Getting here means the frames have been loaded and we can generate the next output frame. */
32741  if (pFramesOutS16 != NULL) {
32742  MA_ASSERT(pResampler->inTimeInt == 0);
32743  ma_linear_resampler_interpolate_frame_s16(pResampler, pFramesOutS16);
32744 
32745  /* Filter. */
32746  ma_lpf_process_pcm_frame_s16(&pResampler->lpf, pFramesOutS16, pFramesOutS16);
32747 
32748  pFramesOutS16 += pResampler->config.channels;
32749  }
32750 
32751  framesProcessedOut += 1;
32752 
32753  /* Advance time forward. */
32754  pResampler->inTimeInt += pResampler->inAdvanceInt;
32755  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
32756  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
32757  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
32758  pResampler->inTimeInt += 1;
32759  }
32760  }
32761 
32762  *pFrameCountIn = framesProcessedIn;
32763  *pFrameCountOut = framesProcessedOut;
32764 
32765  return MA_SUCCESS;
32766 }
32767 
32768 static ma_result ma_linear_resampler_process_pcm_frames_s16(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32769 {
32770  MA_ASSERT(pResampler != NULL);
32771 
32772  if (pResampler->config.sampleRateIn > pResampler->config.sampleRateOut) {
32773  return ma_linear_resampler_process_pcm_frames_s16_downsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
32774  } else {
32775  return ma_linear_resampler_process_pcm_frames_s16_upsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
32776  }
32777 }
32778 
32779 
32780 static ma_result ma_linear_resampler_process_pcm_frames_f32_downsample(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32781 {
32782  const float* pFramesInF32;
32783  /* */ float* pFramesOutF32;
32784  ma_uint64 frameCountIn;
32785  ma_uint64 frameCountOut;
32786  ma_uint64 framesProcessedIn;
32787  ma_uint64 framesProcessedOut;
32788 
32789  MA_ASSERT(pResampler != NULL);
32790  MA_ASSERT(pFrameCountIn != NULL);
32791  MA_ASSERT(pFrameCountOut != NULL);
32792 
32793  pFramesInF32 = (const float*)pFramesIn;
32794  pFramesOutF32 = ( float*)pFramesOut;
32795  frameCountIn = *pFrameCountIn;
32796  frameCountOut = *pFrameCountOut;
32797  framesProcessedIn = 0;
32798  framesProcessedOut = 0;
32799 
32800  while (framesProcessedOut < frameCountOut) {
32801  /* Before interpolating we need to load the buffers. When doing this we need to ensure we run every input sample through the filter. */
32802  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
32803  ma_uint32 iChannel;
32804 
32805  if (pFramesInF32 != NULL) {
32806  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32807  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
32808  pResampler->x1.f32[iChannel] = pFramesInF32[iChannel];
32809  }
32810  pFramesInF32 += pResampler->config.channels;
32811  } else {
32812  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32813  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
32814  pResampler->x1.f32[iChannel] = 0;
32815  }
32816  }
32817 
32818  /* Filter. */
32819  ma_lpf_process_pcm_frame_f32(&pResampler->lpf, pResampler->x1.f32, pResampler->x1.f32);
32820 
32821  framesProcessedIn += 1;
32822  pResampler->inTimeInt -= 1;
32823  }
32824 
32825  if (pResampler->inTimeInt > 0) {
32826  break; /* Ran out of input data. */
32827  }
32828 
32829  /* Getting here means the frames have been loaded and filtered and we can generate the next output frame. */
32830  if (pFramesOutF32 != NULL) {
32831  MA_ASSERT(pResampler->inTimeInt == 0);
32832  ma_linear_resampler_interpolate_frame_f32(pResampler, pFramesOutF32);
32833 
32834  pFramesOutF32 += pResampler->config.channels;
32835  }
32836 
32837  framesProcessedOut += 1;
32838 
32839  /* Advance time forward. */
32840  pResampler->inTimeInt += pResampler->inAdvanceInt;
32841  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
32842  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
32843  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
32844  pResampler->inTimeInt += 1;
32845  }
32846  }
32847 
32848  *pFrameCountIn = framesProcessedIn;
32849  *pFrameCountOut = framesProcessedOut;
32850 
32851  return MA_SUCCESS;
32852 }
32853 
32854 static ma_result ma_linear_resampler_process_pcm_frames_f32_upsample(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32855 {
32856  const float* pFramesInF32;
32857  /* */ float* pFramesOutF32;
32858  ma_uint64 frameCountIn;
32859  ma_uint64 frameCountOut;
32860  ma_uint64 framesProcessedIn;
32861  ma_uint64 framesProcessedOut;
32862 
32863  MA_ASSERT(pResampler != NULL);
32864  MA_ASSERT(pFrameCountIn != NULL);
32865  MA_ASSERT(pFrameCountOut != NULL);
32866 
32867  pFramesInF32 = (const float*)pFramesIn;
32868  pFramesOutF32 = ( float*)pFramesOut;
32869  frameCountIn = *pFrameCountIn;
32870  frameCountOut = *pFrameCountOut;
32871  framesProcessedIn = 0;
32872  framesProcessedOut = 0;
32873 
32874  while (framesProcessedOut < frameCountOut) {
32875  /* Before interpolating we need to load the buffers. */
32876  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
32877  ma_uint32 iChannel;
32878 
32879  if (pFramesInF32 != NULL) {
32880  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32881  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
32882  pResampler->x1.f32[iChannel] = pFramesInF32[iChannel];
32883  }
32884  pFramesInF32 += pResampler->config.channels;
32885  } else {
32886  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
32887  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
32888  pResampler->x1.f32[iChannel] = 0;
32889  }
32890  }
32891 
32892  framesProcessedIn += 1;
32893  pResampler->inTimeInt -= 1;
32894  }
32895 
32896  if (pResampler->inTimeInt > 0) {
32897  break; /* Ran out of input data. */
32898  }
32899 
32900  /* Getting here means the frames have been loaded and we can generate the next output frame. */
32901  if (pFramesOutF32 != NULL) {
32902  MA_ASSERT(pResampler->inTimeInt == 0);
32903  ma_linear_resampler_interpolate_frame_f32(pResampler, pFramesOutF32);
32904 
32905  /* Filter. */
32906  ma_lpf_process_pcm_frame_f32(&pResampler->lpf, pFramesOutF32, pFramesOutF32);
32907 
32908  pFramesOutF32 += pResampler->config.channels;
32909  }
32910 
32911  framesProcessedOut += 1;
32912 
32913  /* Advance time forward. */
32914  pResampler->inTimeInt += pResampler->inAdvanceInt;
32915  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
32916  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
32917  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
32918  pResampler->inTimeInt += 1;
32919  }
32920  }
32921 
32922  *pFrameCountIn = framesProcessedIn;
32923  *pFrameCountOut = framesProcessedOut;
32924 
32925  return MA_SUCCESS;
32926 }
32927 
32928 static ma_result ma_linear_resampler_process_pcm_frames_f32(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32929 {
32930  MA_ASSERT(pResampler != NULL);
32931 
32932  if (pResampler->config.sampleRateIn > pResampler->config.sampleRateOut) {
32933  return ma_linear_resampler_process_pcm_frames_f32_downsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
32934  } else {
32935  return ma_linear_resampler_process_pcm_frames_f32_upsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
32936  }
32937 }
32938 
32939 
32940 MA_API ma_result ma_linear_resampler_process_pcm_frames(ma_linear_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
32941 {
32942  if (pResampler == NULL) {
32943  return MA_INVALID_ARGS;
32944  }
32945 
32946  /* */ if (pResampler->config.format == ma_format_s16) {
32947  return ma_linear_resampler_process_pcm_frames_s16(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
32948  } else if (pResampler->config.format == ma_format_f32) {
32949  return ma_linear_resampler_process_pcm_frames_f32(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
32950  } else {
32951  /* Should never get here. Getting here means the format is not supported and you didn't check the return value of ma_linear_resampler_init(). */
32953  return MA_INVALID_ARGS;
32954  }
32955 }
32956 
32957 
32959 {
32960  return ma_linear_resampler_set_rate_internal(pResampler, sampleRateIn, sampleRateOut, /* isResamplerAlreadyInitialized = */ MA_TRUE);
32961 }
32962 
32964 {
32965  ma_uint32 n;
32966  ma_uint32 d;
32967 
32968  d = 1000;
32969  n = (ma_uint32)(ratioInOut * d);
32970 
32971  if (n == 0) {
32972  return MA_INVALID_ARGS; /* Ratio too small. */
32973  }
32974 
32975  MA_ASSERT(n != 0);
32976 
32977  return ma_linear_resampler_set_rate(pResampler, n, d);
32978 }
32979 
32980 
32982 {
32983  ma_uint64 inputFrameCount;
32984 
32985  if (pResampler == NULL) {
32986  return 0;
32987  }
32988 
32989  if (outputFrameCount == 0) {
32990  return 0;
32991  }
32992 
32993  /* Any whole input frames are consumed before the first output frame is generated. */
32994  inputFrameCount = pResampler->inTimeInt;
32995  outputFrameCount -= 1;
32996 
32997  /* The rest of the output frames can be calculated in constant time. */
32998  inputFrameCount += outputFrameCount * pResampler->inAdvanceInt;
32999  inputFrameCount += (pResampler->inTimeFrac + (outputFrameCount * pResampler->inAdvanceFrac)) / pResampler->config.sampleRateOut;
33000 
33001  return inputFrameCount;
33002 }
33003 
33005 {
33006  ma_uint64 outputFrameCount;
33007  ma_uint64 preliminaryInputFrameCountFromFrac;
33008  ma_uint64 preliminaryInputFrameCount;
33009 
33010  if (pResampler == NULL) {
33011  return 0;
33012  }
33013 
33014  /*
33015  The first step is to get a preliminary output frame count. This will either be exactly equal to what we need, or less by 1. We need to
33016  determine how many input frames will be consumed by this value. If it's greater than our original input frame count it means we won't
33017  be able to generate an extra frame because we will have run out of input data. Otherwise we will have enough input for the generation
33018  of an extra output frame. This add-by-one logic is necessary due to how the data loading logic works when processing frames.
33019  */
33020  outputFrameCount = (inputFrameCount * pResampler->config.sampleRateOut) / pResampler->config.sampleRateIn;
33021 
33022  /*
33023  We need to determine how many *whole* input frames will have been processed to generate our preliminary output frame count. This is
33024  used in the logic below to determine whether or not we need to add an extra output frame.
33025  */
33026  preliminaryInputFrameCountFromFrac = (pResampler->inTimeFrac + outputFrameCount*pResampler->inAdvanceFrac) / pResampler->config.sampleRateOut;
33027  preliminaryInputFrameCount = (pResampler->inTimeInt + outputFrameCount*pResampler->inAdvanceInt ) + preliminaryInputFrameCountFromFrac;
33028 
33029  /*
33030  If the total number of *whole* input frames that would be required to generate our preliminary output frame count is greather than
33031  the amount of whole input frames we have available as input we need to *not* add an extra output frame as there won't be enough data
33032  to actually process. Otherwise we need to add the extra output frame.
33033  */
33034  if (preliminaryInputFrameCount <= inputFrameCount) {
33035  outputFrameCount += 1;
33036  }
33037 
33038  return outputFrameCount;
33039 }
33040 
33042 {
33043  if (pResampler == NULL) {
33044  return 0;
33045  }
33046 
33047  return 1 + ma_lpf_get_latency(&pResampler->lpf);
33048 }
33049 
33051 {
33052  if (pResampler == NULL) {
33053  return 0;
33054  }
33055 
33056  return ma_linear_resampler_get_input_latency(pResampler) * pResampler->config.sampleRateOut / pResampler->config.sampleRateIn;
33057 }
33058 
33059 
33060 #if defined(ma_speex_resampler_h)
33061 #define MA_HAS_SPEEX_RESAMPLER
33062 
33063 static ma_result ma_result_from_speex_err(int err)
33064 {
33065  switch (err)
33066  {
33067  case RESAMPLER_ERR_SUCCESS: return MA_SUCCESS;
33069  case RESAMPLER_ERR_BAD_STATE: return MA_ERROR;
33072  case RESAMPLER_ERR_OVERFLOW: return MA_ERROR;
33073  default: return MA_ERROR;
33074  }
33075 }
33076 #endif /* ma_speex_resampler_h */
33077 
33079 {
33081 
33083  config.format = format;
33084  config.channels = channels;
33085  config.sampleRateIn = sampleRateIn;
33086  config.sampleRateOut = sampleRateOut;
33087  config.algorithm = algorithm;
33088 
33089  /* Linear. */
33091  config.linear.lpfNyquistFactor = 1;
33092 
33093  /* Speex. */
33094  config.speex.quality = 3; /* Cannot leave this as 0 as that is actually a valid value for Speex resampling quality. */
33095 
33096  return config;
33097 }
33098 
33100 {
33101  ma_result result;
33102 
33103  if (pResampler == NULL) {
33104  return MA_INVALID_ARGS;
33105  }
33106 
33107  MA_ZERO_OBJECT(pResampler);
33108 
33109  if (pConfig == NULL) {
33110  return MA_INVALID_ARGS;
33111  }
33112 
33113  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
33114  return MA_INVALID_ARGS;
33115  }
33116 
33117  pResampler->config = *pConfig;
33118 
33119  switch (pConfig->algorithm)
33120  {
33122  {
33123  ma_linear_resampler_config linearConfig;
33124  linearConfig = ma_linear_resampler_config_init(pConfig->format, pConfig->channels, pConfig->sampleRateIn, pConfig->sampleRateOut);
33125  linearConfig.lpfOrder = pConfig->linear.lpfOrder;
33126  linearConfig.lpfNyquistFactor = pConfig->linear.lpfNyquistFactor;
33127 
33128  result = ma_linear_resampler_init(&linearConfig, &pResampler->state.linear);
33129  if (result != MA_SUCCESS) {
33130  return result;
33131  }
33132  } break;
33133 
33135  {
33136  #if defined(MA_HAS_SPEEX_RESAMPLER)
33137  int speexErr;
33138  pResampler->state.speex.pSpeexResamplerState = speex_resampler_init(pConfig->channels, pConfig->sampleRateIn, pConfig->sampleRateOut, pConfig->speex.quality, &speexErr);
33139  if (pResampler->state.speex.pSpeexResamplerState == NULL) {
33140  return ma_result_from_speex_err(speexErr);
33141  }
33142  #else
33143  /* Speex resampler not available. */
33144  return MA_NO_BACKEND;
33145  #endif
33146  } break;
33147 
33148  default: return MA_INVALID_ARGS;
33149  }
33150 
33151  return MA_SUCCESS;
33152 }
33153 
33155 {
33156  if (pResampler == NULL) {
33157  return;
33158  }
33159 
33160  if (pResampler->config.algorithm == ma_resample_algorithm_linear) {
33161  ma_linear_resampler_uninit(&pResampler->state.linear);
33162  }
33163 
33164 #if defined(MA_HAS_SPEEX_RESAMPLER)
33165  if (pResampler->config.algorithm == ma_resample_algorithm_speex) {
33166  speex_resampler_destroy((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState);
33167  }
33168 #endif
33169 }
33170 
33171 static ma_result ma_resampler_process_pcm_frames__read__linear(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
33172 {
33173  return ma_linear_resampler_process_pcm_frames(&pResampler->state.linear, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
33174 }
33175 
33176 #if defined(MA_HAS_SPEEX_RESAMPLER)
33177 static ma_result ma_resampler_process_pcm_frames__read__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
33178 {
33179  int speexErr;
33180  ma_uint64 frameCountOut;
33181  ma_uint64 frameCountIn;
33182  ma_uint64 framesProcessedOut;
33183  ma_uint64 framesProcessedIn;
33184  unsigned int framesPerIteration = UINT_MAX;
33185 
33186  MA_ASSERT(pResampler != NULL);
33187  MA_ASSERT(pFramesOut != NULL);
33188  MA_ASSERT(pFrameCountOut != NULL);
33189  MA_ASSERT(pFrameCountIn != NULL);
33190 
33191  /*
33192  Reading from the Speex resampler requires a bit of dancing around for a few reasons. The first thing is that it's frame counts
33193  are in unsigned int's whereas ours is in ma_uint64. We therefore need to run the conversion in a loop. The other, more complicated
33194  problem, is that we need to keep track of the input time, similar to what we do with the linear resampler. The reason we need to
33195  do this is for ma_resampler_get_required_input_frame_count() and ma_resampler_get_expected_output_frame_count().
33196  */
33197  frameCountOut = *pFrameCountOut;
33198  frameCountIn = *pFrameCountIn;
33199  framesProcessedOut = 0;
33200  framesProcessedIn = 0;
33201 
33202  while (framesProcessedOut < frameCountOut && framesProcessedIn < frameCountIn) {
33203  unsigned int frameCountInThisIteration;
33204  unsigned int frameCountOutThisIteration;
33205  const void* pFramesInThisIteration;
33206  void* pFramesOutThisIteration;
33207 
33208  frameCountInThisIteration = framesPerIteration;
33209  if ((ma_uint64)frameCountInThisIteration > (frameCountIn - framesProcessedIn)) {
33210  frameCountInThisIteration = (unsigned int)(frameCountIn - framesProcessedIn);
33211  }
33212 
33213  frameCountOutThisIteration = framesPerIteration;
33214  if ((ma_uint64)frameCountOutThisIteration > (frameCountOut - framesProcessedOut)) {
33215  frameCountOutThisIteration = (unsigned int)(frameCountOut - framesProcessedOut);
33216  }
33217 
33218  pFramesInThisIteration = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels));
33219  pFramesOutThisIteration = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels));
33220 
33221  if (pResampler->config.format == ma_format_f32) {
33222  speexErr = speex_resampler_process_interleaved_float((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, (const float*)pFramesInThisIteration, &frameCountInThisIteration, (float*)pFramesOutThisIteration, &frameCountOutThisIteration);
33223  } else if (pResampler->config.format == ma_format_s16) {
33224  speexErr = speex_resampler_process_interleaved_int((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, (const spx_int16_t*)pFramesInThisIteration, &frameCountInThisIteration, (spx_int16_t*)pFramesOutThisIteration, &frameCountOutThisIteration);
33225  } else {
33226  /* Format not supported. Should never get here. */
33228  return MA_INVALID_OPERATION;
33229  }
33230 
33231  if (speexErr != RESAMPLER_ERR_SUCCESS) {
33232  return ma_result_from_speex_err(speexErr);
33233  }
33234 
33235  framesProcessedIn += frameCountInThisIteration;
33236  framesProcessedOut += frameCountOutThisIteration;
33237  }
33238 
33239  *pFrameCountOut = framesProcessedOut;
33240  *pFrameCountIn = framesProcessedIn;
33241 
33242  return MA_SUCCESS;
33243 }
33244 #endif
33245 
33246 static ma_result ma_resampler_process_pcm_frames__read(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
33247 {
33248  MA_ASSERT(pResampler != NULL);
33249  MA_ASSERT(pFramesOut != NULL);
33250 
33251  /* pFramesOut is not NULL, which means we must have a capacity. */
33252  if (pFrameCountOut == NULL) {
33253  return MA_INVALID_ARGS;
33254  }
33255 
33256  /* It doesn't make sense to not have any input frames to process. */
33257  if (pFrameCountIn == NULL || pFramesIn == NULL) {
33258  return MA_INVALID_ARGS;
33259  }
33260 
33261  switch (pResampler->config.algorithm)
33262  {
33264  {
33265  return ma_resampler_process_pcm_frames__read__linear(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
33266  }
33267 
33269  {
33270  #if defined(MA_HAS_SPEEX_RESAMPLER)
33271  return ma_resampler_process_pcm_frames__read__speex(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
33272  #else
33273  break;
33274  #endif
33275  }
33276 
33277  default: break;
33278  }
33279 
33280  /* Should never get here. */
33282  return MA_INVALID_ARGS;
33283 }
33284 
33285 
33286 static ma_result ma_resampler_process_pcm_frames__seek__linear(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
33287 {
33288  MA_ASSERT(pResampler != NULL);
33289 
33290  /* Seeking is supported natively by the linear resampler. */
33291  return ma_linear_resampler_process_pcm_frames(&pResampler->state.linear, pFramesIn, pFrameCountIn, NULL, pFrameCountOut);
33292 }
33293 
33294 #if defined(MA_HAS_SPEEX_RESAMPLER)
33295 static ma_result ma_resampler_process_pcm_frames__seek__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
33296 {
33297  /* The generic seek method is implemented in on top of ma_resampler_process_pcm_frames__read() by just processing into a dummy buffer. */
33298  float devnull[4096];
33299  ma_uint64 totalOutputFramesToProcess;
33300  ma_uint64 totalOutputFramesProcessed;
33301  ma_uint64 totalInputFramesProcessed;
33302  ma_uint32 bpf;
33303  ma_result result;
33304 
33305  MA_ASSERT(pResampler != NULL);
33306 
33307  totalOutputFramesProcessed = 0;
33308  totalInputFramesProcessed = 0;
33309  bpf = ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels);
33310 
33311  if (pFrameCountOut != NULL) {
33312  /* Seek by output frames. */
33313  totalOutputFramesToProcess = *pFrameCountOut;
33314  } else {
33315  /* Seek by input frames. */
33316  MA_ASSERT(pFrameCountIn != NULL);
33317  totalOutputFramesToProcess = ma_resampler_get_expected_output_frame_count(pResampler, *pFrameCountIn);
33318  }
33319 
33320  if (pFramesIn != NULL) {
33321  /* Process input data. */
33322  MA_ASSERT(pFrameCountIn != NULL);
33323  while (totalOutputFramesProcessed < totalOutputFramesToProcess && totalInputFramesProcessed < *pFrameCountIn) {
33324  ma_uint64 inputFramesToProcessThisIteration = (*pFrameCountIn - totalInputFramesProcessed);
33325  ma_uint64 outputFramesToProcessThisIteration = (totalOutputFramesToProcess - totalOutputFramesProcessed);
33326  if (outputFramesToProcessThisIteration > sizeof(devnull) / bpf) {
33327  outputFramesToProcessThisIteration = sizeof(devnull) / bpf;
33328  }
33329 
33330  result = ma_resampler_process_pcm_frames__read(pResampler, ma_offset_ptr(pFramesIn, totalInputFramesProcessed*bpf), &inputFramesToProcessThisIteration, ma_offset_ptr(devnull, totalOutputFramesProcessed*bpf), &outputFramesToProcessThisIteration);
33331  if (result != MA_SUCCESS) {
33332  return result;
33333  }
33334 
33335  totalOutputFramesProcessed += outputFramesToProcessThisIteration;
33336  totalInputFramesProcessed += inputFramesToProcessThisIteration;
33337  }
33338  } else {
33339  /* Don't process input data - just update timing and filter state as if zeroes were passed in. */
33340  while (totalOutputFramesProcessed < totalOutputFramesToProcess) {
33341  ma_uint64 inputFramesToProcessThisIteration = 16384;
33342  ma_uint64 outputFramesToProcessThisIteration = (totalOutputFramesToProcess - totalOutputFramesProcessed);
33343  if (outputFramesToProcessThisIteration > sizeof(devnull) / bpf) {
33344  outputFramesToProcessThisIteration = sizeof(devnull) / bpf;
33345  }
33346 
33347  result = ma_resampler_process_pcm_frames__read(pResampler, NULL, &inputFramesToProcessThisIteration, ma_offset_ptr(devnull, totalOutputFramesProcessed*bpf), &outputFramesToProcessThisIteration);
33348  if (result != MA_SUCCESS) {
33349  return result;
33350  }
33351 
33352  totalOutputFramesProcessed += outputFramesToProcessThisIteration;
33353  totalInputFramesProcessed += inputFramesToProcessThisIteration;
33354  }
33355  }
33356 
33357 
33358  if (pFrameCountIn != NULL) {
33359  *pFrameCountIn = totalInputFramesProcessed;
33360  }
33361  if (pFrameCountOut != NULL) {
33362  *pFrameCountOut = totalOutputFramesProcessed;
33363  }
33364 
33365  return MA_SUCCESS;
33366 }
33367 #endif
33368 
33369 static ma_result ma_resampler_process_pcm_frames__seek(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
33370 {
33371  MA_ASSERT(pResampler != NULL);
33372 
33373  switch (pResampler->config.algorithm)
33374  {
33376  {
33377  return ma_resampler_process_pcm_frames__seek__linear(pResampler, pFramesIn, pFrameCountIn, pFrameCountOut);
33378  } break;
33379 
33381  {
33382  #if defined(MA_HAS_SPEEX_RESAMPLER)
33383  return ma_resampler_process_pcm_frames__seek__speex(pResampler, pFramesIn, pFrameCountIn, pFrameCountOut);
33384  #else
33385  break;
33386  #endif
33387  };
33388 
33389  default: break;
33390  }
33391 
33392  /* Should never hit this. */
33394  return MA_INVALID_ARGS;
33395 }
33396 
33397 
33398 MA_API ma_result ma_resampler_process_pcm_frames(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
33399 {
33400  if (pResampler == NULL) {
33401  return MA_INVALID_ARGS;
33402  }
33403 
33404  if (pFrameCountOut == NULL && pFrameCountIn == NULL) {
33405  return MA_INVALID_ARGS;
33406  }
33407 
33408  if (pFramesOut != NULL) {
33409  /* Reading. */
33410  return ma_resampler_process_pcm_frames__read(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
33411  } else {
33412  /* Seeking. */
33413  return ma_resampler_process_pcm_frames__seek(pResampler, pFramesIn, pFrameCountIn, pFrameCountOut);
33414  }
33415 }
33416 
33417 MA_API ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
33418 {
33419  if (pResampler == NULL) {
33420  return MA_INVALID_ARGS;
33421  }
33422 
33423  if (sampleRateIn == 0 || sampleRateOut == 0) {
33424  return MA_INVALID_ARGS;
33425  }
33426 
33427  pResampler->config.sampleRateIn = sampleRateIn;
33428  pResampler->config.sampleRateOut = sampleRateOut;
33429 
33430  switch (pResampler->config.algorithm)
33431  {
33433  {
33434  return ma_linear_resampler_set_rate(&pResampler->state.linear, sampleRateIn, sampleRateOut);
33435  } break;
33436 
33438  {
33439  #if defined(MA_HAS_SPEEX_RESAMPLER)
33440  return ma_result_from_speex_err(speex_resampler_set_rate((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, sampleRateIn, sampleRateOut));
33441  #else
33442  break;
33443  #endif
33444  };
33445 
33446  default: break;
33447  }
33448 
33449  /* Should never get here. */
33451  return MA_INVALID_OPERATION;
33452 }
33453 
33455 {
33456  if (pResampler == NULL) {
33457  return MA_INVALID_ARGS;
33458  }
33459 
33460  if (pResampler->config.algorithm == ma_resample_algorithm_linear) {
33461  return ma_linear_resampler_set_rate_ratio(&pResampler->state.linear, ratio);
33462  } else {
33463  /* Getting here means the backend does not have native support for setting the rate as a ratio so we just do it generically. */
33464  ma_uint32 n;
33465  ma_uint32 d;
33466 
33467  d = 1000;
33468  n = (ma_uint32)(ratio * d);
33469 
33470  if (n == 0) {
33471  return MA_INVALID_ARGS; /* Ratio too small. */
33472  }
33473 
33474  MA_ASSERT(n != 0);
33475 
33476  return ma_resampler_set_rate(pResampler, n, d);
33477  }
33478 }
33479 
33481 {
33482  if (pResampler == NULL) {
33483  return 0;
33484  }
33485 
33486  if (outputFrameCount == 0) {
33487  return 0;
33488  }
33489 
33490  switch (pResampler->config.algorithm)
33491  {
33493  {
33494  return ma_linear_resampler_get_required_input_frame_count(&pResampler->state.linear, outputFrameCount);
33495  }
33496 
33498  {
33499  #if defined(MA_HAS_SPEEX_RESAMPLER)
33501  int speexErr = ma_speex_resampler_get_required_input_frame_count((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, outputFrameCount, &count);
33502  if (speexErr != RESAMPLER_ERR_SUCCESS) {
33503  return 0;
33504  }
33505 
33506  return (ma_uint64)count;
33507  #else
33508  break;
33509  #endif
33510  }
33511 
33512  default: break;
33513  }
33514 
33515  /* Should never get here. */
33517  return 0;
33518 }
33519 
33521 {
33522  if (pResampler == NULL) {
33523  return 0; /* Invalid args. */
33524  }
33525 
33526  if (inputFrameCount == 0) {
33527  return 0;
33528  }
33529 
33530  switch (pResampler->config.algorithm)
33531  {
33533  {
33534  return ma_linear_resampler_get_expected_output_frame_count(&pResampler->state.linear, inputFrameCount);
33535  }
33536 
33538  {
33539  #if defined(MA_HAS_SPEEX_RESAMPLER)
33541  int speexErr = ma_speex_resampler_get_expected_output_frame_count((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, inputFrameCount, &count);
33542  if (speexErr != RESAMPLER_ERR_SUCCESS) {
33543  return 0;
33544  }
33545 
33546  return (ma_uint64)count;
33547  #else
33548  break;
33549  #endif
33550  }
33551 
33552  default: break;
33553  }
33554 
33555  /* Should never get here. */
33557  return 0;
33558 }
33559 
33561 {
33562  if (pResampler == NULL) {
33563  return 0;
33564  }
33565 
33566  switch (pResampler->config.algorithm)
33567  {
33569  {
33570  return ma_linear_resampler_get_input_latency(&pResampler->state.linear);
33571  }
33572 
33574  {
33575  #if defined(MA_HAS_SPEEX_RESAMPLER)
33576  return (ma_uint64)ma_speex_resampler_get_input_latency((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState);
33577  #else
33578  break;
33579  #endif
33580  }
33581 
33582  default: break;
33583  }
33584 
33585  /* Should never get here. */
33587  return 0;
33588 }
33589 
33591 {
33592  if (pResampler == NULL) {
33593  return 0;
33594  }
33595 
33596  switch (pResampler->config.algorithm)
33597  {
33599  {
33601  }
33602 
33604  {
33605  #if defined(MA_HAS_SPEEX_RESAMPLER)
33606  return (ma_uint64)ma_speex_resampler_get_output_latency((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState);
33607  #else
33608  break;
33609  #endif
33610  }
33611 
33612  default: break;
33613  }
33614 
33615  /* Should never get here. */
33617  return 0;
33618 }
33619 
33620 /**************************************************************************************************************************************************************
33621 
33622 Channel Conversion
33623 
33624 **************************************************************************************************************************************************************/
33625 #ifndef MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT
33626 #define MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT 12
33627 #endif
33628 
33629 #define MA_PLANE_LEFT 0
33630 #define MA_PLANE_RIGHT 1
33631 #define MA_PLANE_FRONT 2
33632 #define MA_PLANE_BACK 3
33633 #define MA_PLANE_BOTTOM 4
33634 #define MA_PLANE_TOP 5
33635 
33636 static float g_maChannelPlaneRatios[MA_CHANNEL_POSITION_COUNT][6] = {
33637  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_NONE */
33638  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_MONO */
33639  { 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_LEFT */
33640  { 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_RIGHT */
33641  { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_CENTER */
33642  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_LFE */
33643  { 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}, /* MA_CHANNEL_BACK_LEFT */
33644  { 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f}, /* MA_CHANNEL_BACK_RIGHT */
33645  { 0.25f, 0.0f, 0.75f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_LEFT_CENTER */
33646  { 0.0f, 0.25f, 0.75f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_RIGHT_CENTER */
33647  { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, /* MA_CHANNEL_BACK_CENTER */
33648  { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_SIDE_LEFT */
33649  { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_SIDE_RIGHT */
33650  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, /* MA_CHANNEL_TOP_CENTER */
33651  { 0.33f, 0.0f, 0.33f, 0.0f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_FRONT_LEFT */
33652  { 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f}, /* MA_CHANNEL_TOP_FRONT_CENTER */
33653  { 0.0f, 0.33f, 0.33f, 0.0f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_FRONT_RIGHT */
33654  { 0.33f, 0.0f, 0.0f, 0.33f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_BACK_LEFT */
33655  { 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f}, /* MA_CHANNEL_TOP_BACK_CENTER */
33656  { 0.0f, 0.33f, 0.0f, 0.33f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_BACK_RIGHT */
33657  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_0 */
33658  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_1 */
33659  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_2 */
33660  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_3 */
33661  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_4 */
33662  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_5 */
33663  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_6 */
33664  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_7 */
33665  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_8 */
33666  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_9 */
33667  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_10 */
33668  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_11 */
33669  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_12 */
33670  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_13 */
33671  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_14 */
33672  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_15 */
33673  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_16 */
33674  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_17 */
33675  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_18 */
33676  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_19 */
33677  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_20 */
33678  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_21 */
33679  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_22 */
33680  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_23 */
33681  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_24 */
33682  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_25 */
33683  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_26 */
33684  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_27 */
33685  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_28 */
33686  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_29 */
33687  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_30 */
33688  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_31 */
33689 };
33690 
33691 static float ma_calculate_channel_position_rectangular_weight(ma_channel channelPositionA, ma_channel channelPositionB)
33692 {
33693  /*
33694  Imagine the following simplified example: You have a single input speaker which is the front/left speaker which you want to convert to
33695  the following output configuration:
33696 
33697  - front/left
33698  - side/left
33699  - back/left
33700 
33701  The front/left output is easy - it the same speaker position so it receives the full contribution of the front/left input. The amount
33702  of contribution to apply to the side/left and back/left speakers, however, is a bit more complicated.
33703 
33704  Imagine the front/left speaker as emitting audio from two planes - the front plane and the left plane. You can think of the front/left
33705  speaker emitting half of it's total volume from the front, and the other half from the left. Since part of it's volume is being emitted
33706  from the left side, and the side/left and back/left channels also emit audio from the left plane, one would expect that they would
33707  receive some amount of contribution from front/left speaker. The amount of contribution depends on how many planes are shared between
33708  the two speakers. Note that in the examples below I've added a top/front/left speaker as an example just to show how the math works
33709  across 3 spatial dimensions.
33710 
33711  The first thing to do is figure out how each speaker's volume is spread over each of plane:
33712  - front/left: 2 planes (front and left) = 1/2 = half it's total volume on each plane
33713  - side/left: 1 plane (left only) = 1/1 = entire volume from left plane
33714  - back/left: 2 planes (back and left) = 1/2 = half it's total volume on each plane
33715  - top/front/left: 3 planes (top, front and left) = 1/3 = one third it's total volume on each plane
33716 
33717  The amount of volume each channel contributes to each of it's planes is what controls how much it is willing to given and take to other
33718  channels on the same plane. The volume that is willing to the given by one channel is multiplied by the volume that is willing to be
33719  taken by the other to produce the final contribution.
33720  */
33721 
33722  /* Contribution = Sum(Volume to Give * Volume to Take) */
33723  float contribution =
33724  g_maChannelPlaneRatios[channelPositionA][0] * g_maChannelPlaneRatios[channelPositionB][0] +
33725  g_maChannelPlaneRatios[channelPositionA][1] * g_maChannelPlaneRatios[channelPositionB][1] +
33726  g_maChannelPlaneRatios[channelPositionA][2] * g_maChannelPlaneRatios[channelPositionB][2] +
33727  g_maChannelPlaneRatios[channelPositionA][3] * g_maChannelPlaneRatios[channelPositionB][3] +
33728  g_maChannelPlaneRatios[channelPositionA][4] * g_maChannelPlaneRatios[channelPositionB][4] +
33729  g_maChannelPlaneRatios[channelPositionA][5] * g_maChannelPlaneRatios[channelPositionB][5];
33730 
33731  return contribution;
33732 }
33733 
33734 MA_API ma_channel_converter_config ma_channel_converter_config_init(ma_format format, ma_uint32 channelsIn, const ma_channel* pChannelMapIn, ma_uint32 channelsOut, const ma_channel* pChannelMapOut, ma_channel_mix_mode mixingMode)
33735 {
33737 
33738  /* Channel counts need to be clamped. */
33739  channelsIn = ma_min(channelsIn, ma_countof(config.channelMapIn));
33740  channelsOut = ma_min(channelsOut, ma_countof(config.channelMapOut));
33741 
33743  config.format = format;
33744  config.channelsIn = channelsIn;
33745  config.channelsOut = channelsOut;
33746  ma_channel_map_copy_or_default(config.channelMapIn, pChannelMapIn, channelsIn);
33747  ma_channel_map_copy_or_default(config.channelMapOut, pChannelMapOut, channelsOut);
33748  config.mixingMode = mixingMode;
33749 
33750  return config;
33751 }
33752 
33754 {
33756 }
33757 
33759 {
33760  int i;
33761 
33762  if (channelPosition == MA_CHANNEL_NONE || channelPosition == MA_CHANNEL_MONO || channelPosition == MA_CHANNEL_LFE) {
33763  return MA_FALSE;
33764  }
33765 
33766  if (channelPosition >= MA_CHANNEL_AUX_0 && channelPosition <= MA_CHANNEL_AUX_31) {
33767  return MA_FALSE;
33768  }
33769 
33770  for (i = 0; i < 6; ++i) { /* Each side of a cube. */
33771  if (g_maChannelPlaneRatios[channelPosition][i] != 0) {
33772  return MA_TRUE;
33773  }
33774  }
33775 
33776  return MA_FALSE;
33777 }
33778 
33780 {
33781  ma_uint32 iChannelIn;
33782  ma_uint32 iChannelOut;
33783 
33784  if (pConverter == NULL) {
33785  return MA_INVALID_ARGS;
33786  }
33787 
33788  MA_ZERO_OBJECT(pConverter);
33789 
33790  if (pConfig == NULL) {
33791  return MA_INVALID_ARGS;
33792  }
33793 
33794  /* Basic validation for channel counts. */
33795  if (pConfig->channelsIn < MA_MIN_CHANNELS || pConfig->channelsIn > MA_MAX_CHANNELS ||
33796  pConfig->channelsOut < MA_MIN_CHANNELS || pConfig->channelsOut > MA_MAX_CHANNELS) {
33797  return MA_INVALID_ARGS;
33798  }
33799 
33800  if (!ma_channel_map_valid(pConfig->channelsIn, pConfig->channelMapIn)) {
33801  return MA_INVALID_ARGS; /* Invalid input channel map. */
33802  }
33803  if (!ma_channel_map_valid(pConfig->channelsOut, pConfig->channelMapOut)) {
33804  return MA_INVALID_ARGS; /* Invalid output channel map. */
33805  }
33806 
33807  pConverter->format = pConfig->format;
33808  pConverter->channelsIn = pConfig->channelsIn;
33809  pConverter->channelsOut = pConfig->channelsOut;
33810  ma_channel_map_copy_or_default(pConverter->channelMapIn, pConfig->channelMapIn, pConfig->channelsIn);
33811  ma_channel_map_copy_or_default(pConverter->channelMapOut, pConfig->channelMapOut, pConfig->channelsOut);
33812  pConverter->mixingMode = pConfig->mixingMode;
33813 
33814  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; iChannelIn += 1) {
33815  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
33816  if (pConverter->format == ma_format_f32) {
33817  pConverter->weights.f32[iChannelIn][iChannelOut] = pConfig->weights[iChannelIn][iChannelOut];
33818  } else {
33819  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(pConfig->weights[iChannelIn][iChannelOut]);
33820  }
33821  }
33822  }
33823 
33824 
33825 
33826  /* If the input and output channels and channel maps are the same we should use a passthrough. */
33827  if (pConverter->channelsIn == pConverter->channelsOut) {
33828  if (ma_channel_map_equal(pConverter->channelsIn, pConverter->channelMapIn, pConverter->channelMapOut)) {
33829  pConverter->isPassthrough = MA_TRUE;
33830  }
33831  if (ma_channel_map_blank(pConverter->channelsIn, pConverter->channelMapIn) || ma_channel_map_blank(pConverter->channelsOut, pConverter->channelMapOut)) {
33832  pConverter->isPassthrough = MA_TRUE;
33833  }
33834  }
33835 
33836 
33837  /*
33838  We can use a simple case for expanding the mono channel. This will used when expanding a mono input into any output so long
33839  as no LFE is present in the output.
33840  */
33841  if (!pConverter->isPassthrough) {
33842  if (pConverter->channelsIn == 1 && pConverter->channelMapIn[0] == MA_CHANNEL_MONO) {
33843  /* Optimal case if no LFE is in the output channel map. */
33844  pConverter->isSimpleMonoExpansion = MA_TRUE;
33846  pConverter->isSimpleMonoExpansion = MA_FALSE;
33847  }
33848  }
33849  }
33850 
33851  /* Another optimized case is stereo to mono. */
33852  if (!pConverter->isPassthrough) {
33853  if (pConverter->channelsOut == 1 && pConverter->channelMapOut[0] == MA_CHANNEL_MONO && pConverter->channelsIn == 2) {
33854  /* Optimal case if no LFE is in the input channel map. */
33855  pConverter->isStereoToMono = MA_TRUE;
33857  pConverter->isStereoToMono = MA_FALSE;
33858  }
33859  }
33860  }
33861 
33862 
33863  /*
33864  Here is where we do a bit of pre-processing to know how each channel should be combined to make up the output. Rules:
33865 
33866  1) If it's a passthrough, do nothing - it's just a simple memcpy().
33867  2) If the channel counts are the same and every channel position in the input map is present in the output map, use a
33868  simple shuffle. An example might be different 5.1 channel layouts.
33869  3) Otherwise channels are blended based on spatial locality.
33870  */
33871  if (!pConverter->isPassthrough) {
33872  if (pConverter->channelsIn == pConverter->channelsOut) {
33873  ma_bool32 areAllChannelPositionsPresent = MA_TRUE;
33874  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33875  ma_bool32 isInputChannelPositionInOutput = MA_FALSE;
33876  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
33877  if (pConverter->channelMapIn[iChannelIn] == pConverter->channelMapOut[iChannelOut]) {
33878  isInputChannelPositionInOutput = MA_TRUE;
33879  break;
33880  }
33881  }
33882 
33883  if (!isInputChannelPositionInOutput) {
33884  areAllChannelPositionsPresent = MA_FALSE;
33885  break;
33886  }
33887  }
33888 
33889  if (areAllChannelPositionsPresent) {
33890  pConverter->isSimpleShuffle = MA_TRUE;
33891 
33892  /*
33893  All the router will be doing is rearranging channels which means all we need to do is use a shuffling table which is just
33894  a mapping between the index of the input channel to the index of the output channel.
33895  */
33896  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33897  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
33898  if (pConverter->channelMapIn[iChannelIn] == pConverter->channelMapOut[iChannelOut]) {
33899  pConverter->shuffleTable[iChannelIn] = (ma_uint8)iChannelOut;
33900  break;
33901  }
33902  }
33903  }
33904  }
33905  }
33906  }
33907 
33908 
33909  /*
33910  Here is where weights are calculated. Note that we calculate the weights at all times, even when using a passthrough and simple
33911  shuffling. We use different algorithms for calculating weights depending on our mixing mode.
33912 
33913  In simple mode we don't do any blending (except for converting between mono, which is done in a later step). Instead we just
33914  map 1:1 matching channels. In this mode, if no channels in the input channel map correspond to anything in the output channel
33915  map, nothing will be heard!
33916  */
33917 
33918  /* In all cases we need to make sure all channels that are present in both channel maps have a 1:1 mapping. */
33919  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33920  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
33921 
33922  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
33923  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
33924 
33925  if (channelPosIn == channelPosOut) {
33926  if (pConverter->format == ma_format_f32) {
33927  pConverter->weights.f32[iChannelIn][iChannelOut] = 1;
33928  } else {
33929  pConverter->weights.s16[iChannelIn][iChannelOut] = (1 << MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT);
33930  }
33931  }
33932  }
33933  }
33934 
33935  /*
33936  The mono channel is accumulated on all other channels, except LFE. Make sure in this loop we exclude output mono channels since
33937  they were handled in the pass above.
33938  */
33939  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33940  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
33941 
33942  if (channelPosIn == MA_CHANNEL_MONO) {
33943  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
33944  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
33945 
33946  if (channelPosOut != MA_CHANNEL_NONE && channelPosOut != MA_CHANNEL_MONO && channelPosOut != MA_CHANNEL_LFE) {
33947  if (pConverter->format == ma_format_f32) {
33948  pConverter->weights.f32[iChannelIn][iChannelOut] = 1;
33949  } else {
33950  pConverter->weights.s16[iChannelIn][iChannelOut] = (1 << MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT);
33951  }
33952  }
33953  }
33954  }
33955  }
33956 
33957  /* The output mono channel is the average of all non-none, non-mono and non-lfe input channels. */
33958  {
33959  ma_uint32 len = 0;
33960  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33961  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
33962 
33963  if (channelPosIn != MA_CHANNEL_NONE && channelPosIn != MA_CHANNEL_MONO && channelPosIn != MA_CHANNEL_LFE) {
33964  len += 1;
33965  }
33966  }
33967 
33968  if (len > 0) {
33969  float monoWeight = 1.0f / len;
33970 
33971  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
33972  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
33973 
33974  if (channelPosOut == MA_CHANNEL_MONO) {
33975  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33976  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
33977 
33978  if (channelPosIn != MA_CHANNEL_NONE && channelPosIn != MA_CHANNEL_MONO && channelPosIn != MA_CHANNEL_LFE) {
33979  if (pConverter->format == ma_format_f32) {
33980  pConverter->weights.f32[iChannelIn][iChannelOut] = monoWeight;
33981  } else {
33982  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(monoWeight);
33983  }
33984  }
33985  }
33986  }
33987  }
33988  }
33989  }
33990 
33991 
33992  /* Input and output channels that are not present on the other side need to be blended in based on spatial locality. */
33993  switch (pConverter->mixingMode)
33994  {
33996  {
33997  /* Unmapped input channels. */
33998  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
33999  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
34000 
34001  if (ma_is_spatial_channel_position(channelPosIn)) {
34002  if (!ma_channel_map_contains_channel_position(pConverter->channelsOut, pConverter->channelMapOut, channelPosIn)) {
34003  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34004  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
34005 
34006  if (ma_is_spatial_channel_position(channelPosOut)) {
34007  float weight = 0;
34008  if (pConverter->mixingMode == ma_channel_mix_mode_rectangular) {
34009  weight = ma_calculate_channel_position_rectangular_weight(channelPosIn, channelPosOut);
34010  }
34011 
34012  /* Only apply the weight if we haven't already got some contribution from the respective channels. */
34013  if (pConverter->format == ma_format_f32) {
34014  if (pConverter->weights.f32[iChannelIn][iChannelOut] == 0) {
34015  pConverter->weights.f32[iChannelIn][iChannelOut] = weight;
34016  }
34017  } else {
34018  if (pConverter->weights.s16[iChannelIn][iChannelOut] == 0) {
34019  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(weight);
34020  }
34021  }
34022  }
34023  }
34024  }
34025  }
34026  }
34027 
34028  /* Unmapped output channels. */
34029  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34030  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
34031 
34032  if (ma_is_spatial_channel_position(channelPosOut)) {
34033  if (!ma_channel_map_contains_channel_position(pConverter->channelsIn, pConverter->channelMapIn, channelPosOut)) {
34034  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34035  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
34036 
34037  if (ma_is_spatial_channel_position(channelPosIn)) {
34038  float weight = 0;
34039  if (pConverter->mixingMode == ma_channel_mix_mode_rectangular) {
34040  weight = ma_calculate_channel_position_rectangular_weight(channelPosIn, channelPosOut);
34041  }
34042 
34043  /* Only apply the weight if we haven't already got some contribution from the respective channels. */
34044  if (pConverter->format == ma_format_f32) {
34045  if (pConverter->weights.f32[iChannelIn][iChannelOut] == 0) {
34046  pConverter->weights.f32[iChannelIn][iChannelOut] = weight;
34047  }
34048  } else {
34049  if (pConverter->weights.s16[iChannelIn][iChannelOut] == 0) {
34050  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(weight);
34051  }
34052  }
34053  }
34054  }
34055  }
34056  }
34057  }
34058  } break;
34059 
34061  {
34062  /* In simple mode, excess channels need to be silenced or dropped. */
34063  ma_uint32 iChannel;
34064  for (iChannel = 0; iChannel < ma_min(pConverter->channelsIn, pConverter->channelsOut); iChannel += 1) {
34065  if (pConverter->format == ma_format_f32) {
34066  if (pConverter->weights.f32[iChannel][iChannel] == 0) {
34067  pConverter->weights.f32[iChannel][iChannel] = 1;
34068  }
34069  } else {
34070  if (pConverter->weights.s16[iChannel][iChannel] == 0) {
34071  pConverter->weights.s16[iChannel][iChannel] = ma_channel_converter_float_to_fixed(1);
34072  }
34073  }
34074  }
34075  } break;
34076 
34078  default:
34079  {
34080  /* Fallthrough. */
34081  } break;
34082  }
34083 
34084 
34085  return MA_SUCCESS;
34086 }
34087 
34089 {
34090  if (pConverter == NULL) {
34091  return;
34092  }
34093 }
34094 
34095 static ma_result ma_channel_converter_process_pcm_frames__passthrough(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
34096 {
34097  MA_ASSERT(pConverter != NULL);
34098  MA_ASSERT(pFramesOut != NULL);
34099  MA_ASSERT(pFramesIn != NULL);
34100 
34101  ma_copy_memory_64(pFramesOut, pFramesIn, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
34102  return MA_SUCCESS;
34103 }
34104 
34105 static ma_result ma_channel_converter_process_pcm_frames__simple_shuffle(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
34106 {
34107  ma_uint32 iFrame;
34108  ma_uint32 iChannelIn;
34109 
34110  MA_ASSERT(pConverter != NULL);
34111  MA_ASSERT(pFramesOut != NULL);
34112  MA_ASSERT(pFramesIn != NULL);
34113  MA_ASSERT(pConverter->channelsIn == pConverter->channelsOut);
34114 
34115  switch (pConverter->format)
34116  {
34117  case ma_format_u8:
34118  {
34119  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
34120  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
34121 
34122  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34123  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34124  pFramesOutU8[pConverter->shuffleTable[iChannelIn]] = pFramesInU8[iChannelIn];
34125  }
34126 
34127  pFramesOutU8 += pConverter->channelsOut;
34128  pFramesInU8 += pConverter->channelsIn;
34129  }
34130  } break;
34131 
34132  case ma_format_s16:
34133  {
34134  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
34135  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
34136 
34137  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34138  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34139  pFramesOutS16[pConverter->shuffleTable[iChannelIn]] = pFramesInS16[iChannelIn];
34140  }
34141 
34142  pFramesOutS16 += pConverter->channelsOut;
34143  pFramesInS16 += pConverter->channelsIn;
34144  }
34145  } break;
34146 
34147  case ma_format_s24:
34148  {
34149  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
34150  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
34151 
34152  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34153  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34154  ma_uint32 iChannelOut = pConverter->shuffleTable[iChannelIn];
34155  pFramesOutS24[iChannelOut*3 + 0] = pFramesInS24[iChannelIn*3 + 0];
34156  pFramesOutS24[iChannelOut*3 + 1] = pFramesInS24[iChannelIn*3 + 1];
34157  pFramesOutS24[iChannelOut*3 + 2] = pFramesInS24[iChannelIn*3 + 2];
34158  }
34159 
34160  pFramesOutS24 += pConverter->channelsOut*3;
34161  pFramesInS24 += pConverter->channelsIn*3;
34162  }
34163  } break;
34164 
34165  case ma_format_s32:
34166  {
34167  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
34168  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
34169 
34170  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34171  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34172  pFramesOutS32[pConverter->shuffleTable[iChannelIn]] = pFramesInS32[iChannelIn];
34173  }
34174 
34175  pFramesOutS32 += pConverter->channelsOut;
34176  pFramesInS32 += pConverter->channelsIn;
34177  }
34178  } break;
34179 
34180  case ma_format_f32:
34181  {
34182  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
34183  const float* pFramesInF32 = (const float*)pFramesIn;
34184 
34185  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34186  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34187  pFramesOutF32[pConverter->shuffleTable[iChannelIn]] = pFramesInF32[iChannelIn];
34188  }
34189 
34190  pFramesOutF32 += pConverter->channelsOut;
34191  pFramesInF32 += pConverter->channelsIn;
34192  }
34193  } break;
34194 
34195  default: return MA_INVALID_OPERATION; /* Unknown format. */
34196  }
34197 
34198  return MA_SUCCESS;
34199 }
34200 
34201 static ma_result ma_channel_converter_process_pcm_frames__simple_mono_expansion(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
34202 {
34203  ma_uint64 iFrame;
34204 
34205  MA_ASSERT(pConverter != NULL);
34206  MA_ASSERT(pFramesOut != NULL);
34207  MA_ASSERT(pFramesIn != NULL);
34208  MA_ASSERT(pConverter->channelsIn == 1);
34209 
34210  switch (pConverter->format)
34211  {
34212  case ma_format_u8:
34213  {
34214  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
34215  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
34216 
34217  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34218  ma_uint32 iChannel;
34219  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
34220  pFramesOutU8[iFrame*pConverter->channelsOut + iChannel] = pFramesInU8[iFrame];
34221  }
34222  }
34223  } break;
34224 
34225  case ma_format_s16:
34226  {
34227  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
34228  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
34229 
34230  if (pConverter->channelsOut == 2) {
34231  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34232  pFramesOutS16[iFrame*2 + 0] = pFramesInS16[iFrame];
34233  pFramesOutS16[iFrame*2 + 1] = pFramesInS16[iFrame];
34234  }
34235  } else {
34236  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34237  ma_uint32 iChannel;
34238  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
34239  pFramesOutS16[iFrame*pConverter->channelsOut + iChannel] = pFramesInS16[iFrame];
34240  }
34241  }
34242  }
34243  } break;
34244 
34245  case ma_format_s24:
34246  {
34247  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
34248  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
34249 
34250  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34251  ma_uint32 iChannel;
34252  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
34253  ma_uint64 iSampleOut = iFrame*pConverter->channelsOut + iChannel;
34254  ma_uint64 iSampleIn = iFrame;
34255  pFramesOutS24[iSampleOut*3 + 0] = pFramesInS24[iSampleIn*3 + 0];
34256  pFramesOutS24[iSampleOut*3 + 1] = pFramesInS24[iSampleIn*3 + 1];
34257  pFramesOutS24[iSampleOut*3 + 2] = pFramesInS24[iSampleIn*3 + 2];
34258  }
34259  }
34260  } break;
34261 
34262  case ma_format_s32:
34263  {
34264  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
34265  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
34266 
34267  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34268  ma_uint32 iChannel;
34269  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
34270  pFramesOutS32[iFrame*pConverter->channelsOut + iChannel] = pFramesInS32[iFrame];
34271  }
34272  }
34273  } break;
34274 
34275  case ma_format_f32:
34276  {
34277  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
34278  const float* pFramesInF32 = (const float*)pFramesIn;
34279 
34280  if (pConverter->channelsOut == 2) {
34281  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34282  pFramesOutF32[iFrame*2 + 0] = pFramesInF32[iFrame];
34283  pFramesOutF32[iFrame*2 + 1] = pFramesInF32[iFrame];
34284  }
34285  } else {
34286  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34287  ma_uint32 iChannel;
34288  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
34289  pFramesOutF32[iFrame*pConverter->channelsOut + iChannel] = pFramesInF32[iFrame];
34290  }
34291  }
34292  }
34293  } break;
34294 
34295  default: return MA_INVALID_OPERATION; /* Unknown format. */
34296  }
34297 
34298  return MA_SUCCESS;
34299 }
34300 
34301 static ma_result ma_channel_converter_process_pcm_frames__stereo_to_mono(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
34302 {
34303  ma_uint64 iFrame;
34304 
34305  MA_ASSERT(pConverter != NULL);
34306  MA_ASSERT(pFramesOut != NULL);
34307  MA_ASSERT(pFramesIn != NULL);
34308  MA_ASSERT(pConverter->channelsIn == 2);
34309  MA_ASSERT(pConverter->channelsOut == 1);
34310 
34311  switch (pConverter->format)
34312  {
34313  case ma_format_u8:
34314  {
34315  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
34316  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
34317 
34318  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34319  pFramesOutU8[iFrame] = ma_clip_u8((ma_int16)((ma_pcm_sample_u8_to_s16_no_scale(pFramesInU8[iFrame*2+0]) + ma_pcm_sample_u8_to_s16_no_scale(pFramesInU8[iFrame*2+1])) / 2));
34320  }
34321  } break;
34322 
34323  case ma_format_s16:
34324  {
34325  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
34326  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
34327 
34328  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34329  pFramesOutS16[iFrame] = (ma_int16)(((ma_int32)pFramesInS16[iFrame*2+0] + (ma_int32)pFramesInS16[iFrame*2+1]) / 2);
34330  }
34331  } break;
34332 
34333  case ma_format_s24:
34334  {
34335  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
34336  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
34337 
34338  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34339  ma_int64 s24_0 = ma_pcm_sample_s24_to_s32_no_scale(&pFramesInS24[(iFrame*2+0)*3]);
34340  ma_int64 s24_1 = ma_pcm_sample_s24_to_s32_no_scale(&pFramesInS24[(iFrame*2+1)*3]);
34341  ma_pcm_sample_s32_to_s24_no_scale((s24_0 + s24_1) / 2, &pFramesOutS24[iFrame*3]);
34342  }
34343  } break;
34344 
34345  case ma_format_s32:
34346  {
34347  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
34348  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
34349 
34350  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34351  pFramesOutS32[iFrame] = (ma_int16)(((ma_int32)pFramesInS32[iFrame*2+0] + (ma_int32)pFramesInS32[iFrame*2+1]) / 2);
34352  }
34353  } break;
34354 
34355  case ma_format_f32:
34356  {
34357  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
34358  const float* pFramesInF32 = (const float*)pFramesIn;
34359 
34360  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
34361  pFramesOutF32[iFrame] = (pFramesInF32[iFrame*2+0] + pFramesInF32[iFrame*2+1]) * 0.5f;
34362  }
34363  } break;
34364 
34365  default: return MA_INVALID_OPERATION; /* Unknown format. */
34366  }
34367 
34368  return MA_SUCCESS;
34369 }
34370 
34371 static ma_result ma_channel_converter_process_pcm_frames__weights(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
34372 {
34373  ma_uint32 iFrame;
34374  ma_uint32 iChannelIn;
34375  ma_uint32 iChannelOut;
34376 
34377  MA_ASSERT(pConverter != NULL);
34378  MA_ASSERT(pFramesOut != NULL);
34379  MA_ASSERT(pFramesIn != NULL);
34380 
34381  /* This is the more complicated case. Each of the output channels is accumulated with 0 or more input channels. */
34382 
34383  /* Clear. */
34384  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
34385 
34386  /* Accumulate. */
34387  switch (pConverter->format)
34388  {
34389  case ma_format_u8:
34390  {
34391  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
34392  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
34393 
34394  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34395  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34396  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34397  ma_int16 u8_O = ma_pcm_sample_u8_to_s16_no_scale(pFramesOutU8[iFrame*pConverter->channelsOut + iChannelOut]);
34398  ma_int16 u8_I = ma_pcm_sample_u8_to_s16_no_scale(pFramesInU8 [iFrame*pConverter->channelsIn + iChannelIn ]);
34399  ma_int32 s = (ma_int32)ma_clamp(u8_O + ((u8_I * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT), -128, 127);
34400  pFramesOutU8[iFrame*pConverter->channelsOut + iChannelOut] = ma_clip_u8((ma_int16)s);
34401  }
34402  }
34403  }
34404  } break;
34405 
34406  case ma_format_s16:
34407  {
34408  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
34409  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
34410 
34411  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34412  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34413  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34414  ma_int32 s = pFramesOutS16[iFrame*pConverter->channelsOut + iChannelOut];
34415  s += (pFramesInS16[iFrame*pConverter->channelsIn + iChannelIn] * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT;
34416 
34417  pFramesOutS16[iFrame*pConverter->channelsOut + iChannelOut] = (ma_int16)ma_clamp(s, -32768, 32767);
34418  }
34419  }
34420  }
34421  } break;
34422 
34423  case ma_format_s24:
34424  {
34425  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
34426  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
34427 
34428  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34429  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34430  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34431  ma_int64 s24_O = ma_pcm_sample_s24_to_s32_no_scale(&pFramesOutS24[(iFrame*pConverter->channelsOut + iChannelOut)*3]);
34432  ma_int64 s24_I = ma_pcm_sample_s24_to_s32_no_scale(&pFramesInS24 [(iFrame*pConverter->channelsIn + iChannelIn )*3]);
34433  ma_int64 s24 = (ma_int32)ma_clamp(s24_O + ((s24_I * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT), -8388608, 8388607);
34434  ma_pcm_sample_s32_to_s24_no_scale(s24, &pFramesOutS24[(iFrame*pConverter->channelsOut + iChannelOut)*3]);
34435  }
34436  }
34437  }
34438  } break;
34439 
34440  case ma_format_s32:
34441  {
34442  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
34443  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
34444 
34445  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34446  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34447  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34448  ma_int64 s = pFramesOutS32[iFrame*pConverter->channelsOut + iChannelOut];
34449  s += ((ma_int64)pFramesInS32[iFrame*pConverter->channelsIn + iChannelIn] * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT;
34450 
34451  pFramesOutS32[iFrame*pConverter->channelsOut + iChannelOut] = ma_clip_s32(s);
34452  }
34453  }
34454  }
34455  } break;
34456 
34457  case ma_format_f32:
34458  {
34459  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
34460  const float* pFramesInF32 = (const float*)pFramesIn;
34461 
34462  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34463  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
34464  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
34465  pFramesOutF32[iFrame*pConverter->channelsOut + iChannelOut] += pFramesInF32[iFrame*pConverter->channelsIn + iChannelIn] * pConverter->weights.f32[iChannelIn][iChannelOut];
34466  }
34467  }
34468  }
34469  } break;
34470 
34471  default: return MA_INVALID_OPERATION; /* Unknown format. */
34472  }
34473 
34474  return MA_SUCCESS;
34475 }
34476 
34477 MA_API ma_result ma_channel_converter_process_pcm_frames(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
34478 {
34479  if (pConverter == NULL) {
34480  return MA_INVALID_ARGS;
34481  }
34482 
34483  if (pFramesOut == NULL) {
34484  return MA_INVALID_ARGS;
34485  }
34486 
34487  if (pFramesIn == NULL) {
34488  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
34489  return MA_SUCCESS;
34490  }
34491 
34492  if (pConverter->isPassthrough) {
34493  return ma_channel_converter_process_pcm_frames__passthrough(pConverter, pFramesOut, pFramesIn, frameCount);
34494  } else if (pConverter->isSimpleShuffle) {
34495  return ma_channel_converter_process_pcm_frames__simple_shuffle(pConverter, pFramesOut, pFramesIn, frameCount);
34496  } else if (pConverter->isSimpleMonoExpansion) {
34497  return ma_channel_converter_process_pcm_frames__simple_mono_expansion(pConverter, pFramesOut, pFramesIn, frameCount);
34498  } else if (pConverter->isStereoToMono) {
34499  return ma_channel_converter_process_pcm_frames__stereo_to_mono(pConverter, pFramesOut, pFramesIn, frameCount);
34500  } else {
34501  return ma_channel_converter_process_pcm_frames__weights(pConverter, pFramesOut, pFramesIn, frameCount);
34502  }
34503 }
34504 
34505 
34506 /**************************************************************************************************************************************************************
34507 
34508 Data Conversion
34509 
34510 **************************************************************************************************************************************************************/
34512 {
34515 
34516  config.ditherMode = ma_dither_mode_none;
34517  config.resampling.algorithm = ma_resample_algorithm_linear;
34518  config.resampling.allowDynamicSampleRate = MA_FALSE; /* Disable dynamic sample rates by default because dynamic rate adjustments should be quite rare and it allows an optimization for cases when the in and out sample rates are the same. */
34519 
34520  /* Linear resampling defaults. */
34521  config.resampling.linear.lpfOrder = 1;
34522  config.resampling.linear.lpfNyquistFactor = 1;
34523 
34524  /* Speex resampling defaults. */
34525  config.resampling.speex.quality = 3;
34526 
34527  return config;
34528 }
34529 
34530 MA_API ma_data_converter_config ma_data_converter_config_init(ma_format formatIn, ma_format formatOut, ma_uint32 channelsIn, ma_uint32 channelsOut, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
34531 {
34533  config.formatIn = formatIn;
34534  config.formatOut = formatOut;
34535  config.channelsIn = ma_min(channelsIn, MA_MAX_CHANNELS);
34536  config.channelsOut = ma_min(channelsOut, MA_MAX_CHANNELS);
34537  config.sampleRateIn = sampleRateIn;
34538  config.sampleRateOut = sampleRateOut;
34539 
34540  return config;
34541 }
34542 
34544 {
34545  ma_result result;
34546  ma_format midFormat;
34547 
34548  if (pConverter == NULL) {
34549  return MA_INVALID_ARGS;
34550  }
34551 
34552  MA_ZERO_OBJECT(pConverter);
34553 
34554  if (pConfig == NULL) {
34555  return MA_INVALID_ARGS;
34556  }
34557 
34558  pConverter->config = *pConfig;
34559 
34560  /* Basic validation. */
34561  if (pConfig->channelsIn < MA_MIN_CHANNELS || pConfig->channelsOut < MA_MIN_CHANNELS ||
34562  pConfig->channelsIn > MA_MAX_CHANNELS || pConfig->channelsOut > MA_MAX_CHANNELS) {
34563  return MA_INVALID_ARGS;
34564  }
34565 
34566  /*
34567  We want to avoid as much data conversion as possible. The channel converter and resampler both support s16 and f32 natively. We need to decide
34568  on the format to use for this stage. We call this the mid format because it's used in the middle stage of the conversion pipeline. If the output
34569  format is either s16 or f32 we use that one. If that is not the case it will do the same thing for the input format. If it's neither we just
34570  use f32.
34571  */
34572  /* */ if (pConverter->config.formatOut == ma_format_s16 || pConverter->config.formatOut == ma_format_f32) {
34573  midFormat = pConverter->config.formatOut;
34574  } else if (pConverter->config.formatIn == ma_format_s16 || pConverter->config.formatIn == ma_format_f32) {
34575  midFormat = pConverter->config.formatIn;
34576  } else {
34577  midFormat = ma_format_f32;
34578  }
34579 
34580  /* Channel converter. We always initialize this, but we check if it configures itself as a passthrough to determine whether or not it's needed. */
34581  {
34582  ma_uint32 iChannelIn;
34583  ma_uint32 iChannelOut;
34584  ma_channel_converter_config channelConverterConfig;
34585 
34586  channelConverterConfig = ma_channel_converter_config_init(midFormat, pConverter->config.channelsIn, pConverter->config.channelMapIn, pConverter->config.channelsOut, pConverter->config.channelMapOut, pConverter->config.channelMixMode);
34587 
34588  /* Channel weights. */
34589  for (iChannelIn = 0; iChannelIn < pConverter->config.channelsIn; iChannelIn += 1) {
34590  for (iChannelOut = 0; iChannelOut < pConverter->config.channelsOut; iChannelOut += 1) {
34591  channelConverterConfig.weights[iChannelIn][iChannelOut] = pConverter->config.channelWeights[iChannelIn][iChannelOut];
34592  }
34593  }
34594 
34595  result = ma_channel_converter_init(&channelConverterConfig, &pConverter->channelConverter);
34596  if (result != MA_SUCCESS) {
34597  return result;
34598  }
34599 
34600  /* If the channel converter is not a passthrough we need to enable it. Otherwise we can skip it. */
34601  if (pConverter->channelConverter.isPassthrough == MA_FALSE) {
34602  pConverter->hasChannelConverter = MA_TRUE;
34603  }
34604  }
34605 
34606 
34607  /* Always enable dynamic sample rates if the input sample rate is different because we're always going to need a resampler in this case anyway. */
34608  if (pConverter->config.resampling.allowDynamicSampleRate == MA_FALSE) {
34609  pConverter->config.resampling.allowDynamicSampleRate = pConverter->config.sampleRateIn != pConverter->config.sampleRateOut;
34610  }
34611 
34612  /* Resampler. */
34613  if (pConverter->config.resampling.allowDynamicSampleRate) {
34614  ma_resampler_config resamplerConfig;
34615  ma_uint32 resamplerChannels;
34616 
34617  /* The resampler is the most expensive part of the conversion process, so we need to do it at the stage where the channel count is at it's lowest. */
34618  if (pConverter->config.channelsIn < pConverter->config.channelsOut) {
34619  resamplerChannels = pConverter->config.channelsIn;
34620  } else {
34621  resamplerChannels = pConverter->config.channelsOut;
34622  }
34623 
34624  resamplerConfig = ma_resampler_config_init(midFormat, resamplerChannels, pConverter->config.sampleRateIn, pConverter->config.sampleRateOut, pConverter->config.resampling.algorithm);
34625  resamplerConfig.linear.lpfOrder = pConverter->config.resampling.linear.lpfOrder;
34626  resamplerConfig.linear.lpfNyquistFactor = pConverter->config.resampling.linear.lpfNyquistFactor;
34627  resamplerConfig.speex.quality = pConverter->config.resampling.speex.quality;
34628 
34629  result = ma_resampler_init(&resamplerConfig, &pConverter->resampler);
34630  if (result != MA_SUCCESS) {
34631  return result;
34632  }
34633 
34634  pConverter->hasResampler = MA_TRUE;
34635  }
34636 
34637 
34638  /* We can simplify pre- and post-format conversion if we have neither channel conversion nor resampling. */
34639  if (pConverter->hasChannelConverter == MA_FALSE && pConverter->hasResampler == MA_FALSE) {
34640  /* We have neither channel conversion nor resampling so we'll only need one of pre- or post-format conversion, or none if the input and output formats are the same. */
34641  if (pConverter->config.formatIn == pConverter->config.formatOut) {
34642  /* The formats are the same so we can just pass through. */
34643  pConverter->hasPreFormatConversion = MA_FALSE;
34644  pConverter->hasPostFormatConversion = MA_FALSE;
34645  } else {
34646  /* The formats are different so we need to do either pre- or post-format conversion. It doesn't matter which. */
34647  pConverter->hasPreFormatConversion = MA_FALSE;
34648  pConverter->hasPostFormatConversion = MA_TRUE;
34649  }
34650  } else {
34651  /* We have a channel converter and/or resampler so we'll need channel conversion based on the mid format. */
34652  if (pConverter->config.formatIn != midFormat) {
34653  pConverter->hasPreFormatConversion = MA_TRUE;
34654  }
34655  if (pConverter->config.formatOut != midFormat) {
34656  pConverter->hasPostFormatConversion = MA_TRUE;
34657  }
34658  }
34659 
34660  /* We can enable passthrough optimizations if applicable. Note that we'll only be able to do this if the sample rate is static. */
34661  if (pConverter->hasPreFormatConversion == MA_FALSE &&
34662  pConverter->hasPostFormatConversion == MA_FALSE &&
34663  pConverter->hasChannelConverter == MA_FALSE &&
34664  pConverter->hasResampler == MA_FALSE) {
34665  pConverter->isPassthrough = MA_TRUE;
34666  }
34667 
34668  return MA_SUCCESS;
34669 }
34670 
34672 {
34673  if (pConverter == NULL) {
34674  return;
34675  }
34676 
34677  if (pConverter->hasResampler) {
34678  ma_resampler_uninit(&pConverter->resampler);
34679  }
34680 }
34681 
34682 static ma_result ma_data_converter_process_pcm_frames__passthrough(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
34683 {
34684  ma_uint64 frameCountIn;
34685  ma_uint64 frameCountOut;
34686  ma_uint64 frameCount;
34687 
34688  MA_ASSERT(pConverter != NULL);
34689 
34690  frameCountIn = 0;
34691  if (pFrameCountIn != NULL) {
34692  frameCountIn = *pFrameCountIn;
34693  }
34694 
34695  frameCountOut = 0;
34696  if (pFrameCountOut != NULL) {
34697  frameCountOut = *pFrameCountOut;
34698  }
34699 
34700  frameCount = ma_min(frameCountIn, frameCountOut);
34701 
34702  if (pFramesOut != NULL) {
34703  if (pFramesIn != NULL) {
34704  ma_copy_memory_64(pFramesOut, pFramesIn, frameCount * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
34705  } else {
34706  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
34707  }
34708  }
34709 
34710  if (pFrameCountIn != NULL) {
34711  *pFrameCountIn = frameCount;
34712  }
34713  if (pFrameCountOut != NULL) {
34714  *pFrameCountOut = frameCount;
34715  }
34716 
34717  return MA_SUCCESS;
34718 }
34719 
34720 static ma_result ma_data_converter_process_pcm_frames__format_only(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
34721 {
34722  ma_uint64 frameCountIn;
34723  ma_uint64 frameCountOut;
34724  ma_uint64 frameCount;
34725 
34726  MA_ASSERT(pConverter != NULL);
34727 
34728  frameCountIn = 0;
34729  if (pFrameCountIn != NULL) {
34730  frameCountIn = *pFrameCountIn;
34731  }
34732 
34733  frameCountOut = 0;
34734  if (pFrameCountOut != NULL) {
34735  frameCountOut = *pFrameCountOut;
34736  }
34737 
34738  frameCount = ma_min(frameCountIn, frameCountOut);
34739 
34740  if (pFramesOut != NULL) {
34741  if (pFramesIn != NULL) {
34742  ma_convert_pcm_frames_format(pFramesOut, pConverter->config.formatOut, pFramesIn, pConverter->config.formatIn, frameCount, pConverter->config.channelsIn, pConverter->config.ditherMode);
34743  } else {
34744  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
34745  }
34746  }
34747 
34748  if (pFrameCountIn != NULL) {
34749  *pFrameCountIn = frameCount;
34750  }
34751  if (pFrameCountOut != NULL) {
34752  *pFrameCountOut = frameCount;
34753  }
34754 
34755  return MA_SUCCESS;
34756 }
34757 
34758 
34759 static ma_result ma_data_converter_process_pcm_frames__resample_with_format_conversion(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
34760 {
34761  ma_result result = MA_SUCCESS;
34762  ma_uint64 frameCountIn;
34763  ma_uint64 frameCountOut;
34764  ma_uint64 framesProcessedIn;
34765  ma_uint64 framesProcessedOut;
34766 
34767  MA_ASSERT(pConverter != NULL);
34768 
34769  frameCountIn = 0;
34770  if (pFrameCountIn != NULL) {
34771  frameCountIn = *pFrameCountIn;
34772  }
34773 
34774  frameCountOut = 0;
34775  if (pFrameCountOut != NULL) {
34776  frameCountOut = *pFrameCountOut;
34777  }
34778 
34779  framesProcessedIn = 0;
34780  framesProcessedOut = 0;
34781 
34782  while (framesProcessedOut < frameCountOut) {
34783  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
34784  const ma_uint32 tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
34785  const void* pFramesInThisIteration;
34786  /* */ void* pFramesOutThisIteration;
34787  ma_uint64 frameCountInThisIteration;
34788  ma_uint64 frameCountOutThisIteration;
34789 
34790  if (pFramesIn != NULL) {
34791  pFramesInThisIteration = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
34792  } else {
34793  pFramesInThisIteration = NULL;
34794  }
34795 
34796  if (pFramesOut != NULL) {
34797  pFramesOutThisIteration = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
34798  } else {
34799  pFramesOutThisIteration = NULL;
34800  }
34801 
34802  /* Do a pre format conversion if necessary. */
34803  if (pConverter->hasPreFormatConversion) {
34804  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
34805  const ma_uint32 tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
34806 
34807  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
34808  if (frameCountInThisIteration > tempBufferInCap) {
34809  frameCountInThisIteration = tempBufferInCap;
34810  }
34811 
34812  if (pConverter->hasPostFormatConversion) {
34813  if (frameCountInThisIteration > tempBufferOutCap) {
34814  frameCountInThisIteration = tempBufferOutCap;
34815  }
34816  }
34817 
34818  if (pFramesInThisIteration != NULL) {
34819  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->resampler.config.format, pFramesInThisIteration, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
34820  } else {
34821  MA_ZERO_MEMORY(pTempBufferIn, sizeof(pTempBufferIn));
34822  }
34823 
34824  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
34825 
34826  if (pConverter->hasPostFormatConversion) {
34827  /* Both input and output conversion required. Output to the temp buffer. */
34828  if (frameCountOutThisIteration > tempBufferOutCap) {
34829  frameCountOutThisIteration = tempBufferOutCap;
34830  }
34831 
34832  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferIn, &frameCountInThisIteration, pTempBufferOut, &frameCountOutThisIteration);
34833  } else {
34834  /* Only pre-format required. Output straight to the output buffer. */
34835  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferIn, &frameCountInThisIteration, pFramesOutThisIteration, &frameCountOutThisIteration);
34836  }
34837 
34838  if (result != MA_SUCCESS) {
34839  break;
34840  }
34841  } else {
34842  /* No pre-format required. Just read straight from the input buffer. */
34843  MA_ASSERT(pConverter->hasPostFormatConversion == MA_TRUE);
34844 
34845  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
34846  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
34847  if (frameCountOutThisIteration > tempBufferOutCap) {
34848  frameCountOutThisIteration = tempBufferOutCap;
34849  }
34850 
34851  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pFramesInThisIteration, &frameCountInThisIteration, pTempBufferOut, &frameCountOutThisIteration);
34852  if (result != MA_SUCCESS) {
34853  break;
34854  }
34855  }
34856 
34857  /* If we are doing a post format conversion we need to do that now. */
34858  if (pConverter->hasPostFormatConversion) {
34859  if (pFramesOutThisIteration != NULL) {
34860  ma_convert_pcm_frames_format(pFramesOutThisIteration, pConverter->config.formatOut, pTempBufferOut, pConverter->resampler.config.format, frameCountOutThisIteration, pConverter->resampler.config.channels, pConverter->config.ditherMode);
34861  }
34862  }
34863 
34864  framesProcessedIn += frameCountInThisIteration;
34865  framesProcessedOut += frameCountOutThisIteration;
34866 
34867  MA_ASSERT(framesProcessedIn <= frameCountIn);
34868  MA_ASSERT(framesProcessedOut <= frameCountOut);
34869 
34870  if (frameCountOutThisIteration == 0) {
34871  break; /* Consumed all of our input data. */
34872  }
34873  }
34874 
34875  if (pFrameCountIn != NULL) {
34876  *pFrameCountIn = framesProcessedIn;
34877  }
34878  if (pFrameCountOut != NULL) {
34879  *pFrameCountOut = framesProcessedOut;
34880  }
34881 
34882  return result;
34883 }
34884 
34885 static ma_result ma_data_converter_process_pcm_frames__resample_only(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
34886 {
34887  MA_ASSERT(pConverter != NULL);
34888 
34889  if (pConverter->hasPreFormatConversion == MA_FALSE && pConverter->hasPostFormatConversion == MA_FALSE) {
34890  /* Neither pre- nor post-format required. This is simple case where only resampling is required. */
34891  return ma_resampler_process_pcm_frames(&pConverter->resampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
34892  } else {
34893  /* Format conversion required. */
34894  return ma_data_converter_process_pcm_frames__resample_with_format_conversion(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
34895  }
34896 }
34897 
34898 static ma_result ma_data_converter_process_pcm_frames__channels_only(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
34899 {
34900  ma_result result;
34901  ma_uint64 frameCountIn;
34902  ma_uint64 frameCountOut;
34903  ma_uint64 frameCount;
34904 
34905  MA_ASSERT(pConverter != NULL);
34906 
34907  frameCountIn = 0;
34908  if (pFrameCountIn != NULL) {
34909  frameCountIn = *pFrameCountIn;
34910  }
34911 
34912  frameCountOut = 0;
34913  if (pFrameCountOut != NULL) {
34914  frameCountOut = *pFrameCountOut;
34915  }
34916 
34917  frameCount = ma_min(frameCountIn, frameCountOut);
34918 
34919  if (pConverter->hasPreFormatConversion == MA_FALSE && pConverter->hasPostFormatConversion == MA_FALSE) {
34920  /* No format conversion required. */
34921  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pFramesOut, pFramesIn, frameCount);
34922  if (result != MA_SUCCESS) {
34923  return result;
34924  }
34925  } else {
34926  /* Format conversion required. */
34927  ma_uint64 framesProcessed = 0;
34928 
34929  while (framesProcessed < frameCount) {
34930  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
34931  const ma_uint32 tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
34932  const void* pFramesInThisIteration;
34933  /* */ void* pFramesOutThisIteration;
34934  ma_uint64 frameCountThisIteration;
34935 
34936  if (pFramesIn != NULL) {
34937  pFramesInThisIteration = ma_offset_ptr(pFramesIn, framesProcessed * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
34938  } else {
34939  pFramesInThisIteration = NULL;
34940  }
34941 
34942  if (pFramesOut != NULL) {
34943  pFramesOutThisIteration = ma_offset_ptr(pFramesOut, framesProcessed * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
34944  } else {
34945  pFramesOutThisIteration = NULL;
34946  }
34947 
34948  /* Do a pre format conversion if necessary. */
34949  if (pConverter->hasPreFormatConversion) {
34950  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
34951  const ma_uint32 tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsIn);
34952 
34953  frameCountThisIteration = (frameCount - framesProcessed);
34954  if (frameCountThisIteration > tempBufferInCap) {
34955  frameCountThisIteration = tempBufferInCap;
34956  }
34957 
34958  if (pConverter->hasPostFormatConversion) {
34959  if (frameCountThisIteration > tempBufferOutCap) {
34960  frameCountThisIteration = tempBufferOutCap;
34961  }
34962  }
34963 
34964  if (pFramesInThisIteration != NULL) {
34965  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->channelConverter.format, pFramesInThisIteration, pConverter->config.formatIn, frameCountThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
34966  } else {
34967  MA_ZERO_MEMORY(pTempBufferIn, sizeof(pTempBufferIn));
34968  }
34969 
34970  if (pConverter->hasPostFormatConversion) {
34971  /* Both input and output conversion required. Output to the temp buffer. */
34972  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferOut, pTempBufferIn, frameCountThisIteration);
34973  } else {
34974  /* Only pre-format required. Output straight to the output buffer. */
34975  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pFramesOutThisIteration, pTempBufferIn, frameCountThisIteration);
34976  }
34977 
34978  if (result != MA_SUCCESS) {
34979  break;
34980  }
34981  } else {
34982  /* No pre-format required. Just read straight from the input buffer. */
34983  MA_ASSERT(pConverter->hasPostFormatConversion == MA_TRUE);
34984 
34985  frameCountThisIteration = (frameCount - framesProcessed);
34986  if (frameCountThisIteration > tempBufferOutCap) {
34987  frameCountThisIteration = tempBufferOutCap;
34988  }
34989 
34990  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferOut, pFramesInThisIteration, frameCountThisIteration);
34991  if (result != MA_SUCCESS) {
34992  break;
34993  }
34994  }
34995 
34996  /* If we are doing a post format conversion we need to do that now. */
34997  if (pConverter->hasPostFormatConversion) {
34998  if (pFramesOutThisIteration != NULL) {
34999  ma_convert_pcm_frames_format(pFramesOutThisIteration, pConverter->config.formatOut, pTempBufferOut, pConverter->channelConverter.format, frameCountThisIteration, pConverter->channelConverter.channelsOut, pConverter->config.ditherMode);
35000  }
35001  }
35002 
35003  framesProcessed += frameCountThisIteration;
35004  }
35005  }
35006 
35007  if (pFrameCountIn != NULL) {
35008  *pFrameCountIn = frameCount;
35009  }
35010  if (pFrameCountOut != NULL) {
35011  *pFrameCountOut = frameCount;
35012  }
35013 
35014  return MA_SUCCESS;
35015 }
35016 
35017 static ma_result ma_data_converter_process_pcm_frames__resampling_first(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
35018 {
35019  ma_result result;
35020  ma_uint64 frameCountIn;
35021  ma_uint64 frameCountOut;
35022  ma_uint64 framesProcessedIn;
35023  ma_uint64 framesProcessedOut;
35024  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format. */
35025  ma_uint64 tempBufferInCap;
35026  ma_uint8 pTempBufferMid[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format, channel converter input format. */
35027  ma_uint64 tempBufferMidCap;
35028  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In channel converter output format. */
35029  ma_uint64 tempBufferOutCap;
35030 
35031  MA_ASSERT(pConverter != NULL);
35032  MA_ASSERT(pConverter->resampler.config.format == pConverter->channelConverter.format);
35033  MA_ASSERT(pConverter->resampler.config.channels == pConverter->channelConverter.channelsIn);
35034  MA_ASSERT(pConverter->resampler.config.channels < pConverter->channelConverter.channelsOut);
35035 
35036  frameCountIn = 0;
35037  if (pFrameCountIn != NULL) {
35038  frameCountIn = *pFrameCountIn;
35039  }
35040 
35041  frameCountOut = 0;
35042  if (pFrameCountOut != NULL) {
35043  frameCountOut = *pFrameCountOut;
35044  }
35045 
35046  framesProcessedIn = 0;
35047  framesProcessedOut = 0;
35048 
35049  tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
35050  tempBufferMidCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
35051  tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
35052 
35053  while (framesProcessedOut < frameCountOut) {
35054  ma_uint64 frameCountInThisIteration;
35055  ma_uint64 frameCountOutThisIteration;
35056  const void* pRunningFramesIn = NULL;
35057  void* pRunningFramesOut = NULL;
35058  const void* pResampleBufferIn;
35059  void* pChannelsBufferOut;
35060 
35061  if (pFramesIn != NULL) {
35062  pRunningFramesIn = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
35063  }
35064  if (pFramesOut != NULL) {
35065  pRunningFramesOut = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
35066  }
35067 
35068  /* Run input data through the resampler and output it to the temporary buffer. */
35069  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
35070 
35071  if (pConverter->hasPreFormatConversion) {
35072  if (frameCountInThisIteration > tempBufferInCap) {
35073  frameCountInThisIteration = tempBufferInCap;
35074  }
35075  }
35076 
35077  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
35078  if (frameCountOutThisIteration > tempBufferMidCap) {
35079  frameCountOutThisIteration = tempBufferMidCap;
35080  }
35081 
35082  /* We can't read more frames than can fit in the output buffer. */
35083  if (pConverter->hasPostFormatConversion) {
35084  if (frameCountOutThisIteration > tempBufferOutCap) {
35085  frameCountOutThisIteration = tempBufferOutCap;
35086  }
35087  }
35088 
35089  /* We need to ensure we don't try to process too many input frames that we run out of room in the output buffer. If this happens we'll end up glitching. */
35090  {
35091  ma_uint64 requiredInputFrameCount = ma_resampler_get_required_input_frame_count(&pConverter->resampler, frameCountOutThisIteration);
35092  if (frameCountInThisIteration > requiredInputFrameCount) {
35093  frameCountInThisIteration = requiredInputFrameCount;
35094  }
35095  }
35096 
35097  if (pConverter->hasPreFormatConversion) {
35098  if (pFramesIn != NULL) {
35099  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->resampler.config.format, pRunningFramesIn, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
35100  pResampleBufferIn = pTempBufferIn;
35101  } else {
35102  pResampleBufferIn = NULL;
35103  }
35104  } else {
35105  pResampleBufferIn = pRunningFramesIn;
35106  }
35107 
35108  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pResampleBufferIn, &frameCountInThisIteration, pTempBufferMid, &frameCountOutThisIteration);
35109  if (result != MA_SUCCESS) {
35110  return result;
35111  }
35112 
35113 
35114  /*
35115  The input data has been resampled so now we need to run it through the channel converter. The input data is always contained in pTempBufferMid. We only need to do
35116  this part if we have an output buffer.
35117  */
35118  if (pFramesOut != NULL) {
35119  if (pConverter->hasPostFormatConversion) {
35120  pChannelsBufferOut = pTempBufferOut;
35121  } else {
35122  pChannelsBufferOut = pRunningFramesOut;
35123  }
35124 
35125  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pChannelsBufferOut, pTempBufferMid, frameCountOutThisIteration);
35126  if (result != MA_SUCCESS) {
35127  return result;
35128  }
35129 
35130  /* Finally we do post format conversion. */
35131  if (pConverter->hasPostFormatConversion) {
35132  ma_convert_pcm_frames_format(pRunningFramesOut, pConverter->config.formatOut, pChannelsBufferOut, pConverter->channelConverter.format, frameCountOutThisIteration, pConverter->channelConverter.channelsOut, pConverter->config.ditherMode);
35133  }
35134  }
35135 
35136 
35137  framesProcessedIn += frameCountInThisIteration;
35138  framesProcessedOut += frameCountOutThisIteration;
35139 
35140  MA_ASSERT(framesProcessedIn <= frameCountIn);
35141  MA_ASSERT(framesProcessedOut <= frameCountOut);
35142 
35143  if (frameCountOutThisIteration == 0) {
35144  break; /* Consumed all of our input data. */
35145  }
35146  }
35147 
35148  if (pFrameCountIn != NULL) {
35149  *pFrameCountIn = framesProcessedIn;
35150  }
35151  if (pFrameCountOut != NULL) {
35152  *pFrameCountOut = framesProcessedOut;
35153  }
35154 
35155  return MA_SUCCESS;
35156 }
35157 
35158 static ma_result ma_data_converter_process_pcm_frames__channels_first(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
35159 {
35160  ma_result result;
35161  ma_uint64 frameCountIn;
35162  ma_uint64 frameCountOut;
35163  ma_uint64 framesProcessedIn;
35164  ma_uint64 framesProcessedOut;
35165  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format. */
35166  ma_uint64 tempBufferInCap;
35167  ma_uint8 pTempBufferMid[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format, channel converter input format. */
35168  ma_uint64 tempBufferMidCap;
35169  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In channel converter output format. */
35170  ma_uint64 tempBufferOutCap;
35171 
35172  MA_ASSERT(pConverter != NULL);
35173  MA_ASSERT(pConverter->resampler.config.format == pConverter->channelConverter.format);
35174  MA_ASSERT(pConverter->resampler.config.channels == pConverter->channelConverter.channelsOut);
35175  MA_ASSERT(pConverter->resampler.config.channels < pConverter->channelConverter.channelsIn);
35176 
35177  frameCountIn = 0;
35178  if (pFrameCountIn != NULL) {
35179  frameCountIn = *pFrameCountIn;
35180  }
35181 
35182  frameCountOut = 0;
35183  if (pFrameCountOut != NULL) {
35184  frameCountOut = *pFrameCountOut;
35185  }
35186 
35187  framesProcessedIn = 0;
35188  framesProcessedOut = 0;
35189 
35190  tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsIn);
35191  tempBufferMidCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
35192  tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
35193 
35194  while (framesProcessedOut < frameCountOut) {
35195  ma_uint64 frameCountInThisIteration;
35196  ma_uint64 frameCountOutThisIteration;
35197  const void* pRunningFramesIn = NULL;
35198  void* pRunningFramesOut = NULL;
35199  const void* pChannelsBufferIn;
35200  void* pResampleBufferOut;
35201 
35202  if (pFramesIn != NULL) {
35203  pRunningFramesIn = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
35204  }
35205  if (pFramesOut != NULL) {
35206  pRunningFramesOut = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
35207  }
35208 
35209  /* Run input data through the channel converter and output it to the temporary buffer. */
35210  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
35211 
35212  if (pConverter->hasPreFormatConversion) {
35213  if (frameCountInThisIteration > tempBufferInCap) {
35214  frameCountInThisIteration = tempBufferInCap;
35215  }
35216 
35217  if (pRunningFramesIn != NULL) {
35218  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->channelConverter.format, pRunningFramesIn, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
35219  pChannelsBufferIn = pTempBufferIn;
35220  } else {
35221  pChannelsBufferIn = NULL;
35222  }
35223  } else {
35224  pChannelsBufferIn = pRunningFramesIn;
35225  }
35226 
35227  /*
35228  We can't convert more frames than will fit in the output buffer. We shouldn't actually need to do this check because the channel count is always reduced
35229  in this case which means we should always have capacity, but I'm leaving it here just for safety for future maintenance.
35230  */
35231  if (frameCountInThisIteration > tempBufferMidCap) {
35232  frameCountInThisIteration = tempBufferMidCap;
35233  }
35234 
35235  /*
35236  Make sure we don't read any more input frames than we need to fill the output frame count. If we do this we will end up in a situation where we lose some
35237  input samples and will end up glitching.
35238  */
35239  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
35240  if (frameCountOutThisIteration > tempBufferMidCap) {
35241  frameCountOutThisIteration = tempBufferMidCap;
35242  }
35243 
35244  if (pConverter->hasPostFormatConversion) {
35245  ma_uint64 requiredInputFrameCount;
35246 
35247  if (frameCountOutThisIteration > tempBufferOutCap) {
35248  frameCountOutThisIteration = tempBufferOutCap;
35249  }
35250 
35251  requiredInputFrameCount = ma_resampler_get_required_input_frame_count(&pConverter->resampler, frameCountOutThisIteration);
35252  if (frameCountInThisIteration > requiredInputFrameCount) {
35253  frameCountInThisIteration = requiredInputFrameCount;
35254  }
35255  }
35256 
35257  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferMid, pChannelsBufferIn, frameCountInThisIteration);
35258  if (result != MA_SUCCESS) {
35259  return result;
35260  }
35261 
35262 
35263  /* At this point we have converted the channels to the output channel count which we now need to resample. */
35264  if (pConverter->hasPostFormatConversion) {
35265  pResampleBufferOut = pTempBufferOut;
35266  } else {
35267  pResampleBufferOut = pRunningFramesOut;
35268  }
35269 
35270  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferMid, &frameCountInThisIteration, pResampleBufferOut, &frameCountOutThisIteration);
35271  if (result != MA_SUCCESS) {
35272  return result;
35273  }
35274 
35275  /* Finally we can do the post format conversion. */
35276  if (pConverter->hasPostFormatConversion) {
35277  if (pRunningFramesOut != NULL) {
35278  ma_convert_pcm_frames_format(pRunningFramesOut, pConverter->config.formatOut, pResampleBufferOut, pConverter->resampler.config.format, frameCountOutThisIteration, pConverter->config.channelsOut, pConverter->config.ditherMode);
35279  }
35280  }
35281 
35282  framesProcessedIn += frameCountInThisIteration;
35283  framesProcessedOut += frameCountOutThisIteration;
35284 
35285  MA_ASSERT(framesProcessedIn <= frameCountIn);
35286  MA_ASSERT(framesProcessedOut <= frameCountOut);
35287 
35288  if (frameCountOutThisIteration == 0) {
35289  break; /* Consumed all of our input data. */
35290  }
35291  }
35292 
35293  if (pFrameCountIn != NULL) {
35294  *pFrameCountIn = framesProcessedIn;
35295  }
35296  if (pFrameCountOut != NULL) {
35297  *pFrameCountOut = framesProcessedOut;
35298  }
35299 
35300  return MA_SUCCESS;
35301 }
35302 
35303 MA_API ma_result ma_data_converter_process_pcm_frames(ma_data_converter* pConverter, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
35304 {
35305  if (pConverter == NULL) {
35306  return MA_INVALID_ARGS;
35307  }
35308 
35309  if (pConverter->isPassthrough) {
35310  return ma_data_converter_process_pcm_frames__passthrough(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35311  }
35312 
35313  /*
35314  Here is where the real work is done. Getting here means we're not using a passthrough and we need to move the data through each of the relevant stages. The order
35315  of our stages depends on the input and output channel count. If the input channels is less than the output channels we want to do sample rate conversion first so
35316  that it has less work (resampling is the most expensive part of format conversion).
35317  */
35318  if (pConverter->config.channelsIn < pConverter->config.channelsOut) {
35319  /* Do resampling first, if necessary. */
35320  MA_ASSERT(pConverter->hasChannelConverter == MA_TRUE);
35321 
35322  if (pConverter->hasResampler) {
35323  /* Resampling first. */
35324  return ma_data_converter_process_pcm_frames__resampling_first(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35325  } else {
35326  /* Resampling not required. */
35327  return ma_data_converter_process_pcm_frames__channels_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35328  }
35329  } else {
35330  /* Do channel conversion first, if necessary. */
35331  if (pConverter->hasChannelConverter) {
35332  if (pConverter->hasResampler) {
35333  /* Channel routing first. */
35334  return ma_data_converter_process_pcm_frames__channels_first(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35335  } else {
35336  /* Resampling not required. */
35337  return ma_data_converter_process_pcm_frames__channels_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35338  }
35339  } else {
35340  /* Channel routing not required. */
35341  if (pConverter->hasResampler) {
35342  /* Resampling only. */
35343  return ma_data_converter_process_pcm_frames__resample_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35344  } else {
35345  /* No channel routing nor resampling required. Just format conversion. */
35346  return ma_data_converter_process_pcm_frames__format_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
35347  }
35348  }
35349  }
35350 }
35351 
35353 {
35354  if (pConverter == NULL) {
35355  return MA_INVALID_ARGS;
35356  }
35357 
35358  if (pConverter->hasResampler == MA_FALSE) {
35359  return MA_INVALID_OPERATION; /* Dynamic resampling not enabled. */
35360  }
35361 
35362  return ma_resampler_set_rate(&pConverter->resampler, sampleRateIn, sampleRateOut);
35363 }
35364 
35366 {
35367  if (pConverter == NULL) {
35368  return MA_INVALID_ARGS;
35369  }
35370 
35371  if (pConverter->hasResampler == MA_FALSE) {
35372  return MA_INVALID_OPERATION; /* Dynamic resampling not enabled. */
35373  }
35374 
35375  return ma_resampler_set_rate_ratio(&pConverter->resampler, ratioInOut);
35376 }
35377 
35379 {
35380  if (pConverter == NULL) {
35381  return 0;
35382  }
35383 
35384  if (pConverter->hasResampler) {
35385  return ma_resampler_get_required_input_frame_count(&pConverter->resampler, outputFrameCount);
35386  } else {
35387  return outputFrameCount; /* 1:1 */
35388  }
35389 }
35390 
35392 {
35393  if (pConverter == NULL) {
35394  return 0;
35395  }
35396 
35397  if (pConverter->hasResampler) {
35398  return ma_resampler_get_expected_output_frame_count(&pConverter->resampler, inputFrameCount);
35399  } else {
35400  return inputFrameCount; /* 1:1 */
35401  }
35402 }
35403 
35405 {
35406  if (pConverter == NULL) {
35407  return 0;
35408  }
35409 
35410  if (pConverter->hasResampler) {
35411  return ma_resampler_get_input_latency(&pConverter->resampler);
35412  }
35413 
35414  return 0; /* No latency without a resampler. */
35415 }
35416 
35418 {
35419  if (pConverter == NULL) {
35420  return 0;
35421  }
35422 
35423  if (pConverter->hasResampler) {
35424  return ma_resampler_get_output_latency(&pConverter->resampler);
35425  }
35426 
35427  return 0; /* No latency without a resampler. */
35428 }
35429 
35430 
35431 
35432 /**************************************************************************************************************************************************************
35433 
35434 Channel Maps
35435 
35436 **************************************************************************************************************************************************************/
35438 {
35439  if (channelCount == 0 || channelIndex >= channelCount) {
35440  return MA_CHANNEL_NONE;
35441  }
35442 
35443  /* This is the Microsoft channel map. Based off the speaker configurations mentioned here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ksmedia/ns-ksmedia-ksaudio_channel_config */
35444  switch (channelCount)
35445  {
35446  case 0: return MA_CHANNEL_NONE;
35447 
35448  case 1:
35449  {
35450  return MA_CHANNEL_MONO;
35451  } break;
35452 
35453  case 2:
35454  {
35455  switch (channelIndex) {
35456  case 0: return MA_CHANNEL_FRONT_LEFT;
35457  case 1: return MA_CHANNEL_FRONT_RIGHT;
35458  }
35459  } break;
35460 
35461  case 3: /* No defined, but best guess. */
35462  {
35463  switch (channelIndex) {
35464  case 0: return MA_CHANNEL_FRONT_LEFT;
35465  case 1: return MA_CHANNEL_FRONT_RIGHT;
35466  case 2: return MA_CHANNEL_FRONT_CENTER;
35467  }
35468  } break;
35469 
35470  case 4:
35471  {
35472  switch (channelIndex) {
35473  #ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
35474  /* Surround. Using the Surround profile has the advantage of the 3rd channel (MA_CHANNEL_FRONT_CENTER) mapping nicely with higher channel counts. */
35475  case 0: return MA_CHANNEL_FRONT_LEFT;
35476  case 1: return MA_CHANNEL_FRONT_RIGHT;
35477  case 2: return MA_CHANNEL_FRONT_CENTER;
35478  case 3: return MA_CHANNEL_BACK_CENTER;
35479  #else
35480  /* Quad. */
35481  case 0: return MA_CHANNEL_FRONT_LEFT;
35482  case 1: return MA_CHANNEL_FRONT_RIGHT;
35483  case 2: return MA_CHANNEL_BACK_LEFT;
35484  case 3: return MA_CHANNEL_BACK_RIGHT;
35485  #endif
35486  }
35487  } break;
35488 
35489  case 5: /* Not defined, but best guess. */
35490  {
35491  switch (channelIndex) {
35492  case 0: return MA_CHANNEL_FRONT_LEFT;
35493  case 1: return MA_CHANNEL_FRONT_RIGHT;
35494  case 2: return MA_CHANNEL_FRONT_CENTER;
35495  case 3: return MA_CHANNEL_BACK_LEFT;
35496  case 4: return MA_CHANNEL_BACK_RIGHT;
35497  }
35498  } break;
35499 
35500  case 6:
35501  {
35502  switch (channelIndex) {
35503  case 0: return MA_CHANNEL_FRONT_LEFT;
35504  case 1: return MA_CHANNEL_FRONT_RIGHT;
35505  case 2: return MA_CHANNEL_FRONT_CENTER;
35506  case 3: return MA_CHANNEL_LFE;
35507  case 4: return MA_CHANNEL_SIDE_LEFT;
35508  case 5: return MA_CHANNEL_SIDE_RIGHT;
35509  }
35510  } break;
35511 
35512  case 7: /* Not defined, but best guess. */
35513  {
35514  switch (channelIndex) {
35515  case 0: return MA_CHANNEL_FRONT_LEFT;
35516  case 1: return MA_CHANNEL_FRONT_RIGHT;
35517  case 2: return MA_CHANNEL_FRONT_CENTER;
35518  case 3: return MA_CHANNEL_LFE;
35519  case 4: return MA_CHANNEL_BACK_CENTER;
35520  case 5: return MA_CHANNEL_SIDE_LEFT;
35521  case 6: return MA_CHANNEL_SIDE_RIGHT;
35522  }
35523  } break;
35524 
35525  case 8:
35526  default:
35527  {
35528  switch (channelIndex) {
35529  case 0: return MA_CHANNEL_FRONT_LEFT;
35530  case 1: return MA_CHANNEL_FRONT_RIGHT;
35531  case 2: return MA_CHANNEL_FRONT_CENTER;
35532  case 3: return MA_CHANNEL_LFE;
35533  case 4: return MA_CHANNEL_BACK_LEFT;
35534  case 5: return MA_CHANNEL_BACK_RIGHT;
35535  case 6: return MA_CHANNEL_SIDE_LEFT;
35536  case 7: return MA_CHANNEL_SIDE_RIGHT;
35537  }
35538  } break;
35539  }
35540 
35541  if (channelCount > 8) {
35542  if (channelIndex < 32) { /* We have 32 AUX channels. */
35543  return (ma_channel)(MA_CHANNEL_AUX_0 + (channelIndex - 8));
35544  }
35545  }
35546 
35547  /* Getting here means we don't know how to map the channel position so just return MA_CHANNEL_NONE. */
35548  return MA_CHANNEL_NONE;
35549 }
35550 
35551 MA_API ma_channel ma_channel_map_get_channel(const ma_channel* pChannelMap, ma_uint32 channelCount, ma_uint32 channelIndex)
35552 {
35553  if (pChannelMap == NULL) {
35554  return ma_channel_map_get_default_channel(channelCount, channelIndex);
35555  } else {
35556  if (channelIndex >= channelCount) {
35557  return MA_CHANNEL_NONE;
35558  }
35559 
35560  return pChannelMap[channelIndex];
35561  }
35562 }
35563 
35564 
35566 {
35567  if (pChannelMap == NULL) {
35568  return;
35569  }
35570 
35571  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channels);
35572 }
35573 
35575 {
35576  /* Based off the speaker configurations mentioned here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ksmedia/ns-ksmedia-ksaudio_channel_config */
35577  switch (channels)
35578  {
35579  case 1:
35580  {
35581  pChannelMap[0] = MA_CHANNEL_MONO;
35582  } break;
35583 
35584  case 2:
35585  {
35586  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35587  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35588  } break;
35589 
35590  case 3: /* Not defined, but best guess. */
35591  {
35592  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35593  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35594  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35595  } break;
35596 
35597  case 4:
35598  {
35599 #ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
35600  /* Surround. Using the Surround profile has the advantage of the 3rd channel (MA_CHANNEL_FRONT_CENTER) mapping nicely with higher channel counts. */
35601  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35602  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35603  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35604  pChannelMap[3] = MA_CHANNEL_BACK_CENTER;
35605 #else
35606  /* Quad. */
35607  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35608  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35609  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35610  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35611 #endif
35612  } break;
35613 
35614  case 5: /* Not defined, but best guess. */
35615  {
35616  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35617  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35618  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35619  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
35620  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
35621  } break;
35622 
35623  case 6:
35624  {
35625  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35626  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35627  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35628  pChannelMap[3] = MA_CHANNEL_LFE;
35629  pChannelMap[4] = MA_CHANNEL_SIDE_LEFT;
35630  pChannelMap[5] = MA_CHANNEL_SIDE_RIGHT;
35631  } break;
35632 
35633  case 7: /* Not defined, but best guess. */
35634  {
35635  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35636  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35637  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35638  pChannelMap[3] = MA_CHANNEL_LFE;
35639  pChannelMap[4] = MA_CHANNEL_BACK_CENTER;
35640  pChannelMap[5] = MA_CHANNEL_SIDE_LEFT;
35641  pChannelMap[6] = MA_CHANNEL_SIDE_RIGHT;
35642  } break;
35643 
35644  case 8:
35645  default:
35646  {
35647  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35648  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35649  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35650  pChannelMap[3] = MA_CHANNEL_LFE;
35651  pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
35652  pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
35653  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
35654  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
35655  } break;
35656  }
35657 
35658  /* Remainder. */
35659  if (channels > 8) {
35660  ma_uint32 iChannel;
35661  for (iChannel = 8; iChannel < channels; ++iChannel) {
35662  if (iChannel < MA_MAX_CHANNELS) {
35663  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
35664  } else {
35665  pChannelMap[iChannel] = MA_CHANNEL_NONE;
35666  }
35667  }
35668  }
35669 }
35670 
35671 static void ma_get_standard_channel_map_alsa(ma_uint32 channels, ma_channel* pChannelMap)
35672 {
35673  switch (channels)
35674  {
35675  case 1:
35676  {
35677  pChannelMap[0] = MA_CHANNEL_MONO;
35678  } break;
35679 
35680  case 2:
35681  {
35682  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35683  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35684  } break;
35685 
35686  case 3:
35687  {
35688  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35689  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35690  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35691  } break;
35692 
35693  case 4:
35694  {
35695  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35696  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35697  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35698  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35699  } break;
35700 
35701  case 5:
35702  {
35703  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35704  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35705  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35706  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35707  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
35708  } break;
35709 
35710  case 6:
35711  {
35712  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35713  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35714  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35715  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35716  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
35717  pChannelMap[5] = MA_CHANNEL_LFE;
35718  } break;
35719 
35720  case 7:
35721  {
35722  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35723  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35724  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35725  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35726  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
35727  pChannelMap[5] = MA_CHANNEL_LFE;
35728  pChannelMap[6] = MA_CHANNEL_BACK_CENTER;
35729  } break;
35730 
35731  case 8:
35732  default:
35733  {
35734  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35735  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35736  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35737  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35738  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
35739  pChannelMap[5] = MA_CHANNEL_LFE;
35740  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
35741  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
35742  } break;
35743  }
35744 
35745  /* Remainder. */
35746  if (channels > 8) {
35747  ma_uint32 iChannel;
35748  for (iChannel = 8; iChannel < channels; ++iChannel) {
35749  if (iChannel < MA_MAX_CHANNELS) {
35750  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
35751  } else {
35752  pChannelMap[iChannel] = MA_CHANNEL_NONE;
35753  }
35754  }
35755  }
35756 }
35757 
35758 static void ma_get_standard_channel_map_rfc3551(ma_uint32 channels, ma_channel* pChannelMap)
35759 {
35760  switch (channels)
35761  {
35762  case 1:
35763  {
35764  pChannelMap[0] = MA_CHANNEL_MONO;
35765  } break;
35766 
35767  case 2:
35768  {
35769  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35770  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35771  } break;
35772 
35773  case 3:
35774  {
35775  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35776  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35777  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35778  } break;
35779 
35780  case 4:
35781  {
35782  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35783  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
35784  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
35785  pChannelMap[3] = MA_CHANNEL_BACK_CENTER;
35786  } break;
35787 
35788  case 5:
35789  {
35790  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35791  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35792  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35793  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
35794  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
35795  } break;
35796 
35797  case 6:
35798  {
35799  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35800  pChannelMap[1] = MA_CHANNEL_SIDE_LEFT;
35801  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35802  pChannelMap[3] = MA_CHANNEL_FRONT_RIGHT;
35803  pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
35804  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
35805  } break;
35806  }
35807 
35808  /* Remainder. */
35809  if (channels > 8) {
35810  ma_uint32 iChannel;
35811  for (iChannel = 6; iChannel < channels; ++iChannel) {
35812  if (iChannel < MA_MAX_CHANNELS) {
35813  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-6));
35814  } else {
35815  pChannelMap[iChannel] = MA_CHANNEL_NONE;
35816  }
35817  }
35818  }
35819 }
35820 
35821 static void ma_get_standard_channel_map_flac(ma_uint32 channels, ma_channel* pChannelMap)
35822 {
35823  switch (channels)
35824  {
35825  case 1:
35826  {
35827  pChannelMap[0] = MA_CHANNEL_MONO;
35828  } break;
35829 
35830  case 2:
35831  {
35832  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35833  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35834  } break;
35835 
35836  case 3:
35837  {
35838  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35839  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35840  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35841  } break;
35842 
35843  case 4:
35844  {
35845  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35846  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35847  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35848  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35849  } break;
35850 
35851  case 5:
35852  {
35853  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35854  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35855  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35856  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
35857  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
35858  } break;
35859 
35860  case 6:
35861  {
35862  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35863  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35864  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35865  pChannelMap[3] = MA_CHANNEL_LFE;
35866  pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
35867  pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
35868  } break;
35869 
35870  case 7:
35871  {
35872  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35873  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35874  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35875  pChannelMap[3] = MA_CHANNEL_LFE;
35876  pChannelMap[4] = MA_CHANNEL_BACK_CENTER;
35877  pChannelMap[5] = MA_CHANNEL_SIDE_LEFT;
35878  pChannelMap[6] = MA_CHANNEL_SIDE_RIGHT;
35879  } break;
35880 
35881  case 8:
35882  default:
35883  {
35884  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35885  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35886  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
35887  pChannelMap[3] = MA_CHANNEL_LFE;
35888  pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
35889  pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
35890  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
35891  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
35892  } break;
35893  }
35894 
35895  /* Remainder. */
35896  if (channels > 8) {
35897  ma_uint32 iChannel;
35898  for (iChannel = 8; iChannel < channels; ++iChannel) {
35899  if (iChannel < MA_MAX_CHANNELS) {
35900  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
35901  } else {
35902  pChannelMap[iChannel] = MA_CHANNEL_NONE;
35903  }
35904  }
35905  }
35906 }
35907 
35908 static void ma_get_standard_channel_map_vorbis(ma_uint32 channels, ma_channel* pChannelMap)
35909 {
35910  /* In Vorbis' type 0 channel mapping, the first two channels are not always the standard left/right - it will have the center speaker where the right usually goes. Why?! */
35911  switch (channels)
35912  {
35913  case 1:
35914  {
35915  pChannelMap[0] = MA_CHANNEL_MONO;
35916  } break;
35917 
35918  case 2:
35919  {
35920  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35921  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35922  } break;
35923 
35924  case 3:
35925  {
35926  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35927  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
35928  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
35929  } break;
35930 
35931  case 4:
35932  {
35933  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35934  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
35935  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
35936  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
35937  } break;
35938 
35939  case 5:
35940  {
35941  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35942  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
35943  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
35944  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
35945  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
35946  } break;
35947 
35948  case 6:
35949  {
35950  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35951  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
35952  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
35953  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
35954  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
35955  pChannelMap[5] = MA_CHANNEL_LFE;
35956  } break;
35957 
35958  case 7:
35959  {
35960  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35961  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
35962  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
35963  pChannelMap[3] = MA_CHANNEL_SIDE_LEFT;
35964  pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
35965  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
35966  pChannelMap[6] = MA_CHANNEL_LFE;
35967  } break;
35968 
35969  case 8:
35970  default:
35971  {
35972  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
35973  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
35974  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
35975  pChannelMap[3] = MA_CHANNEL_SIDE_LEFT;
35976  pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
35977  pChannelMap[5] = MA_CHANNEL_BACK_LEFT;
35978  pChannelMap[6] = MA_CHANNEL_BACK_RIGHT;
35979  pChannelMap[7] = MA_CHANNEL_LFE;
35980  } break;
35981  }
35982 
35983  /* Remainder. */
35984  if (channels > 8) {
35985  ma_uint32 iChannel;
35986  for (iChannel = 8; iChannel < channels; ++iChannel) {
35987  if (iChannel < MA_MAX_CHANNELS) {
35988  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
35989  } else {
35990  pChannelMap[iChannel] = MA_CHANNEL_NONE;
35991  }
35992  }
35993  }
35994 }
35995 
35996 static void ma_get_standard_channel_map_sound4(ma_uint32 channels, ma_channel* pChannelMap)
35997 {
35998  switch (channels)
35999  {
36000  case 1:
36001  {
36002  pChannelMap[0] = MA_CHANNEL_MONO;
36003  } break;
36004 
36005  case 2:
36006  {
36007  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36008  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36009  } break;
36010 
36011  case 3:
36012  {
36013  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36014  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36015  pChannelMap[2] = MA_CHANNEL_BACK_CENTER;
36016  } break;
36017 
36018  case 4:
36019  {
36020  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36021  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36022  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36023  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36024  } break;
36025 
36026  case 5:
36027  {
36028  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36029  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36030  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36031  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36032  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
36033  } break;
36034 
36035  case 6:
36036  {
36037  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36038  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36039  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36040  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36041  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
36042  pChannelMap[5] = MA_CHANNEL_LFE;
36043  } break;
36044 
36045  case 7:
36046  {
36047  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36048  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36049  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36050  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36051  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
36052  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
36053  pChannelMap[6] = MA_CHANNEL_LFE;
36054  } break;
36055 
36056  case 8:
36057  default:
36058  {
36059  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36060  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36061  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36062  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36063  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
36064  pChannelMap[5] = MA_CHANNEL_LFE;
36065  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
36066  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
36067  } break;
36068  }
36069 
36070  /* Remainder. */
36071  if (channels > 8) {
36072  ma_uint32 iChannel;
36073  for (iChannel = 8; iChannel < MA_MAX_CHANNELS; ++iChannel) {
36074  if (iChannel < MA_MAX_CHANNELS) {
36075  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
36076  } else {
36077  pChannelMap[iChannel] = MA_CHANNEL_NONE;
36078  }
36079  }
36080  }
36081 }
36082 
36083 static void ma_get_standard_channel_map_sndio(ma_uint32 channels, ma_channel* pChannelMap)
36084 {
36085  switch (channels)
36086  {
36087  case 1:
36088  {
36089  pChannelMap[0] = MA_CHANNEL_MONO;
36090  } break;
36091 
36092  case 2:
36093  {
36094  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36095  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36096  } break;
36097 
36098  case 3:
36099  {
36100  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36101  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36102  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
36103  } break;
36104 
36105  case 4:
36106  {
36107  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36108  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36109  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36110  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36111  } break;
36112 
36113  case 5:
36114  {
36115  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36116  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36117  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36118  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36119  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
36120  } break;
36121 
36122  case 6:
36123  default:
36124  {
36125  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
36126  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
36127  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
36128  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
36129  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
36130  pChannelMap[5] = MA_CHANNEL_LFE;
36131  } break;
36132  }
36133 
36134  /* Remainder. */
36135  if (channels > 6) {
36136  ma_uint32 iChannel;
36137  for (iChannel = 6; iChannel < channels && iChannel < MA_MAX_CHANNELS; ++iChannel) {
36138  if (iChannel < MA_MAX_CHANNELS) {
36139  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-6));
36140  } else {
36141  pChannelMap[iChannel] = MA_CHANNEL_NONE;
36142  }
36143  }
36144  }
36145 }
36146 
36147 MA_API void ma_get_standard_channel_map(ma_standard_channel_map standardChannelMap, ma_uint32 channels, ma_channel* pChannelMap)
36148 {
36149  switch (standardChannelMap)
36150  {
36152  {
36153  ma_get_standard_channel_map_alsa(channels, pChannelMap);
36154  } break;
36155 
36157  {
36158  ma_get_standard_channel_map_rfc3551(channels, pChannelMap);
36159  } break;
36160 
36162  {
36163  ma_get_standard_channel_map_flac(channels, pChannelMap);
36164  } break;
36165 
36167  {
36168  ma_get_standard_channel_map_vorbis(channels, pChannelMap);
36169  } break;
36170 
36172  {
36173  ma_get_standard_channel_map_sound4(channels, pChannelMap);
36174  } break;
36175 
36177  {
36178  ma_get_standard_channel_map_sndio(channels, pChannelMap);
36179  } break;
36180 
36181  case ma_standard_channel_map_microsoft: /* Also default. */
36182  /*case ma_standard_channel_map_default;*/
36183  default:
36184  {
36185  ma_get_standard_channel_map_microsoft(channels, pChannelMap);
36186  } break;
36187  }
36188 }
36189 
36190 MA_API void ma_channel_map_copy(ma_channel* pOut, const ma_channel* pIn, ma_uint32 channels)
36191 {
36192  if (pOut != NULL && pIn != NULL && channels > 0) {
36193  MA_COPY_MEMORY(pOut, pIn, sizeof(*pOut) * channels);
36194  }
36195 }
36196 
36198 {
36199  if (pOut == NULL || channels == 0) {
36200  return;
36201  }
36202 
36203  if (pIn != NULL) {
36204  ma_channel_map_copy(pOut, pIn, channels);
36205  } else {
36207  }
36208 }
36209 
36211 {
36212  if (pChannelMap == NULL) {
36213  return MA_FALSE;
36214  }
36215 
36216  /* A channel count of 0 is invalid. */
36217  if (channels == 0) {
36218  return MA_FALSE;
36219  }
36220 
36221  /* It does not make sense to have a mono channel when there is more than 1 channel. */
36222  if (channels > 1) {
36223  ma_uint32 iChannel;
36224  for (iChannel = 0; iChannel < channels; ++iChannel) {
36225  if (pChannelMap[iChannel] == MA_CHANNEL_MONO) {
36226  return MA_FALSE;
36227  }
36228  }
36229  }
36230 
36231  return MA_TRUE;
36232 }
36233 
36234 MA_API ma_bool32 ma_channel_map_equal(ma_uint32 channels, const ma_channel* pChannelMapA, const ma_channel* pChannelMapB)
36235 {
36236  ma_uint32 iChannel;
36237 
36238  if (pChannelMapA == pChannelMapB) {
36239  return MA_TRUE;
36240  }
36241 
36242  for (iChannel = 0; iChannel < channels; ++iChannel) {
36243  if (ma_channel_map_get_channel(pChannelMapA, channels, iChannel) != ma_channel_map_get_channel(pChannelMapB, channels, iChannel)) {
36244  return MA_FALSE;
36245  }
36246  }
36247 
36248  return MA_TRUE;
36249 }
36250 
36252 {
36253  ma_uint32 iChannel;
36254 
36255  /* A null channel map is equivalent to the default channel map. */
36256  if (pChannelMap == NULL) {
36257  return MA_FALSE;
36258  }
36259 
36260  for (iChannel = 0; iChannel < channels; ++iChannel) {
36261  if (pChannelMap[iChannel] != MA_CHANNEL_NONE) {
36262  return MA_FALSE;
36263  }
36264  }
36265 
36266  return MA_TRUE;
36267 }
36268 
36270 {
36271  ma_uint32 iChannel;
36272 
36273  for (iChannel = 0; iChannel < channels; ++iChannel) {
36274  if (ma_channel_map_get_channel(pChannelMap, channels, iChannel) == channelPosition) {
36275  return MA_TRUE;
36276  }
36277  }
36278 
36279  return MA_FALSE;
36280 }
36281 
36282 
36283 
36284 /**************************************************************************************************************************************************************
36285 
36286 Conversion Helpers
36287 
36288 **************************************************************************************************************************************************************/
36289 MA_API ma_uint64 ma_convert_frames(void* pOut, ma_uint64 frameCountOut, ma_format formatOut, ma_uint32 channelsOut, ma_uint32 sampleRateOut, const void* pIn, ma_uint64 frameCountIn, ma_format formatIn, ma_uint32 channelsIn, ma_uint32 sampleRateIn)
36290 {
36292 
36293  config = ma_data_converter_config_init(formatIn, formatOut, channelsIn, channelsOut, sampleRateIn, sampleRateOut);
36296  config.resampling.linear.lpfOrder = ma_min(MA_DEFAULT_RESAMPLER_LPF_ORDER, MA_MAX_FILTER_ORDER);
36297 
36298  return ma_convert_frames_ex(pOut, frameCountOut, pIn, frameCountIn, &config);
36299 }
36300 
36301 MA_API ma_uint64 ma_convert_frames_ex(void* pOut, ma_uint64 frameCountOut, const void* pIn, ma_uint64 frameCountIn, const ma_data_converter_config* pConfig)
36302 {
36303  ma_result result;
36304  ma_data_converter converter;
36305 
36306  if (frameCountIn == 0 || pConfig == NULL) {
36307  return 0;
36308  }
36309 
36310  result = ma_data_converter_init(pConfig, &converter);
36311  if (result != MA_SUCCESS) {
36312  return 0; /* Failed to initialize the data converter. */
36313  }
36314 
36315  if (pOut == NULL) {
36316  frameCountOut = ma_data_converter_get_expected_output_frame_count(&converter, frameCountIn);
36317  } else {
36318  result = ma_data_converter_process_pcm_frames(&converter, pIn, &frameCountIn, pOut, &frameCountOut);
36319  if (result != MA_SUCCESS) {
36320  frameCountOut = 0;
36321  }
36322  }
36323 
36324  ma_data_converter_uninit(&converter);
36325  return frameCountOut;
36326 }
36327 
36328 
36329 /**************************************************************************************************************************************************************
36330 
36331 Ring Buffer
36332 
36333 **************************************************************************************************************************************************************/
36335 {
36336  return encodedOffset & 0x7FFFFFFF;
36337 }
36338 
36340 {
36341  return encodedOffset & 0x80000000;
36342 }
36343 
36345 {
36346  MA_ASSERT(pRB != NULL);
36348 }
36349 
36351 {
36352  MA_ASSERT(pRB != NULL);
36354 }
36355 
36356 static MA_INLINE ma_uint32 ma_rb__construct_offset(ma_uint32 offsetInBytes, ma_uint32 offsetLoopFlag)
36357 {
36358  return offsetLoopFlag | offsetInBytes;
36359 }
36360 
36361 static MA_INLINE void ma_rb__deconstruct_offset(ma_uint32 encodedOffset, ma_uint32* pOffsetInBytes, ma_uint32* pOffsetLoopFlag)
36362 {
36363  MA_ASSERT(pOffsetInBytes != NULL);
36364  MA_ASSERT(pOffsetLoopFlag != NULL);
36365 
36366  *pOffsetInBytes = ma_rb__extract_offset_in_bytes(encodedOffset);
36367  *pOffsetLoopFlag = ma_rb__extract_offset_loop_flag(encodedOffset);
36368 }
36369 
36370 
36371 MA_API ma_result ma_rb_init_ex(size_t subbufferSizeInBytes, size_t subbufferCount, size_t subbufferStrideInBytes, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_rb* pRB)
36372 {
36373  ma_result result;
36374  const ma_uint32 maxSubBufferSize = 0x7FFFFFFF - (MA_SIMD_ALIGNMENT-1);
36375 
36376  if (pRB == NULL) {
36377  return MA_INVALID_ARGS;
36378  }
36379 
36380  if (subbufferSizeInBytes == 0 || subbufferCount == 0) {
36381  return MA_INVALID_ARGS;
36382  }
36383 
36384  if (subbufferSizeInBytes > maxSubBufferSize) {
36385  return MA_INVALID_ARGS; /* Maximum buffer size is ~2GB. The most significant bit is a flag for use internally. */
36386  }
36387 
36388 
36389  MA_ZERO_OBJECT(pRB);
36390 
36391  result = ma_allocation_callbacks_init_copy(&pRB->allocationCallbacks, pAllocationCallbacks);
36392  if (result != MA_SUCCESS) {
36393  return result;
36394  }
36395 
36396  pRB->subbufferSizeInBytes = (ma_uint32)subbufferSizeInBytes;
36397  pRB->subbufferCount = (ma_uint32)subbufferCount;
36398 
36399  if (pOptionalPreallocatedBuffer != NULL) {
36400  pRB->subbufferStrideInBytes = (ma_uint32)subbufferStrideInBytes;
36401  pRB->pBuffer = pOptionalPreallocatedBuffer;
36402  } else {
36403  size_t bufferSizeInBytes;
36404 
36405  /*
36406  Here is where we allocate our own buffer. We always want to align this to MA_SIMD_ALIGNMENT for future SIMD optimization opportunity. To do this
36407  we need to make sure the stride is a multiple of MA_SIMD_ALIGNMENT.
36408  */
36410 
36411  bufferSizeInBytes = (size_t)pRB->subbufferCount*pRB->subbufferStrideInBytes;
36412  pRB->pBuffer = ma_aligned_malloc(bufferSizeInBytes, MA_SIMD_ALIGNMENT, &pRB->allocationCallbacks);
36413  if (pRB->pBuffer == NULL) {
36414  return MA_OUT_OF_MEMORY;
36415  }
36416 
36417  MA_ZERO_MEMORY(pRB->pBuffer, bufferSizeInBytes);
36418  pRB->ownsBuffer = MA_TRUE;
36419  }
36420 
36421  return MA_SUCCESS;
36422 }
36423 
36424 MA_API ma_result ma_rb_init(size_t bufferSizeInBytes, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_rb* pRB)
36425 {
36426  return ma_rb_init_ex(bufferSizeInBytes, 1, 0, pOptionalPreallocatedBuffer, pAllocationCallbacks, pRB);
36427 }
36428 
36430 {
36431  if (pRB == NULL) {
36432  return;
36433  }
36434 
36435  if (pRB->ownsBuffer) {
36437  }
36438 }
36439 
36441 {
36442  if (pRB == NULL) {
36443  return;
36444  }
36445 
36448 }
36449 
36450 MA_API ma_result ma_rb_acquire_read(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut)
36451 {
36452  ma_uint32 writeOffset;
36453  ma_uint32 writeOffsetInBytes;
36454  ma_uint32 writeOffsetLoopFlag;
36455  ma_uint32 readOffset;
36456  ma_uint32 readOffsetInBytes;
36457  ma_uint32 readOffsetLoopFlag;
36458  size_t bytesAvailable;
36459  size_t bytesRequested;
36460 
36461  if (pRB == NULL || pSizeInBytes == NULL || ppBufferOut == NULL) {
36462  return MA_INVALID_ARGS;
36463  }
36464 
36465  /* The returned buffer should never move ahead of the write pointer. */
36466  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
36467  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
36468 
36469  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
36470  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
36471 
36472  /*
36473  The number of bytes available depends on whether or not the read and write pointers are on the same loop iteration. If so, we
36474  can only read up to the write pointer. If not, we can only read up to the end of the buffer.
36475  */
36476  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
36477  bytesAvailable = writeOffsetInBytes - readOffsetInBytes;
36478  } else {
36479  bytesAvailable = pRB->subbufferSizeInBytes - readOffsetInBytes;
36480  }
36481 
36482  bytesRequested = *pSizeInBytes;
36483  if (bytesRequested > bytesAvailable) {
36484  bytesRequested = bytesAvailable;
36485  }
36486 
36487  *pSizeInBytes = bytesRequested;
36488  (*ppBufferOut) = ma_rb__get_read_ptr(pRB);
36489 
36490  return MA_SUCCESS;
36491 }
36492 
36493 MA_API ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut)
36494 {
36495  ma_uint32 readOffset;
36496  ma_uint32 readOffsetInBytes;
36497  ma_uint32 readOffsetLoopFlag;
36498  ma_uint32 newReadOffsetInBytes;
36499  ma_uint32 newReadOffsetLoopFlag;
36500 
36501  if (pRB == NULL) {
36502  return MA_INVALID_ARGS;
36503  }
36504 
36505  /* Validate the buffer. */
36506  if (pBufferOut != ma_rb__get_read_ptr(pRB)) {
36507  return MA_INVALID_ARGS;
36508  }
36509 
36510  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
36511  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
36512 
36513  /* Check that sizeInBytes is correct. It should never go beyond the end of the buffer. */
36514  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + sizeInBytes);
36515  if (newReadOffsetInBytes > pRB->subbufferSizeInBytes) {
36516  return MA_INVALID_ARGS; /* <-- sizeInBytes will cause the read offset to overflow. */
36517  }
36518 
36519  /* Move the read pointer back to the start if necessary. */
36520  newReadOffsetLoopFlag = readOffsetLoopFlag;
36521  if (newReadOffsetInBytes == pRB->subbufferSizeInBytes) {
36522  newReadOffsetInBytes = 0;
36523  newReadOffsetLoopFlag ^= 0x80000000;
36524  }
36525 
36526  c89atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetLoopFlag, newReadOffsetInBytes));
36527 
36528  if (ma_rb_pointer_distance(pRB) == 0) {
36529  return MA_AT_END;
36530  } else {
36531  return MA_SUCCESS;
36532  }
36533 }
36534 
36535 MA_API ma_result ma_rb_acquire_write(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut)
36536 {
36537  ma_uint32 readOffset;
36538  ma_uint32 readOffsetInBytes;
36539  ma_uint32 readOffsetLoopFlag;
36540  ma_uint32 writeOffset;
36541  ma_uint32 writeOffsetInBytes;
36542  ma_uint32 writeOffsetLoopFlag;
36543  size_t bytesAvailable;
36544  size_t bytesRequested;
36545 
36546  if (pRB == NULL || pSizeInBytes == NULL || ppBufferOut == NULL) {
36547  return MA_INVALID_ARGS;
36548  }
36549 
36550  /* The returned buffer should never overtake the read buffer. */
36551  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
36552  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
36553 
36554  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
36555  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
36556 
36557  /*
36558  In the case of writing, if the write pointer and the read pointer are on the same loop iteration we can only
36559  write up to the end of the buffer. Otherwise we can only write up to the read pointer. The write pointer should
36560  never overtake the read pointer.
36561  */
36562  if (writeOffsetLoopFlag == readOffsetLoopFlag) {
36563  bytesAvailable = pRB->subbufferSizeInBytes - writeOffsetInBytes;
36564  } else {
36565  bytesAvailable = readOffsetInBytes - writeOffsetInBytes;
36566  }
36567 
36568  bytesRequested = *pSizeInBytes;
36569  if (bytesRequested > bytesAvailable) {
36570  bytesRequested = bytesAvailable;
36571  }
36572 
36573  *pSizeInBytes = bytesRequested;
36574  *ppBufferOut = ma_rb__get_write_ptr(pRB);
36575 
36576  /* Clear the buffer if desired. */
36577  if (pRB->clearOnWriteAcquire) {
36578  MA_ZERO_MEMORY(*ppBufferOut, *pSizeInBytes);
36579  }
36580 
36581  return MA_SUCCESS;
36582 }
36583 
36584 MA_API ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut)
36585 {
36586  ma_uint32 writeOffset;
36587  ma_uint32 writeOffsetInBytes;
36588  ma_uint32 writeOffsetLoopFlag;
36589  ma_uint32 newWriteOffsetInBytes;
36590  ma_uint32 newWriteOffsetLoopFlag;
36591 
36592  if (pRB == NULL) {
36593  return MA_INVALID_ARGS;
36594  }
36595 
36596  /* Validate the buffer. */
36597  if (pBufferOut != ma_rb__get_write_ptr(pRB)) {
36598  return MA_INVALID_ARGS;
36599  }
36600 
36601  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
36602  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
36603 
36604  /* Check that sizeInBytes is correct. It should never go beyond the end of the buffer. */
36605  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + sizeInBytes);
36606  if (newWriteOffsetInBytes > pRB->subbufferSizeInBytes) {
36607  return MA_INVALID_ARGS; /* <-- sizeInBytes will cause the read offset to overflow. */
36608  }
36609 
36610  /* Move the read pointer back to the start if necessary. */
36611  newWriteOffsetLoopFlag = writeOffsetLoopFlag;
36612  if (newWriteOffsetInBytes == pRB->subbufferSizeInBytes) {
36613  newWriteOffsetInBytes = 0;
36614  newWriteOffsetLoopFlag ^= 0x80000000;
36615  }
36616 
36617  c89atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetLoopFlag, newWriteOffsetInBytes));
36618 
36619  if (ma_rb_pointer_distance(pRB) == 0) {
36620  return MA_AT_END;
36621  } else {
36622  return MA_SUCCESS;
36623  }
36624 }
36625 
36626 MA_API ma_result ma_rb_seek_read(ma_rb* pRB, size_t offsetInBytes)
36627 {
36628  ma_uint32 readOffset;
36629  ma_uint32 readOffsetInBytes;
36630  ma_uint32 readOffsetLoopFlag;
36631  ma_uint32 writeOffset;
36632  ma_uint32 writeOffsetInBytes;
36633  ma_uint32 writeOffsetLoopFlag;
36634  ma_uint32 newReadOffsetInBytes;
36635  ma_uint32 newReadOffsetLoopFlag;
36636 
36637  if (pRB == NULL || offsetInBytes > pRB->subbufferSizeInBytes) {
36638  return MA_INVALID_ARGS;
36639  }
36640 
36641  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
36642  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
36643 
36644  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
36645  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
36646 
36647  newReadOffsetLoopFlag = readOffsetLoopFlag;
36648 
36649  /* We cannot go past the write buffer. */
36650  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
36651  if ((readOffsetInBytes + offsetInBytes) > writeOffsetInBytes) {
36652  newReadOffsetInBytes = writeOffsetInBytes;
36653  } else {
36654  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + offsetInBytes);
36655  }
36656  } else {
36657  /* May end up looping. */
36658  if ((readOffsetInBytes + offsetInBytes) >= pRB->subbufferSizeInBytes) {
36659  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + offsetInBytes) - pRB->subbufferSizeInBytes;
36660  newReadOffsetLoopFlag ^= 0x80000000; /* <-- Looped. */
36661  } else {
36662  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + offsetInBytes);
36663  }
36664  }
36665 
36666  c89atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetInBytes, newReadOffsetLoopFlag));
36667  return MA_SUCCESS;
36668 }
36669 
36670 MA_API ma_result ma_rb_seek_write(ma_rb* pRB, size_t offsetInBytes)
36671 {
36672  ma_uint32 readOffset;
36673  ma_uint32 readOffsetInBytes;
36674  ma_uint32 readOffsetLoopFlag;
36675  ma_uint32 writeOffset;
36676  ma_uint32 writeOffsetInBytes;
36677  ma_uint32 writeOffsetLoopFlag;
36678  ma_uint32 newWriteOffsetInBytes;
36679  ma_uint32 newWriteOffsetLoopFlag;
36680 
36681  if (pRB == NULL) {
36682  return MA_INVALID_ARGS;
36683  }
36684 
36685  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
36686  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
36687 
36688  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
36689  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
36690 
36691  newWriteOffsetLoopFlag = writeOffsetLoopFlag;
36692 
36693  /* We cannot go past the write buffer. */
36694  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
36695  /* May end up looping. */
36696  if ((writeOffsetInBytes + offsetInBytes) >= pRB->subbufferSizeInBytes) {
36697  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + offsetInBytes) - pRB->subbufferSizeInBytes;
36698  newWriteOffsetLoopFlag ^= 0x80000000; /* <-- Looped. */
36699  } else {
36700  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + offsetInBytes);
36701  }
36702  } else {
36703  if ((writeOffsetInBytes + offsetInBytes) > readOffsetInBytes) {
36704  newWriteOffsetInBytes = readOffsetInBytes;
36705  } else {
36706  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + offsetInBytes);
36707  }
36708  }
36709 
36710  c89atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetInBytes, newWriteOffsetLoopFlag));
36711  return MA_SUCCESS;
36712 }
36713 
36715 {
36716  ma_uint32 readOffset;
36717  ma_uint32 readOffsetInBytes;
36718  ma_uint32 readOffsetLoopFlag;
36719  ma_uint32 writeOffset;
36720  ma_uint32 writeOffsetInBytes;
36721  ma_uint32 writeOffsetLoopFlag;
36722 
36723  if (pRB == NULL) {
36724  return 0;
36725  }
36726 
36727  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
36728  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
36729 
36730  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
36731  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
36732 
36733  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
36734  return writeOffsetInBytes - readOffsetInBytes;
36735  } else {
36736  return writeOffsetInBytes + (pRB->subbufferSizeInBytes - readOffsetInBytes);
36737  }
36738 }
36739 
36741 {
36742  ma_int32 dist;
36743 
36744  if (pRB == NULL) {
36745  return 0;
36746  }
36747 
36748  dist = ma_rb_pointer_distance(pRB);
36749  if (dist < 0) {
36750  return 0;
36751  }
36752 
36753  return dist;
36754 }
36755 
36757 {
36758  if (pRB == NULL) {
36759  return 0;
36760  }
36761 
36763 }
36764 
36766 {
36767  if (pRB == NULL) {
36768  return 0;
36769  }
36770 
36771  return pRB->subbufferSizeInBytes;
36772 }
36773 
36775 {
36776  if (pRB == NULL) {
36777  return 0;
36778  }
36779 
36780  if (pRB->subbufferStrideInBytes == 0) {
36781  return (size_t)pRB->subbufferSizeInBytes;
36782  }
36783 
36784  return (size_t)pRB->subbufferStrideInBytes;
36785 }
36786 
36787 MA_API size_t ma_rb_get_subbuffer_offset(ma_rb* pRB, size_t subbufferIndex)
36788 {
36789  if (pRB == NULL) {
36790  return 0;
36791  }
36792 
36793  return subbufferIndex * ma_rb_get_subbuffer_stride(pRB);
36794 }
36795 
36796 MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pBuffer)
36797 {
36798  if (pRB == NULL) {
36799  return NULL;
36800  }
36801 
36802  return ma_offset_ptr(pBuffer, ma_rb_get_subbuffer_offset(pRB, subbufferIndex));
36803 }
36804 
36805 
36806 
36808 {
36809  MA_ASSERT(pRB != NULL);
36810 
36811  return ma_get_bytes_per_frame(pRB->format, pRB->channels);
36812 }
36813 
36814 MA_API ma_result ma_pcm_rb_init_ex(ma_format format, ma_uint32 channels, ma_uint32 subbufferSizeInFrames, ma_uint32 subbufferCount, ma_uint32 subbufferStrideInFrames, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_pcm_rb* pRB)
36815 {
36816  ma_uint32 bpf;
36817  ma_result result;
36818 
36819  if (pRB == NULL) {
36820  return MA_INVALID_ARGS;
36821  }
36822 
36823  MA_ZERO_OBJECT(pRB);
36824 
36825  bpf = ma_get_bytes_per_frame(format, channels);
36826  if (bpf == 0) {
36827  return MA_INVALID_ARGS;
36828  }
36829 
36830  result = ma_rb_init_ex(subbufferSizeInFrames*bpf, subbufferCount, subbufferStrideInFrames*bpf, pOptionalPreallocatedBuffer, pAllocationCallbacks, &pRB->rb);
36831  if (result != MA_SUCCESS) {
36832  return result;
36833  }
36834 
36835  pRB->format = format;
36836  pRB->channels = channels;
36837 
36838  return MA_SUCCESS;
36839 }
36840 
36841 MA_API ma_result ma_pcm_rb_init(ma_format format, ma_uint32 channels, ma_uint32 bufferSizeInFrames, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_pcm_rb* pRB)
36842 {
36843  return ma_pcm_rb_init_ex(format, channels, bufferSizeInFrames, 1, 0, pOptionalPreallocatedBuffer, pAllocationCallbacks, pRB);
36844 }
36845 
36847 {
36848  if (pRB == NULL) {
36849  return;
36850  }
36851 
36852  ma_rb_uninit(&pRB->rb);
36853 }
36854 
36856 {
36857  if (pRB == NULL) {
36858  return;
36859  }
36860 
36861  ma_rb_reset(&pRB->rb);
36862 }
36863 
36864 MA_API ma_result ma_pcm_rb_acquire_read(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut)
36865 {
36866  size_t sizeInBytes;
36867  ma_result result;
36868 
36869  if (pRB == NULL || pSizeInFrames == NULL) {
36870  return MA_INVALID_ARGS;
36871  }
36872 
36873  sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
36874 
36875  result = ma_rb_acquire_read(&pRB->rb, &sizeInBytes, ppBufferOut);
36876  if (result != MA_SUCCESS) {
36877  return result;
36878  }
36879 
36880  *pSizeInFrames = (ma_uint32)(sizeInBytes / (size_t)ma_pcm_rb_get_bpf(pRB));
36881  return MA_SUCCESS;
36882 }
36883 
36884 MA_API ma_result ma_pcm_rb_commit_read(ma_pcm_rb* pRB, ma_uint32 sizeInFrames, void* pBufferOut)
36885 {
36886  if (pRB == NULL) {
36887  return MA_INVALID_ARGS;
36888  }
36889 
36890  return ma_rb_commit_read(&pRB->rb, sizeInFrames * ma_pcm_rb_get_bpf(pRB), pBufferOut);
36891 }
36892 
36893 MA_API ma_result ma_pcm_rb_acquire_write(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut)
36894 {
36895  size_t sizeInBytes;
36896  ma_result result;
36897 
36898  if (pRB == NULL) {
36899  return MA_INVALID_ARGS;
36900  }
36901 
36902  sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
36903 
36904  result = ma_rb_acquire_write(&pRB->rb, &sizeInBytes, ppBufferOut);
36905  if (result != MA_SUCCESS) {
36906  return result;
36907  }
36908 
36909  *pSizeInFrames = (ma_uint32)(sizeInBytes / ma_pcm_rb_get_bpf(pRB));
36910  return MA_SUCCESS;
36911 }
36912 
36913 MA_API ma_result ma_pcm_rb_commit_write(ma_pcm_rb* pRB, ma_uint32 sizeInFrames, void* pBufferOut)
36914 {
36915  if (pRB == NULL) {
36916  return MA_INVALID_ARGS;
36917  }
36918 
36919  return ma_rb_commit_write(&pRB->rb, sizeInFrames * ma_pcm_rb_get_bpf(pRB), pBufferOut);
36920 }
36921 
36923 {
36924  if (pRB == NULL) {
36925  return MA_INVALID_ARGS;
36926  }
36927 
36928  return ma_rb_seek_read(&pRB->rb, offsetInFrames * ma_pcm_rb_get_bpf(pRB));
36929 }
36930 
36932 {
36933  if (pRB == NULL) {
36934  return MA_INVALID_ARGS;
36935  }
36936 
36937  return ma_rb_seek_write(&pRB->rb, offsetInFrames * ma_pcm_rb_get_bpf(pRB));
36938 }
36939 
36941 {
36942  if (pRB == NULL) {
36943  return 0;
36944  }
36945 
36946  return ma_rb_pointer_distance(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
36947 }
36948 
36950 {
36951  if (pRB == NULL) {
36952  return 0;
36953  }
36954 
36955  return ma_rb_available_read(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
36956 }
36957 
36959 {
36960  if (pRB == NULL) {
36961  return 0;
36962  }
36963 
36964  return ma_rb_available_write(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
36965 }
36966 
36968 {
36969  if (pRB == NULL) {
36970  return 0;
36971  }
36972 
36973  return (ma_uint32)(ma_rb_get_subbuffer_size(&pRB->rb) / ma_pcm_rb_get_bpf(pRB));
36974 }
36975 
36977 {
36978  if (pRB == NULL) {
36979  return 0;
36980  }
36981 
36982  return (ma_uint32)(ma_rb_get_subbuffer_stride(&pRB->rb) / ma_pcm_rb_get_bpf(pRB));
36983 }
36984 
36986 {
36987  if (pRB == NULL) {
36988  return 0;
36989  }
36990 
36991  return (ma_uint32)(ma_rb_get_subbuffer_offset(&pRB->rb, subbufferIndex) / ma_pcm_rb_get_bpf(pRB));
36992 }
36993 
36994 MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer)
36995 {
36996  if (pRB == NULL) {
36997  return NULL;
36998  }
36999 
37000  return ma_rb_get_subbuffer_ptr(&pRB->rb, subbufferIndex, pBuffer);
37001 }
37002 
37003 
37004 
37005 MA_API ma_result ma_duplex_rb_init(ma_format captureFormat, ma_uint32 captureChannels, ma_uint32 sampleRate, ma_uint32 captureInternalSampleRate, ma_uint32 captureInternalPeriodSizeInFrames, const ma_allocation_callbacks* pAllocationCallbacks, ma_duplex_rb* pRB)
37006 {
37007  ma_result result;
37008  ma_uint32 sizeInFrames;
37009 
37010  sizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(sampleRate, captureInternalSampleRate, captureInternalPeriodSizeInFrames * 5);
37011  if (sizeInFrames == 0) {
37012  return MA_INVALID_ARGS;
37013  }
37014 
37015  result = ma_pcm_rb_init(captureFormat, captureChannels, sizeInFrames, NULL, pAllocationCallbacks, &pRB->rb);
37016  if (result != MA_SUCCESS) {
37017  return result;
37018  }
37019 
37020  /* Seek forward a bit so we have a bit of a buffer in case of desyncs. */
37021  ma_pcm_rb_seek_write((ma_pcm_rb*)pRB, captureInternalPeriodSizeInFrames * 2);
37022 
37023  return MA_SUCCESS;
37024 }
37025 
37027 {
37028  ma_pcm_rb_uninit((ma_pcm_rb*)pRB);
37029  return MA_SUCCESS;
37030 }
37031 
37032 
37033 
37034 /**************************************************************************************************************************************************************
37035 
37036 Miscellaneous Helpers
37037 
37038 **************************************************************************************************************************************************************/
37040 {
37041  switch (result)
37042  {
37043  case MA_SUCCESS: return "No error";
37044  case MA_ERROR: return "Unknown error";
37045  case MA_INVALID_ARGS: return "Invalid argument";
37046  case MA_INVALID_OPERATION: return "Invalid operation";
37047  case MA_OUT_OF_MEMORY: return "Out of memory";
37048  case MA_OUT_OF_RANGE: return "Out of range";
37049  case MA_ACCESS_DENIED: return "Permission denied";
37050  case MA_DOES_NOT_EXIST: return "Resource does not exist";
37051  case MA_ALREADY_EXISTS: return "Resource already exists";
37052  case MA_TOO_MANY_OPEN_FILES: return "Too many open files";
37053  case MA_INVALID_FILE: return "Invalid file";
37054  case MA_TOO_BIG: return "Too large";
37055  case MA_PATH_TOO_LONG: return "Path too long";
37056  case MA_NAME_TOO_LONG: return "Name too long";
37057  case MA_NOT_DIRECTORY: return "Not a directory";
37058  case MA_IS_DIRECTORY: return "Is a directory";
37059  case MA_DIRECTORY_NOT_EMPTY: return "Directory not empty";
37060  case MA_AT_END: return "At end";
37061  case MA_NO_SPACE: return "No space available";
37062  case MA_BUSY: return "Device or resource busy";
37063  case MA_IO_ERROR: return "Input/output error";
37064  case MA_INTERRUPT: return "Interrupted";
37065  case MA_UNAVAILABLE: return "Resource unavailable";
37066  case MA_ALREADY_IN_USE: return "Resource already in use";
37067  case MA_BAD_ADDRESS: return "Bad address";
37068  case MA_BAD_SEEK: return "Illegal seek";
37069  case MA_BAD_PIPE: return "Broken pipe";
37070  case MA_DEADLOCK: return "Deadlock";
37071  case MA_TOO_MANY_LINKS: return "Too many links";
37072  case MA_NOT_IMPLEMENTED: return "Not implemented";
37073  case MA_NO_MESSAGE: return "No message of desired type";
37074  case MA_BAD_MESSAGE: return "Invalid message";
37075  case MA_NO_DATA_AVAILABLE: return "No data available";
37076  case MA_INVALID_DATA: return "Invalid data";
37077  case MA_TIMEOUT: return "Timeout";
37078  case MA_NO_NETWORK: return "Network unavailable";
37079  case MA_NOT_UNIQUE: return "Not unique";
37080  case MA_NOT_SOCKET: return "Socket operation on non-socket";
37081  case MA_NO_ADDRESS: return "Destination address required";
37082  case MA_BAD_PROTOCOL: return "Protocol wrong type for socket";
37083  case MA_PROTOCOL_UNAVAILABLE: return "Protocol not available";
37084  case MA_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
37085  case MA_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
37086  case MA_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
37087  case MA_SOCKET_NOT_SUPPORTED: return "Socket type not supported";
37088  case MA_CONNECTION_RESET: return "Connection reset";
37089  case MA_ALREADY_CONNECTED: return "Already connected";
37090  case MA_NOT_CONNECTED: return "Not connected";
37091  case MA_CONNECTION_REFUSED: return "Connection refused";
37092  case MA_NO_HOST: return "No host";
37093  case MA_IN_PROGRESS: return "Operation in progress";
37094  case MA_CANCELLED: return "Operation cancelled";
37095  case MA_MEMORY_ALREADY_MAPPED: return "Memory already mapped";
37096 
37097  case MA_FORMAT_NOT_SUPPORTED: return "Format not supported";
37098  case MA_DEVICE_TYPE_NOT_SUPPORTED: return "Device type not supported";
37099  case MA_SHARE_MODE_NOT_SUPPORTED: return "Share mode not supported";
37100  case MA_NO_BACKEND: return "No backend";
37101  case MA_NO_DEVICE: return "No device";
37102  case MA_API_NOT_FOUND: return "API not found";
37103  case MA_INVALID_DEVICE_CONFIG: return "Invalid device config";
37104 
37105  case MA_DEVICE_NOT_INITIALIZED: return "Device not initialized";
37106  case MA_DEVICE_NOT_STARTED: return "Device not started";
37107 
37108  case MA_FAILED_TO_INIT_BACKEND: return "Failed to initialize backend";
37109  case MA_FAILED_TO_OPEN_BACKEND_DEVICE: return "Failed to open backend device";
37110  case MA_FAILED_TO_START_BACKEND_DEVICE: return "Failed to start backend device";
37111  case MA_FAILED_TO_STOP_BACKEND_DEVICE: return "Failed to stop backend device";
37112 
37113  default: return "Unknown error";
37114  }
37115 }
37116 
37117 MA_API void* ma_malloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
37118 {
37119  if (pAllocationCallbacks != NULL) {
37120  return ma__malloc_from_callbacks(sz, pAllocationCallbacks);
37121  } else {
37122  return ma__malloc_default(sz, NULL);
37123  }
37124 }
37125 
37126 MA_API void* ma_realloc(void* p, size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
37127 {
37128  if (pAllocationCallbacks != NULL) {
37129  if (pAllocationCallbacks->onRealloc != NULL) {
37130  return pAllocationCallbacks->onRealloc(p, sz, pAllocationCallbacks->pUserData);
37131  } else {
37132  return NULL; /* This requires a native implementation of realloc(). */
37133  }
37134  } else {
37135  return ma__realloc_default(p, sz, NULL);
37136  }
37137 }
37138 
37139 MA_API void ma_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
37140 {
37141  if (pAllocationCallbacks != NULL) {
37142  ma__free_from_callbacks(p, pAllocationCallbacks);
37143  } else {
37144  ma__free_default(p, NULL);
37145  }
37146 }
37147 
37148 MA_API void* ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks* pAllocationCallbacks)
37149 {
37150  size_t extraBytes;
37151  void* pUnaligned;
37152  void* pAligned;
37153 
37154  if (alignment == 0) {
37155  return 0;
37156  }
37157 
37158  extraBytes = alignment-1 + sizeof(void*);
37159 
37160  pUnaligned = ma_malloc(sz + extraBytes, pAllocationCallbacks);
37161  if (pUnaligned == NULL) {
37162  return NULL;
37163  }
37164 
37165  pAligned = (void*)(((ma_uintptr)pUnaligned + extraBytes) & ~((ma_uintptr)(alignment-1)));
37166  ((void**)pAligned)[-1] = pUnaligned;
37167 
37168  return pAligned;
37169 }
37170 
37171 MA_API void ma_aligned_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
37172 {
37173  ma_free(((void**)p)[-1], pAllocationCallbacks);
37174 }
37175 
37177 {
37178  switch (format)
37179  {
37180  case ma_format_unknown: return "Unknown";
37181  case ma_format_u8: return "8-bit Unsigned Integer";
37182  case ma_format_s16: return "16-bit Signed Integer";
37183  case ma_format_s24: return "24-bit Signed Integer (Tightly Packed)";
37184  case ma_format_s32: return "32-bit Signed Integer";
37185  case ma_format_f32: return "32-bit IEEE Floating Point";
37186  default: return "Invalid";
37187  }
37188 }
37189 
37190 MA_API void ma_blend_f32(float* pOut, float* pInA, float* pInB, float factor, ma_uint32 channels)
37191 {
37192  ma_uint32 i;
37193  for (i = 0; i < channels; ++i) {
37194  pOut[i] = ma_mix_f32(pInA[i], pInB[i], factor);
37195  }
37196 }
37197 
37198 
37200 {
37201  ma_uint32 sizes[] = {
37202  0, /* unknown */
37203  1, /* u8 */
37204  2, /* s16 */
37205  3, /* s24 */
37206  4, /* s32 */
37207  4, /* f32 */
37208  };
37209  return sizes[format];
37210 }
37211 
37212 
37213 
37215 {
37217 
37219 
37220  return config;
37221 }
37222 
37223 
37225 {
37226  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37227 
37228  if (pDataSource == NULL) {
37229  return MA_INVALID_ARGS;
37230  }
37231 
37232  MA_ZERO_OBJECT(pDataSourceBase);
37233 
37234  if (pConfig == NULL) {
37235  return MA_INVALID_ARGS;
37236  }
37237 
37238  pDataSourceBase->vtable = pConfig->vtable;
37239  pDataSourceBase->rangeBegInFrames = 0;
37240  pDataSourceBase->rangeEndInFrames = ~((ma_uint64)0);
37241  pDataSourceBase->loopBegInFrames = 0;
37242  pDataSourceBase->loopEndInFrames = ~((ma_uint64)0);
37243  pDataSourceBase->pCurrent = pDataSource; /* Always read from ourself by default. */
37244  pDataSourceBase->pNext = NULL;
37245  pDataSourceBase->onGetNext = NULL;
37246 
37247  /* Compatibility: Need to make a copy of the callbacks. This will be removed in version 0.11. */
37248  if (pConfig->vtable != NULL) {
37249  pDataSourceBase->cb = *pConfig->vtable;
37250  }
37251 
37252  return MA_SUCCESS;
37253 }
37254 
37256 {
37257  if (pDataSource == NULL) {
37258  return;
37259  }
37260 
37261  /*
37262  This is placeholder in case we need this later. Data sources need to call this in their
37263  uninitialization routine to ensure things work later on if something is added here.
37264  */
37265 }
37266 
37267 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
37268 static ma_result ma_data_source_resolve_current(ma_data_source* pDataSource, ma_data_source** ppCurrentDataSource)
37269 {
37270  ma_data_source_base* pCurrentDataSource = (ma_data_source_base*)pDataSource;
37271 
37272  MA_ASSERT(pDataSource != NULL);
37273  MA_ASSERT(ppCurrentDataSource != NULL);
37274 
37275  if (pCurrentDataSource->pCurrent == NULL) {
37276  /*
37277  The current data source is NULL. If we're using this in the context of a chain we need to return NULL
37278  here so that we don't end up looping. Otherwise we just return the data source itself.
37279  */
37280  if (pCurrentDataSource->pNext != NULL || pCurrentDataSource->onGetNext != NULL) {
37281  pCurrentDataSource = NULL;
37282  } else {
37283  pCurrentDataSource = (ma_data_source_base*)pDataSource; /* Not being used in a chain. Make sure we just always read from the data source itself at all times. */
37284  }
37285  } else {
37286  pCurrentDataSource = (ma_data_source_base*)pCurrentDataSource->pCurrent;
37287  }
37288 
37289  *ppCurrentDataSource = pCurrentDataSource;
37290 
37291  return MA_SUCCESS;
37292 }
37293 
37294 static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop)
37295 {
37296  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37297 
37298  if (pDataSourceBase == NULL) {
37299  return MA_AT_END;
37300  }
37301 
37302  if (pDataSourceBase->rangeEndInFrames == ~((ma_uint64)0) && (pDataSourceBase->loopEndInFrames == ~((ma_uint64)0) || loop == MA_FALSE)) {
37303  /* No range is set - just read like normal. The data source itself will tell us when the end is reached. */
37304  return pDataSourceBase->cb.onRead(pDataSourceBase, pFramesOut, frameCount, pFramesRead);
37305  } else {
37306  /* Need to clamp to within the range. */
37307  ma_result result;
37308  ma_uint64 cursor;
37309  ma_uint64 framesRead = 0;
37310  ma_uint64 rangeEnd;
37311 
37312  result = ma_data_source_get_cursor_in_pcm_frames(pDataSourceBase, &cursor);
37313  if (result != MA_SUCCESS) {
37314  /* Failed to retrieve the cursor. Cannot read within a range or loop points. Just read like normal - this may happen for things like noise data sources where it doesn't really matter. */
37315  return pDataSourceBase->cb.onRead(pDataSourceBase, pFramesOut, frameCount, pFramesRead);
37316  }
37317 
37318  /* We have the cursor. We need to make sure we don't read beyond our range. */
37319  rangeEnd = pDataSourceBase->rangeEndInFrames;
37320 
37321  /* If looping, make sure we're within range. */
37322  if (loop) {
37323  if (pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) {
37324  rangeEnd = ma_min(rangeEnd, pDataSourceBase->rangeBegInFrames + pDataSourceBase->loopEndInFrames);
37325  }
37326  }
37327 
37328  if (frameCount > (rangeEnd - cursor) && rangeEnd != ~((ma_uint64)0)) {
37329  frameCount = (rangeEnd - cursor);
37330  }
37331 
37332  result = pDataSourceBase->cb.onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead);
37333 
37334  if (pFramesRead != NULL) {
37335  *pFramesRead = framesRead;
37336  }
37337 
37338  /* We need to make sure MA_AT_END is returned if we hit the end of the range. */
37339  if (result != MA_AT_END && framesRead == 0) {
37340  result = MA_AT_END;
37341  }
37342 
37343  return result;
37344  }
37345 }
37346 #endif
37347 
37348 MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead, ma_bool32 loop)
37349 {
37350 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
37351  ma_result result = MA_SUCCESS;
37352  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37353  ma_data_source_base* pCurrentDataSource;
37354  void* pRunningFramesOut = pFramesOut;
37355  ma_uint64 totalFramesProcessed = 0;
37356  ma_format format;
37357  ma_uint32 channels;
37358  ma_uint32 emptyLoopCounter = 0; /* Keeps track of how many times 0 frames have been read. For infinite loop detection of sounds with no audio data. */
37359 
37360  if (pFramesRead != NULL) {
37361  *pFramesRead = 0;
37362  }
37363 
37364  if (pDataSourceBase == NULL) {
37365  return MA_INVALID_ARGS;
37366  }
37367 
37368  /*
37369  We need to know the data format so we can advance the output buffer as we read frames. If this
37370  fails, chaining will not work and we'll just read as much as we can from the current source.
37371  */
37372  if (ma_data_source_get_data_format(pDataSource, &format, &channels, NULL) != MA_SUCCESS) {
37373  result = ma_data_source_resolve_current(pDataSource, (ma_data_source**)&pCurrentDataSource);
37374  if (result != MA_SUCCESS) {
37375  return result;
37376  }
37377 
37378  return ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pFramesOut, frameCount, pFramesRead, loop);
37379  }
37380 
37381  /*
37382  Looping is a bit of a special case. When the `loop` argument is true, chaining will not work and
37383  only the current data source will be read from.
37384  */
37385 
37386  /* Keep reading until we've read as many frames as possible. */
37387  while (totalFramesProcessed < frameCount) {
37388  ma_uint64 framesProcessed;
37389  ma_uint64 framesRemaining = frameCount - totalFramesProcessed;
37390 
37391  /* We need to resolve the data source that we'll actually be reading from. */
37392  result = ma_data_source_resolve_current(pDataSource, (ma_data_source**)&pCurrentDataSource);
37393  if (result != MA_SUCCESS) {
37394  break;
37395  }
37396 
37397  if (pCurrentDataSource == NULL) {
37398  break;
37399  }
37400 
37401  result = ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pRunningFramesOut, framesRemaining, &framesProcessed, loop);
37402  totalFramesProcessed += framesProcessed;
37403 
37404  /*
37405  If we encounted an error from the read callback, make sure it's propagated to the caller. The caller may need to know whether or not MA_BUSY is returned which is
37406  not necessarily considered an error.
37407  */
37408  if (result != MA_SUCCESS && result != MA_AT_END) {
37409  break;
37410  }
37411 
37412  /*
37413  We can determine if we've reached the end by checking the return value of the onRead()
37414  callback. To loop back to the start, all we need to do is seek back to the first frame.
37415  */
37416  if (result == MA_AT_END) {
37417  /*
37418  We reached the end. If we're looping, we just loop back to the start of the current
37419  data source. If we're not looping we need to check if we have another in the chain, and
37420  if so, switch to it.
37421  */
37422  if (loop) {
37423  if (framesProcessed == 0) {
37424  emptyLoopCounter += 1;
37425  if (emptyLoopCounter > 1) {
37426  break; /* Infinite loop detected. Get out. */
37427  }
37428  } else {
37429  emptyLoopCounter = 0;
37430  }
37431 
37432  if (ma_data_source_seek_to_pcm_frame(pCurrentDataSource, pCurrentDataSource->loopBegInFrames) != MA_SUCCESS) {
37433  break; /* Failed to loop. Abort. */
37434  }
37435 
37436  /* Don't return MA_AT_END for looping sounds. */
37437  result = MA_SUCCESS;
37438  } else {
37439  if (pCurrentDataSource->pNext != NULL) {
37440  pDataSourceBase->pCurrent = pCurrentDataSource->pNext;
37441  } else if (pCurrentDataSource->onGetNext != NULL) {
37442  pDataSourceBase->pCurrent = pCurrentDataSource->onGetNext(pCurrentDataSource);
37443  if (pDataSourceBase->pCurrent == NULL) {
37444  break; /* Our callback did not return a next data source. We're done. */
37445  }
37446  } else {
37447  /* Reached the end of the chain. We're done. */
37448  break;
37449  }
37450 
37451  /* The next data source needs to be rewound to ensure data is read in looping scenarios. */
37452  ma_data_source_seek_to_pcm_frame(pDataSourceBase->pCurrent, 0);
37453 
37454  /*
37455  We need to make sure we clear the MA_AT_END result so we don't accidentally return
37456  it in the event that we coincidentally ended reading at the exact transition point
37457  of two data sources in a chain.
37458  */
37459  result = MA_SUCCESS;
37460  }
37461  }
37462 
37463  if (pRunningFramesOut != NULL) {
37464  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesProcessed * ma_get_bytes_per_frame(format, channels));
37465  }
37466  }
37467 
37468  if (pFramesRead != NULL) {
37469  *pFramesRead = totalFramesProcessed;
37470  }
37471 
37472  return result;
37473 #else
37474  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37475 
37476  /* Safety. */
37477  if (pFramesRead != NULL) {
37478  *pFramesRead = 0;
37479  }
37480 
37481  if (pCallbacks == NULL) {
37482  return MA_INVALID_ARGS;
37483  }
37484 
37485  if (pCallbacks->onRead == NULL) {
37486  return MA_NOT_IMPLEMENTED;
37487  }
37488 
37489  /* A very small optimization for the non looping case. */
37490  if (loop == MA_FALSE) {
37491  return pCallbacks->onRead(pDataSource, pFramesOut, frameCount, pFramesRead);
37492  } else {
37493  ma_format format;
37494  ma_uint32 channels;
37495  ma_uint32 sampleRate;
37496  if (ma_data_source_get_data_format(pDataSource, &format, &channels, &sampleRate) != MA_SUCCESS) {
37497  return pCallbacks->onRead(pDataSource, pFramesOut, frameCount, pFramesRead); /* We don't have a way to retrieve the data format which means we don't know how to offset the output buffer. Just read as much as we can. */
37498  } else {
37499  ma_result result = MA_SUCCESS;
37500  ma_uint64 totalFramesProcessed;
37501  void* pRunningFramesOut = pFramesOut;
37502 
37503  totalFramesProcessed = 0;
37504  while (totalFramesProcessed < frameCount) {
37505  ma_uint64 framesProcessed;
37506  ma_uint64 framesRemaining = frameCount - totalFramesProcessed;
37507 
37508  result = pCallbacks->onRead(pDataSource, pRunningFramesOut, framesRemaining, &framesProcessed);
37509  totalFramesProcessed += framesProcessed;
37510 
37511  /*
37512  If we encounted an error from the read callback, make sure it's propagated to the caller. The caller may need to know whether or not MA_BUSY is returned which is
37513  not necessarily considered an error.
37514  */
37515  if (result != MA_SUCCESS && result != MA_AT_END) {
37516  break;
37517  }
37518 
37519  /*
37520  We can determine if we've reached the end by checking the return value of the onRead() callback. If it's less than what we requested it means
37521  we've reached the end. To loop back to the start, all we need to do is seek back to the first frame.
37522  */
37523  if (framesProcessed < framesRemaining || result == MA_AT_END) {
37524  if (ma_data_source_seek_to_pcm_frame(pDataSource, 0) != MA_SUCCESS) {
37525  break;
37526  }
37527  }
37528 
37529  if (pRunningFramesOut != NULL) {
37530  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesProcessed * ma_get_bytes_per_frame(format, channels));
37531  }
37532  }
37533 
37534  if (pFramesRead != NULL) {
37535  *pFramesRead = totalFramesProcessed;
37536  }
37537 
37538  return result;
37539  }
37540  }
37541 #endif
37542 }
37543 
37545 {
37546  return ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, pFramesSeeked, loop);
37547 }
37548 
37550 {
37551 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
37552  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37553 
37554  if (pDataSourceBase == NULL) {
37555  return MA_SUCCESS;
37556  }
37557 
37558  if (pDataSourceBase->cb.onSeek == NULL) {
37559  return MA_NOT_IMPLEMENTED;
37560  }
37561 
37562  if (frameIndex > pDataSourceBase->rangeEndInFrames) {
37563  return MA_INVALID_OPERATION; /* Trying to seek to far forward. */
37564  }
37565 
37566  return pDataSourceBase->cb.onSeek(pDataSource, pDataSourceBase->rangeBegInFrames + frameIndex);
37567 #else
37568  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37569  if (pCallbacks == NULL) {
37570  return MA_INVALID_ARGS;
37571  }
37572 
37573  if (pCallbacks->onSeek == NULL) {
37574  return MA_NOT_IMPLEMENTED;
37575  }
37576 
37577  return pCallbacks->onSeek(pDataSource, frameIndex);
37578 #endif
37579 }
37580 
37581 MA_API ma_result ma_data_source_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount)
37582 {
37583  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37584  if (pCallbacks == NULL) {
37585  return MA_INVALID_ARGS;
37586  }
37587 
37588  if (pCallbacks->onMap == NULL) {
37589  return MA_NOT_IMPLEMENTED;
37590  }
37591 
37592  return pCallbacks->onMap(pDataSource, ppFramesOut, pFrameCount);
37593 }
37594 
37596 {
37597  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37598  if (pCallbacks == NULL) {
37599  return MA_INVALID_ARGS;
37600  }
37601 
37602  if (pCallbacks->onUnmap == NULL) {
37603  return MA_NOT_IMPLEMENTED;
37604  }
37605 
37606  return pCallbacks->onUnmap(pDataSource, frameCount);
37607 }
37608 
37610 {
37611  ma_result result;
37612  ma_format format;
37613  ma_uint32 channels;
37614  ma_uint32 sampleRate;
37615  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37616 
37617  if (pFormat != NULL) {
37618  *pFormat = ma_format_unknown;
37619  }
37620 
37621  if (pChannels != NULL) {
37622  *pChannels = 0;
37623  }
37624 
37625  if (pSampleRate != NULL) {
37626  *pSampleRate = 0;
37627  }
37628 
37629  if (pCallbacks == NULL) {
37630  return MA_INVALID_ARGS;
37631  }
37632 
37633  if (pCallbacks->onGetDataFormat == NULL) {
37634  return MA_NOT_IMPLEMENTED;
37635  }
37636 
37637  result = pCallbacks->onGetDataFormat(pDataSource, &format, &channels, &sampleRate);
37638  if (result != MA_SUCCESS) {
37639  return result;
37640  }
37641 
37642  if (pFormat != NULL) {
37643  *pFormat = format;
37644  }
37645  if (pChannels != NULL) {
37646  *pChannels = channels;
37647  }
37648  if (pSampleRate != NULL) {
37649  *pSampleRate = sampleRate;
37650  }
37651 
37652  return MA_SUCCESS;
37653 }
37654 
37656 {
37657 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
37658  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37659  ma_result result;
37660  ma_uint64 cursor;
37661 
37662  if (pCursor == NULL) {
37663  return MA_INVALID_ARGS;
37664  }
37665 
37666  *pCursor = 0;
37667 
37668  if (pDataSourceBase == NULL) {
37669  return MA_SUCCESS;
37670  }
37671 
37672  if (pDataSourceBase->cb.onGetCursor == NULL) {
37673  return MA_NOT_IMPLEMENTED;
37674  }
37675 
37676  result = pDataSourceBase->cb.onGetCursor(pDataSourceBase, &cursor);
37677  if (result != MA_SUCCESS) {
37678  return result;
37679  }
37680 
37681  /* The cursor needs to be made relative to the start of the range. */
37682  if (cursor < pDataSourceBase->rangeBegInFrames) { /* Safety check so we don't return some huge number. */
37683  *pCursor = 0;
37684  } else {
37685  *pCursor = cursor - pDataSourceBase->rangeBegInFrames;
37686  }
37687 
37688  return MA_SUCCESS;
37689 #else
37690  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37691 
37692  if (pCursor == NULL) {
37693  return MA_INVALID_ARGS;
37694  }
37695 
37696  *pCursor = 0;
37697 
37698  if (pCallbacks == NULL) {
37699  return MA_INVALID_ARGS;
37700  }
37701 
37702  if (pCallbacks->onGetCursor == NULL) {
37703  return MA_NOT_IMPLEMENTED;
37704  }
37705 
37706  return pCallbacks->onGetCursor(pDataSource, pCursor);
37707 #endif
37708 }
37709 
37711 {
37712 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
37713  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37714 
37715  if (pLength == NULL) {
37716  return MA_INVALID_ARGS;
37717  }
37718 
37719  *pLength = 0;
37720 
37721  if (pDataSourceBase == NULL) {
37722  return MA_INVALID_ARGS;
37723  }
37724 
37725  /*
37726  If we have a range defined we'll use that to determine the length. This is one of rare times
37727  where we'll actually trust the caller. If they've set the range, I think it's mostly safe to
37728  assume they've set it based on some higher level knowledge of the structure of the sound bank.
37729  */
37730  if (pDataSourceBase->rangeEndInFrames != ~((ma_uint64)0)) {
37731  *pLength = pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames;
37732  return MA_SUCCESS;
37733  }
37734 
37735  /*
37736  Getting here means a range is not defined so we'll need to get the data source itself to tell
37737  us the length.
37738  */
37739  if (pDataSourceBase->cb.onGetLength == NULL) {
37740  return MA_NOT_IMPLEMENTED;
37741  }
37742 
37743  return pDataSourceBase->cb.onGetLength(pDataSource, pLength);
37744 #else
37745  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
37746 
37747  if (pLength == NULL) {
37748  return MA_INVALID_ARGS;
37749  }
37750 
37751  *pLength = 0;
37752 
37753  if (pCallbacks == NULL) {
37754  return MA_INVALID_ARGS;
37755  }
37756 
37757  if (pCallbacks->onGetLength == NULL) {
37758  return MA_NOT_IMPLEMENTED;
37759  }
37760 
37761  return pCallbacks->onGetLength(pDataSource, pLength);
37762 #endif
37763 }
37764 
37765 
37766 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
37767 MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames)
37768 {
37769  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37770  ma_result result;
37771  ma_uint64 cursor;
37772  ma_uint64 loopBegAbsolute;
37773  ma_uint64 loopEndAbsolute;
37774 
37775  if (pDataSource == NULL) {
37776  return MA_INVALID_ARGS;
37777  }
37778 
37779  if (rangeEndInFrames < rangeBegInFrames) {
37780  return MA_INVALID_ARGS; /* The end of the range must come after the beginning. */
37781  }
37782 
37783  /*
37784  The loop points need to be updated. We'll be storing the loop points relative to the range. We'll update
37785  these so that they maintain their absolute positioning. The loop points will then be clamped to the range.
37786  */
37787  loopBegAbsolute = pDataSourceBase->loopBegInFrames + pDataSourceBase->rangeBegInFrames;
37788  loopEndAbsolute = pDataSourceBase->loopEndInFrames + ((pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) ? pDataSourceBase->rangeBegInFrames : 0);
37789 
37790  pDataSourceBase->rangeBegInFrames = rangeBegInFrames;
37791  pDataSourceBase->rangeEndInFrames = rangeEndInFrames;
37792 
37793  /* Make the loop points relative again, and make sure they're clamped to within the range. */
37794  if (loopBegAbsolute > pDataSourceBase->rangeBegInFrames) {
37795  pDataSourceBase->loopBegInFrames = loopBegAbsolute - pDataSourceBase->rangeBegInFrames;
37796  } else {
37797  pDataSourceBase->loopBegInFrames = 0;
37798  }
37799 
37800  if (pDataSourceBase->loopBegInFrames > pDataSourceBase->rangeEndInFrames) {
37801  pDataSourceBase->loopBegInFrames = pDataSourceBase->rangeEndInFrames;
37802  }
37803 
37804  /* Only need to update the loop end point if it's not -1. */
37805  if (loopEndAbsolute != ~((ma_uint64)0)) {
37806  if (loopEndAbsolute > pDataSourceBase->rangeBegInFrames) {
37807  pDataSourceBase->loopEndInFrames = loopEndAbsolute - pDataSourceBase->rangeBegInFrames;
37808  } else {
37809  pDataSourceBase->loopEndInFrames = 0;
37810  }
37811 
37812  if (pDataSourceBase->loopEndInFrames > pDataSourceBase->rangeEndInFrames && pDataSourceBase->loopEndInFrames) {
37813  pDataSourceBase->loopEndInFrames = pDataSourceBase->rangeEndInFrames;
37814  }
37815  }
37816 
37817 
37818  /* If the new range is past the current cursor position we need to seek to it. */
37819  result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursor);
37820  if (result == MA_SUCCESS) {
37821  /* Seek to within range. Note that our seek positions here are relative to the new range. */
37822  if (cursor < rangeBegInFrames) {
37823  ma_data_source_seek_to_pcm_frame(pDataSource, 0);
37824  } else if (cursor > rangeEndInFrames) {
37825  ma_data_source_seek_to_pcm_frame(pDataSource, rangeEndInFrames - rangeBegInFrames);
37826  }
37827  } else {
37828  /* We failed to get the cursor position. Probably means the data source has no notion of a cursor such a noise data source. Just pretend the seeking worked. */
37829  }
37830 
37831  return MA_SUCCESS;
37832 }
37833 
37834 MA_API void ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames)
37835 {
37836  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37837 
37838  if (pDataSource == NULL) {
37839  return;
37840  }
37841 
37842  if (pRangeBegInFrames != NULL) {
37843  *pRangeBegInFrames = pDataSourceBase->rangeBegInFrames;
37844  }
37845 
37846  if (pRangeEndInFrames != NULL) {
37847  *pRangeEndInFrames = pDataSourceBase->rangeEndInFrames;
37848  }
37849 }
37850 
37851 MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames)
37852 {
37853  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37854 
37855  if (pDataSource == NULL) {
37856  return MA_INVALID_ARGS;
37857  }
37858 
37859  if (loopEndInFrames < loopBegInFrames) {
37860  return MA_INVALID_ARGS; /* The end of the loop point must come after the beginning. */
37861  }
37862 
37863  if (loopEndInFrames > pDataSourceBase->rangeEndInFrames && loopEndInFrames != ~((ma_uint64)0)) {
37864  return MA_INVALID_ARGS; /* The end of the loop point must not go beyond the range. */
37865  }
37866 
37867  pDataSourceBase->loopBegInFrames = loopBegInFrames;
37868  pDataSourceBase->loopEndInFrames = loopEndInFrames;
37869 
37870  /* The end cannot exceed the range. */
37871  if (pDataSourceBase->loopEndInFrames > (pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames) && pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) {
37872  pDataSourceBase->loopEndInFrames = (pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames);
37873  }
37874 
37875  return MA_SUCCESS;
37876 }
37877 
37878 MA_API void ma_data_source_get_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLoopBegInFrames, ma_uint64* pLoopEndInFrames)
37879 {
37880  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37881 
37882  if (pDataSource == NULL) {
37883  return;
37884  }
37885 
37886  if (pLoopBegInFrames != NULL) {
37887  *pLoopBegInFrames = pDataSourceBase->loopBegInFrames;
37888  }
37889 
37890  if (pLoopEndInFrames != NULL) {
37891  *pLoopEndInFrames = pDataSourceBase->loopEndInFrames;
37892  }
37893 }
37894 
37895 MA_API ma_result ma_data_source_set_current(ma_data_source* pDataSource, ma_data_source* pCurrentDataSource)
37896 {
37897  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37898 
37899  if (pDataSource == NULL) {
37900  return MA_INVALID_ARGS;
37901  }
37902 
37903  pDataSourceBase->pCurrent = pCurrentDataSource;
37904 
37905  return MA_SUCCESS;
37906 }
37907 
37908 MA_API ma_data_source* ma_data_source_get_current(ma_data_source* pDataSource)
37909 {
37910  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37911 
37912  if (pDataSource == NULL) {
37913  return NULL;
37914  }
37915 
37916  return pDataSourceBase->pCurrent;
37917 }
37918 
37919 MA_API ma_result ma_data_source_set_next(ma_data_source* pDataSource, ma_data_source* pNextDataSource)
37920 {
37921  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37922 
37923  if (pDataSource == NULL) {
37924  return MA_INVALID_ARGS;
37925  }
37926 
37927  pDataSourceBase->pNext = pNextDataSource;
37928 
37929  return MA_SUCCESS;
37930 }
37931 
37932 MA_API ma_data_source* ma_data_source_get_next(ma_data_source* pDataSource)
37933 {
37934  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37935 
37936  if (pDataSource == NULL) {
37937  return NULL;
37938  }
37939 
37940  return pDataSourceBase->pNext;
37941 }
37942 
37943 MA_API ma_result ma_data_source_set_next_callback(ma_data_source* pDataSource, ma_data_source_get_next_proc onGetNext)
37944 {
37945  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37946 
37947  if (pDataSource == NULL) {
37948  return MA_INVALID_ARGS;
37949  }
37950 
37951  pDataSourceBase->onGetNext = onGetNext;
37952 
37953  return MA_SUCCESS;
37954 }
37955 
37956 MA_API ma_data_source_get_next_proc ma_data_source_get_next_callback(ma_data_source* pDataSource)
37957 {
37958  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
37959 
37960  if (pDataSource == NULL) {
37961  return NULL;
37962  }
37963 
37964  return pDataSourceBase->onGetNext;
37965 }
37966 #endif
37967 
37968 
37969 static ma_result ma_audio_buffer_ref__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
37970 {
37971  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
37972  ma_uint64 framesRead = ma_audio_buffer_ref_read_pcm_frames(pAudioBufferRef, pFramesOut, frameCount, MA_FALSE);
37973 
37974  if (pFramesRead != NULL) {
37975  *pFramesRead = framesRead;
37976  }
37977 
37978  if (framesRead < frameCount || framesRead == 0) {
37979  return MA_AT_END;
37980  }
37981 
37982  return MA_SUCCESS;
37983 }
37984 
37986 {
37987  return ma_audio_buffer_ref_seek_to_pcm_frame((ma_audio_buffer_ref*)pDataSource, frameIndex);
37988 }
37989 
37990 static ma_result ma_audio_buffer_ref__data_source_on_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount)
37991 {
37992  return ma_audio_buffer_ref_map((ma_audio_buffer_ref*)pDataSource, ppFramesOut, pFrameCount);
37993 }
37994 
37996 {
37997  return ma_audio_buffer_ref_unmap((ma_audio_buffer_ref*)pDataSource, frameCount);
37998 }
37999 
38001 {
38002  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
38003 
38004  *pFormat = pAudioBufferRef->format;
38005  *pChannels = pAudioBufferRef->channels;
38006  *pSampleRate = 0; /* There is no notion of a sample rate with audio buffers. */
38007 
38008  return MA_SUCCESS;
38009 }
38010 
38012 {
38013  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
38014 
38015  *pCursor = pAudioBufferRef->cursor;
38016 
38017  return MA_SUCCESS;
38018 }
38019 
38021 {
38022  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
38023 
38024  *pLength = pAudioBufferRef->sizeInFrames;
38025 
38026  return MA_SUCCESS;
38027 }
38028 
38030 {
38038 };
38039 
38040 MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef)
38041 {
38042  ma_result result;
38043  ma_data_source_config dataSourceConfig;
38044 
38045  if (pAudioBufferRef == NULL) {
38046  return MA_INVALID_ARGS;
38047  }
38048 
38049  MA_ZERO_OBJECT(pAudioBufferRef);
38050 
38051  dataSourceConfig = ma_data_source_config_init();
38053 
38054  result = ma_data_source_init(&dataSourceConfig, &pAudioBufferRef->ds);
38055  if (result != MA_SUCCESS) {
38056  return result;
38057  }
38058 
38059  pAudioBufferRef->format = format;
38060  pAudioBufferRef->channels = channels;
38061  pAudioBufferRef->cursor = 0;
38062  pAudioBufferRef->sizeInFrames = sizeInFrames;
38063  pAudioBufferRef->pData = pData;
38064 
38065  return MA_SUCCESS;
38066 }
38067 
38069 {
38070  if (pAudioBufferRef == NULL) {
38071  return;
38072  }
38073 
38074  ma_data_source_uninit(&pAudioBufferRef->ds);
38075 }
38076 
38077 MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames)
38078 {
38079  if (pAudioBufferRef == NULL) {
38080  return MA_INVALID_ARGS;
38081  }
38082 
38083  pAudioBufferRef->cursor = 0;
38084  pAudioBufferRef->sizeInFrames = sizeInFrames;
38085  pAudioBufferRef->pData = pData;
38086 
38087  return MA_SUCCESS;
38088 }
38089 
38091 {
38092  ma_uint64 totalFramesRead = 0;
38093 
38094  if (pAudioBufferRef == NULL) {
38095  return 0;
38096  }
38097 
38098  if (frameCount == 0) {
38099  return 0;
38100  }
38101 
38102  while (totalFramesRead < frameCount) {
38103  ma_uint64 framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
38104  ma_uint64 framesRemaining = frameCount - totalFramesRead;
38105  ma_uint64 framesToRead;
38106 
38107  framesToRead = framesRemaining;
38108  if (framesToRead > framesAvailable) {
38109  framesToRead = framesAvailable;
38110  }
38111 
38112  if (pFramesOut != NULL) {
38113  ma_copy_pcm_frames(pFramesOut, ma_offset_ptr(pAudioBufferRef->pData, pAudioBufferRef->cursor * ma_get_bytes_per_frame(pAudioBufferRef->format, pAudioBufferRef->channels)), framesToRead, pAudioBufferRef->format, pAudioBufferRef->channels);
38114  }
38115 
38116  totalFramesRead += framesToRead;
38117 
38118  pAudioBufferRef->cursor += framesToRead;
38119  if (pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames) {
38120  if (loop) {
38121  pAudioBufferRef->cursor = 0;
38122  } else {
38123  break; /* We've reached the end and we're not looping. Done. */
38124  }
38125  }
38126 
38127  MA_ASSERT(pAudioBufferRef->cursor < pAudioBufferRef->sizeInFrames);
38128  }
38129 
38130  return totalFramesRead;
38131 }
38132 
38134 {
38135  if (pAudioBufferRef == NULL) {
38136  return MA_INVALID_ARGS;
38137  }
38138 
38139  if (frameIndex > pAudioBufferRef->sizeInFrames) {
38140  return MA_INVALID_ARGS;
38141  }
38142 
38143  pAudioBufferRef->cursor = (size_t)frameIndex;
38144 
38145  return MA_SUCCESS;
38146 }
38147 
38148 MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount)
38149 {
38150  ma_uint64 framesAvailable;
38151  ma_uint64 frameCount = 0;
38152 
38153  if (ppFramesOut != NULL) {
38154  *ppFramesOut = NULL; /* Safety. */
38155  }
38156 
38157  if (pFrameCount != NULL) {
38158  frameCount = *pFrameCount;
38159  *pFrameCount = 0; /* Safety. */
38160  }
38161 
38162  if (pAudioBufferRef == NULL || ppFramesOut == NULL || pFrameCount == NULL) {
38163  return MA_INVALID_ARGS;
38164  }
38165 
38166  framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
38167  if (frameCount > framesAvailable) {
38168  frameCount = framesAvailable;
38169  }
38170 
38171  *ppFramesOut = ma_offset_ptr(pAudioBufferRef->pData, pAudioBufferRef->cursor * ma_get_bytes_per_frame(pAudioBufferRef->format, pAudioBufferRef->channels));
38172  *pFrameCount = frameCount;
38173 
38174  return MA_SUCCESS;
38175 }
38176 
38178 {
38179  ma_uint64 framesAvailable;
38180 
38181  if (pAudioBufferRef == NULL) {
38182  return MA_INVALID_ARGS;
38183  }
38184 
38185  framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
38186  if (frameCount > framesAvailable) {
38187  return MA_INVALID_ARGS; /* The frame count was too big. This should never happen in an unmapping. Need to make sure the caller is aware of this. */
38188  }
38189 
38190  pAudioBufferRef->cursor += frameCount;
38191 
38192  if (pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames) {
38193  return MA_AT_END; /* Successful. Need to tell the caller that the end has been reached so that it can loop if desired. */
38194  } else {
38195  return MA_SUCCESS;
38196  }
38197 }
38198 
38200 {
38201  if (pAudioBufferRef == NULL) {
38202  return MA_FALSE;
38203  }
38204 
38205  return pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames;
38206 }
38207 
38209 {
38210  if (pCursor == NULL) {
38211  return MA_INVALID_ARGS;
38212  }
38213 
38214  *pCursor = 0;
38215 
38216  if (pAudioBufferRef == NULL) {
38217  return MA_INVALID_ARGS;
38218  }
38219 
38220  *pCursor = pAudioBufferRef->cursor;
38221 
38222  return MA_SUCCESS;
38223 }
38224 
38226 {
38227  if (pLength == NULL) {
38228  return MA_INVALID_ARGS;
38229  }
38230 
38231  *pLength = 0;
38232 
38233  if (pAudioBufferRef == NULL) {
38234  return MA_INVALID_ARGS;
38235  }
38236 
38237  *pLength = pAudioBufferRef->sizeInFrames;
38238 
38239  return MA_SUCCESS;
38240 }
38241 
38243 {
38244  if (pAvailableFrames == NULL) {
38245  return MA_INVALID_ARGS;
38246  }
38247 
38248  *pAvailableFrames = 0;
38249 
38250  if (pAudioBufferRef == NULL) {
38251  return MA_INVALID_ARGS;
38252  }
38253 
38254  if (pAudioBufferRef->sizeInFrames <= pAudioBufferRef->cursor) {
38255  *pAvailableFrames = 0;
38256  } else {
38257  *pAvailableFrames = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
38258  }
38259 
38260  return MA_SUCCESS;
38261 }
38262 
38263 
38264 
38265 
38266 MA_API ma_audio_buffer_config ma_audio_buffer_config_init(ma_format format, ma_uint32 channels, ma_uint64 sizeInFrames, const void* pData, const ma_allocation_callbacks* pAllocationCallbacks)
38267 {
38269 
38271  config.format = format;
38272  config.channels = channels;
38273  config.sizeInFrames = sizeInFrames;
38274  config.pData = pData;
38275  ma_allocation_callbacks_init_copy(&config.allocationCallbacks, pAllocationCallbacks);
38276 
38277  return config;
38278 }
38279 
38281 {
38282  ma_result result;
38283 
38284  if (pAudioBuffer == NULL) {
38285  return MA_INVALID_ARGS;
38286  }
38287 
38288  MA_ZERO_MEMORY(pAudioBuffer, sizeof(*pAudioBuffer) - sizeof(pAudioBuffer->_pExtraData)); /* Safety. Don't overwrite the extra data. */
38289 
38290  if (pConfig == NULL) {
38291  return MA_INVALID_ARGS;
38292  }
38293 
38294  if (pConfig->sizeInFrames == 0) {
38295  return MA_INVALID_ARGS; /* Not allowing buffer sizes of 0 frames. */
38296  }
38297 
38298  result = ma_audio_buffer_ref_init(pConfig->format, pConfig->channels, NULL, 0, &pAudioBuffer->ref);
38299  if (result != MA_SUCCESS) {
38300  return result;
38301  }
38302 
38304 
38305  if (doCopy) {
38306  ma_uint64 allocationSizeInBytes;
38307  void* pData;
38308 
38309  allocationSizeInBytes = pConfig->sizeInFrames * ma_get_bytes_per_frame(pConfig->format, pConfig->channels);
38310  if (allocationSizeInBytes > MA_SIZE_MAX) {
38311  return MA_OUT_OF_MEMORY; /* Too big. */
38312  }
38313 
38314  pData = ma__malloc_from_callbacks((size_t)allocationSizeInBytes, &pAudioBuffer->allocationCallbacks); /* Safe cast to size_t. */
38315  if (pData == NULL) {
38316  return MA_OUT_OF_MEMORY;
38317  }
38318 
38319  if (pConfig->pData != NULL) {
38320  ma_copy_pcm_frames(pData, pConfig->pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
38321  } else {
38322  ma_silence_pcm_frames(pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
38323  }
38324 
38325  ma_audio_buffer_ref_set_data(&pAudioBuffer->ref, pData, pConfig->sizeInFrames);
38326  pAudioBuffer->ownsData = MA_TRUE;
38327  } else {
38328  ma_audio_buffer_ref_set_data(&pAudioBuffer->ref, pConfig->pData, pConfig->sizeInFrames);
38329  pAudioBuffer->ownsData = MA_FALSE;
38330  }
38331 
38332  return MA_SUCCESS;
38333 }
38334 
38335 static void ma_audio_buffer_uninit_ex(ma_audio_buffer* pAudioBuffer, ma_bool32 doFree)
38336 {
38337  if (pAudioBuffer == NULL) {
38338  return;
38339  }
38340 
38341  if (pAudioBuffer->ownsData && pAudioBuffer->ref.pData != &pAudioBuffer->_pExtraData[0]) {
38342  ma__free_from_callbacks((void*)pAudioBuffer->ref.pData, &pAudioBuffer->allocationCallbacks); /* Naugty const cast, but OK in this case since we've guarded it with the ownsData check. */
38343  }
38344 
38345  if (doFree) {
38346  ma__free_from_callbacks(pAudioBuffer, &pAudioBuffer->allocationCallbacks);
38347  }
38348 
38349  ma_audio_buffer_ref_uninit(&pAudioBuffer->ref);
38350 }
38351 
38353 {
38354  return ma_audio_buffer_init_ex(pConfig, MA_FALSE, pAudioBuffer);
38355 }
38356 
38358 {
38359  return ma_audio_buffer_init_ex(pConfig, MA_TRUE, pAudioBuffer);
38360 }
38361 
38363 {
38364  ma_result result;
38365  ma_audio_buffer* pAudioBuffer;
38366  ma_audio_buffer_config innerConfig; /* We'll be making some changes to the config, so need to make a copy. */
38367  ma_uint64 allocationSizeInBytes;
38368 
38369  if (ppAudioBuffer == NULL) {
38370  return MA_INVALID_ARGS;
38371  }
38372 
38373  *ppAudioBuffer = NULL; /* Safety. */
38374 
38375  if (pConfig == NULL) {
38376  return MA_INVALID_ARGS;
38377  }
38378 
38379  innerConfig = *pConfig;
38381 
38382  allocationSizeInBytes = sizeof(*pAudioBuffer) - sizeof(pAudioBuffer->_pExtraData) + (pConfig->sizeInFrames * ma_get_bytes_per_frame(pConfig->format, pConfig->channels));
38383  if (allocationSizeInBytes > MA_SIZE_MAX) {
38384  return MA_OUT_OF_MEMORY; /* Too big. */
38385  }
38386 
38387  pAudioBuffer = (ma_audio_buffer*)ma__malloc_from_callbacks((size_t)allocationSizeInBytes, &innerConfig.allocationCallbacks); /* Safe cast to size_t. */
38388  if (pAudioBuffer == NULL) {
38389  return MA_OUT_OF_MEMORY;
38390  }
38391 
38392  if (pConfig->pData != NULL) {
38393  ma_copy_pcm_frames(&pAudioBuffer->_pExtraData[0], pConfig->pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
38394  } else {
38395  ma_silence_pcm_frames(&pAudioBuffer->_pExtraData[0], pConfig->sizeInFrames, pConfig->format, pConfig->channels);
38396  }
38397 
38398  innerConfig.pData = &pAudioBuffer->_pExtraData[0];
38399 
38400  result = ma_audio_buffer_init_ex(&innerConfig, MA_FALSE, pAudioBuffer);
38401  if (result != MA_SUCCESS) {
38402  ma__free_from_callbacks(pAudioBuffer, &innerConfig.allocationCallbacks);
38403  return result;
38404  }
38405 
38406  *ppAudioBuffer = pAudioBuffer;
38407 
38408  return MA_SUCCESS;
38409 }
38410 
38412 {
38413  ma_audio_buffer_uninit_ex(pAudioBuffer, MA_FALSE);
38414 }
38415 
38417 {
38418  ma_audio_buffer_uninit_ex(pAudioBuffer, MA_TRUE);
38419 }
38420 
38421 MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop)
38422 {
38423  if (pAudioBuffer == NULL) {
38424  return 0;
38425  }
38426 
38427  return ma_audio_buffer_ref_read_pcm_frames(&pAudioBuffer->ref, pFramesOut, frameCount, loop);
38428 }
38429 
38431 {
38432  if (pAudioBuffer == NULL) {
38433  return MA_INVALID_ARGS;
38434  }
38435 
38436  return ma_audio_buffer_ref_seek_to_pcm_frame(&pAudioBuffer->ref, frameIndex);
38437 }
38438 
38439 MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount)
38440 {
38441  if (ppFramesOut != NULL) {
38442  *ppFramesOut = NULL; /* Safety. */
38443  }
38444 
38445  if (pAudioBuffer == NULL) {
38446  if (pFrameCount != NULL) {
38447  *pFrameCount = 0;
38448  }
38449 
38450  return MA_INVALID_ARGS;
38451  }
38452 
38453  return ma_audio_buffer_ref_map(&pAudioBuffer->ref, ppFramesOut, pFrameCount);
38454 }
38455 
38457 {
38458  if (pAudioBuffer == NULL) {
38459  return MA_INVALID_ARGS;
38460  }
38461 
38462  return ma_audio_buffer_ref_unmap(&pAudioBuffer->ref, frameCount);
38463 }
38464 
38466 {
38467  if (pAudioBuffer == NULL) {
38468  return MA_FALSE;
38469  }
38470 
38471  return ma_audio_buffer_ref_at_end(&pAudioBuffer->ref);
38472 }
38473 
38475 {
38476  if (pAudioBuffer == NULL) {
38477  return MA_INVALID_ARGS;
38478  }
38479 
38480  return ma_audio_buffer_ref_get_cursor_in_pcm_frames(&pAudioBuffer->ref, pCursor);
38481 }
38482 
38484 {
38485  if (pAudioBuffer == NULL) {
38486  return MA_INVALID_ARGS;
38487  }
38488 
38489  return ma_audio_buffer_ref_get_length_in_pcm_frames(&pAudioBuffer->ref, pLength);
38490 }
38491 
38493 {
38494  if (pAvailableFrames == NULL) {
38495  return MA_INVALID_ARGS;
38496  }
38497 
38498  *pAvailableFrames = 0;
38499 
38500  if (pAudioBuffer == NULL) {
38501  return MA_INVALID_ARGS;
38502  }
38503 
38504  return ma_audio_buffer_ref_get_available_frames(&pAudioBuffer->ref, pAvailableFrames);
38505 }
38506 
38507 
38508 
38509 /**************************************************************************************************************************************************************
38510 
38511 VFS
38512 
38513 **************************************************************************************************************************************************************/
38514 MA_API ma_result ma_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
38515 {
38516  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38517 
38518  if (pFile == NULL) {
38519  return MA_INVALID_ARGS;
38520  }
38521 
38522  *pFile = NULL;
38523 
38524  if (pVFS == NULL || pFilePath == NULL || openMode == 0) {
38525  return MA_INVALID_ARGS;
38526  }
38527 
38528  if (pCallbacks->onOpen == NULL) {
38529  return MA_NOT_IMPLEMENTED;
38530  }
38531 
38532  return pCallbacks->onOpen(pVFS, pFilePath, openMode, pFile);
38533 }
38534 
38535 MA_API ma_result ma_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
38536 {
38537  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38538 
38539  if (pFile == NULL) {
38540  return MA_INVALID_ARGS;
38541  }
38542 
38543  *pFile = NULL;
38544 
38545  if (pVFS == NULL || pFilePath == NULL || openMode == 0) {
38546  return MA_INVALID_ARGS;
38547  }
38548 
38549  if (pCallbacks->onOpenW == NULL) {
38550  return MA_NOT_IMPLEMENTED;
38551  }
38552 
38553  return pCallbacks->onOpenW(pVFS, pFilePath, openMode, pFile);
38554 }
38555 
38557 {
38558  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38559 
38560  if (pVFS == NULL || file == NULL) {
38561  return MA_INVALID_ARGS;
38562  }
38563 
38564  if (pCallbacks->onClose == NULL) {
38565  return MA_NOT_IMPLEMENTED;
38566  }
38567 
38568  return pCallbacks->onClose(pVFS, file);
38569 }
38570 
38571 MA_API ma_result ma_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
38572 {
38573  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38574 
38575  if (pBytesRead != NULL) {
38576  *pBytesRead = 0;
38577  }
38578 
38579  if (pVFS == NULL || file == NULL || pDst == NULL) {
38580  return MA_INVALID_ARGS;
38581  }
38582 
38583  if (pCallbacks->onRead == NULL) {
38584  return MA_NOT_IMPLEMENTED;
38585  }
38586 
38587  return pCallbacks->onRead(pVFS, file, pDst, sizeInBytes, pBytesRead);
38588 }
38589 
38590 MA_API ma_result ma_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
38591 {
38592  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38593 
38594  if (pBytesWritten != NULL) {
38595  *pBytesWritten = 0;
38596  }
38597 
38598  if (pVFS == NULL || file == NULL || pSrc == NULL) {
38599  return MA_INVALID_ARGS;
38600  }
38601 
38602  if (pCallbacks->onWrite == NULL) {
38603  return MA_NOT_IMPLEMENTED;
38604  }
38605 
38606  return pCallbacks->onWrite(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
38607 }
38608 
38610 {
38611  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38612 
38613  if (pVFS == NULL || file == NULL) {
38614  return MA_INVALID_ARGS;
38615  }
38616 
38617  if (pCallbacks->onSeek == NULL) {
38618  return MA_NOT_IMPLEMENTED;
38619  }
38620 
38621  return pCallbacks->onSeek(pVFS, file, offset, origin);
38622 }
38623 
38625 {
38626  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38627 
38628  if (pCursor == NULL) {
38629  return MA_INVALID_ARGS;
38630  }
38631 
38632  *pCursor = 0;
38633 
38634  if (pVFS == NULL || file == NULL) {
38635  return MA_INVALID_ARGS;
38636  }
38637 
38638  if (pCallbacks->onTell == NULL) {
38639  return MA_NOT_IMPLEMENTED;
38640  }
38641 
38642  return pCallbacks->onTell(pVFS, file, pCursor);
38643 }
38644 
38646 {
38647  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
38648 
38649  if (pInfo == NULL) {
38650  return MA_INVALID_ARGS;
38651  }
38652 
38653  MA_ZERO_OBJECT(pInfo);
38654 
38655  if (pVFS == NULL || file == NULL) {
38656  return MA_INVALID_ARGS;
38657  }
38658 
38659  if (pCallbacks->onInfo == NULL) {
38660  return MA_NOT_IMPLEMENTED;
38661  }
38662 
38663  return pCallbacks->onInfo(pVFS, file, pInfo);
38664 }
38665 
38666 
38667 static ma_result ma_vfs_open_and_read_file_ex(ma_vfs* pVFS, const char* pFilePath, const wchar_t* pFilePathW, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks, ma_uint32 allocationType)
38668 {
38669  ma_result result;
38670  ma_vfs_file file;
38671  ma_file_info info;
38672  void* pData;
38673  size_t bytesRead;
38674 
38675  (void)allocationType;
38676 
38677  if (ppData != NULL) {
38678  *ppData = NULL;
38679  }
38680  if (pSize != NULL) {
38681  *pSize = 0;
38682  }
38683 
38684  if (ppData == NULL) {
38685  return MA_INVALID_ARGS;
38686  }
38687 
38688  if (pFilePath != NULL) {
38689  result = ma_vfs_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
38690  } else {
38691  result = ma_vfs_open_w(pVFS, pFilePathW, MA_OPEN_MODE_READ, &file);
38692  }
38693  if (result != MA_SUCCESS) {
38694  return result;
38695  }
38696 
38697  result = ma_vfs_info(pVFS, file, &info);
38698  if (result != MA_SUCCESS) {
38699  ma_vfs_close(pVFS, file);
38700  return result;
38701  }
38702 
38703  if (info.sizeInBytes > MA_SIZE_MAX) {
38704  ma_vfs_close(pVFS, file);
38705  return MA_TOO_BIG;
38706  }
38707 
38708  pData = ma__malloc_from_callbacks((size_t)info.sizeInBytes, pAllocationCallbacks); /* Safe cast. */
38709  if (pData == NULL) {
38710  ma_vfs_close(pVFS, file);
38711  return result;
38712  }
38713 
38714  result = ma_vfs_read(pVFS, file, pData, (size_t)info.sizeInBytes, &bytesRead); /* Safe cast. */
38715  ma_vfs_close(pVFS, file);
38716 
38717  if (result != MA_SUCCESS) {
38718  ma__free_from_callbacks(pData, pAllocationCallbacks);
38719  return result;
38720  }
38721 
38722  if (pSize != NULL) {
38723  *pSize = bytesRead;
38724  }
38725 
38726  MA_ASSERT(ppData != NULL);
38727  *ppData = pData;
38728 
38729  return MA_SUCCESS;
38730 }
38731 
38732 MA_API ma_result ma_vfs_open_and_read_file(ma_vfs* pVFS, const char* pFilePath, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks)
38733 {
38734  return ma_vfs_open_and_read_file_ex(pVFS, pFilePath, NULL, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/);
38735 }
38736 
38737 MA_API ma_result ma_vfs_open_and_read_file_w(ma_vfs* pVFS, const wchar_t* pFilePath, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks)
38738 {
38739  return ma_vfs_open_and_read_file_ex(pVFS, NULL, pFilePath, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/);
38740 }
38741 
38742 
38743 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
38744 static void ma_default_vfs__get_open_settings_win32(ma_uint32 openMode, DWORD* pDesiredAccess, DWORD* pShareMode, DWORD* pCreationDisposition)
38745 {
38746  *pDesiredAccess = 0;
38747  if ((openMode & MA_OPEN_MODE_READ) != 0) {
38748  *pDesiredAccess |= GENERIC_READ;
38749  }
38750  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
38751  *pDesiredAccess |= GENERIC_WRITE;
38752  }
38753 
38754  *pShareMode = 0;
38755  if ((openMode & MA_OPEN_MODE_READ) != 0) {
38756  *pShareMode |= FILE_SHARE_READ;
38757  }
38758 
38759  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
38760  *pCreationDisposition = CREATE_ALWAYS; /* Opening in write mode. Truncate. */
38761  } else {
38762  *pCreationDisposition = OPEN_EXISTING; /* Opening in read mode. File must exist. */
38763  }
38764 }
38765 
38766 static ma_result ma_default_vfs_open__win32(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
38767 {
38768  HANDLE hFile;
38769  DWORD dwDesiredAccess;
38770  DWORD dwShareMode;
38771  DWORD dwCreationDisposition;
38772 
38773  (void)pVFS;
38774 
38775  ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
38776 
38777  hFile = CreateFileA(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
38778  if (hFile == INVALID_HANDLE_VALUE) {
38779  return ma_result_from_GetLastError(GetLastError());
38780  }
38781 
38782  *pFile = hFile;
38783  return MA_SUCCESS;
38784 }
38785 
38786 static ma_result ma_default_vfs_open_w__win32(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
38787 {
38788  HANDLE hFile;
38789  DWORD dwDesiredAccess;
38790  DWORD dwShareMode;
38791  DWORD dwCreationDisposition;
38792 
38793  (void)pVFS;
38794 
38795  ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
38796 
38797  hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
38798  if (hFile == INVALID_HANDLE_VALUE) {
38799  return ma_result_from_GetLastError(GetLastError());
38800  }
38801 
38802  *pFile = hFile;
38803  return MA_SUCCESS;
38804 }
38805 
38806 static ma_result ma_default_vfs_close__win32(ma_vfs* pVFS, ma_vfs_file file)
38807 {
38808  (void)pVFS;
38809 
38810  if (CloseHandle((HANDLE)file) == 0) {
38811  return ma_result_from_GetLastError(GetLastError());
38812  }
38813 
38814  return MA_SUCCESS;
38815 }
38816 
38817 
38818 static ma_result ma_default_vfs_read__win32(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
38819 {
38820  ma_result result = MA_SUCCESS;
38821  size_t totalBytesRead;
38822 
38823  (void)pVFS;
38824 
38825  totalBytesRead = 0;
38826  while (totalBytesRead < sizeInBytes) {
38827  size_t bytesRemaining;
38828  DWORD bytesToRead;
38829  DWORD bytesRead;
38830  BOOL readResult;
38831 
38832  bytesRemaining = sizeInBytes - totalBytesRead;
38833  if (bytesRemaining >= 0xFFFFFFFF) {
38834  bytesToRead = 0xFFFFFFFF;
38835  } else {
38836  bytesToRead = (DWORD)bytesRemaining;
38837  }
38838 
38839  readResult = ReadFile((HANDLE)file, ma_offset_ptr(pDst, totalBytesRead), bytesToRead, &bytesRead, NULL);
38840  if (readResult == 1 && bytesRead == 0) {
38841  result = MA_AT_END;
38842  break; /* EOF */
38843  }
38844 
38845  totalBytesRead += bytesRead;
38846 
38847  if (bytesRead < bytesToRead) {
38848  break; /* EOF */
38849  }
38850 
38851  if (readResult == 0) {
38852  result = ma_result_from_GetLastError(GetLastError());
38853  break;
38854  }
38855  }
38856 
38857  if (pBytesRead != NULL) {
38858  *pBytesRead = totalBytesRead;
38859  }
38860 
38861  return result;
38862 }
38863 
38864 static ma_result ma_default_vfs_write__win32(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
38865 {
38866  ma_result result = MA_SUCCESS;
38867  size_t totalBytesWritten;
38868 
38869  (void)pVFS;
38870 
38871  totalBytesWritten = 0;
38872  while (totalBytesWritten < sizeInBytes) {
38873  size_t bytesRemaining;
38874  DWORD bytesToWrite;
38875  DWORD bytesWritten;
38876  BOOL writeResult;
38877 
38878  bytesRemaining = sizeInBytes - totalBytesWritten;
38879  if (bytesRemaining >= 0xFFFFFFFF) {
38880  bytesToWrite = 0xFFFFFFFF;
38881  } else {
38882  bytesToWrite = (DWORD)bytesRemaining;
38883  }
38884 
38885  writeResult = WriteFile((HANDLE)file, ma_offset_ptr(pSrc, totalBytesWritten), bytesToWrite, &bytesWritten, NULL);
38886  totalBytesWritten += bytesWritten;
38887 
38888  if (writeResult == 0) {
38889  result = ma_result_from_GetLastError(GetLastError());
38890  break;
38891  }
38892  }
38893 
38894  if (pBytesWritten != NULL) {
38895  *pBytesWritten = totalBytesWritten;
38896  }
38897 
38898  return result;
38899 }
38900 
38901 
38902 static ma_result ma_default_vfs_seek__win32(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
38903 {
38904  LARGE_INTEGER liDistanceToMove;
38905  DWORD dwMoveMethod;
38906  BOOL result;
38907 
38908  (void)pVFS;
38909 
38910  liDistanceToMove.QuadPart = offset;
38911 
38912  /* */ if (origin == ma_seek_origin_current) {
38913  dwMoveMethod = FILE_CURRENT;
38914  } else if (origin == ma_seek_origin_end) {
38915  dwMoveMethod = FILE_END;
38916  } else {
38917  dwMoveMethod = FILE_BEGIN;
38918  }
38919 
38920 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__DMC__)
38921  /* No SetFilePointerEx() so restrict to 31 bits. */
38922  if (origin > 0x7FFFFFFF) {
38923  return MA_OUT_OF_RANGE;
38924  }
38925 
38926  result = SetFilePointer((HANDLE)file, (LONG)liDistanceToMove.QuadPart, NULL, dwMoveMethod);
38927 #else
38928  result = SetFilePointerEx((HANDLE)file, liDistanceToMove, NULL, dwMoveMethod);
38929 #endif
38930  if (result == 0) {
38931  return ma_result_from_GetLastError(GetLastError());
38932  }
38933 
38934  return MA_SUCCESS;
38935 }
38936 
38937 static ma_result ma_default_vfs_tell__win32(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
38938 {
38939  LARGE_INTEGER liZero;
38940  LARGE_INTEGER liTell;
38941  BOOL result;
38942 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__DMC__)
38943  LONG tell;
38944 #endif
38945 
38946  (void)pVFS;
38947 
38948  liZero.QuadPart = 0;
38949 
38950 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__DMC__)
38951  result = SetFilePointer((HANDLE)file, (LONG)liZero.QuadPart, &tell, FILE_CURRENT);
38952  liTell.QuadPart = tell;
38953 #else
38954  result = SetFilePointerEx((HANDLE)file, liZero, &liTell, FILE_CURRENT);
38955 #endif
38956  if (result == 0) {
38957  return ma_result_from_GetLastError(GetLastError());
38958  }
38959 
38960  if (pCursor != NULL) {
38961  *pCursor = liTell.QuadPart;
38962  }
38963 
38964  return MA_SUCCESS;
38965 }
38966 
38967 static ma_result ma_default_vfs_info__win32(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
38968 {
38969  BY_HANDLE_FILE_INFORMATION fi;
38970  BOOL result;
38971 
38972  (void)pVFS;
38973 
38974  result = GetFileInformationByHandle((HANDLE)file, &fi);
38975  if (result == 0) {
38976  return ma_result_from_GetLastError(GetLastError());
38977  }
38978 
38979  pInfo->sizeInBytes = ((ma_uint64)fi.nFileSizeHigh << 32) | ((ma_uint64)fi.nFileSizeLow);
38980 
38981  return MA_SUCCESS;
38982 }
38983 #else
38984 static ma_result ma_default_vfs_open__stdio(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
38985 {
38986  ma_result result;
38987  FILE* pFileStd;
38988  const char* pOpenModeStr;
38989 
38990  MA_ASSERT(pFilePath != NULL);
38991  MA_ASSERT(openMode != 0);
38992  MA_ASSERT(pFile != NULL);
38993 
38994  (void)pVFS;
38995 
38996  if ((openMode & MA_OPEN_MODE_READ) != 0) {
38997  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
38998  pOpenModeStr = "r+";
38999  } else {
39000  pOpenModeStr = "rb";
39001  }
39002  } else {
39003  pOpenModeStr = "wb";
39004  }
39005 
39006  result = ma_fopen(&pFileStd, pFilePath, pOpenModeStr);
39007  if (result != MA_SUCCESS) {
39008  return result;
39009  }
39010 
39011  *pFile = pFileStd;
39012 
39013  return MA_SUCCESS;
39014 }
39015 
39016 static ma_result ma_default_vfs_open_w__stdio(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
39017 {
39018  ma_result result;
39019  FILE* pFileStd;
39020  const wchar_t* pOpenModeStr;
39021 
39022  MA_ASSERT(pFilePath != NULL);
39023  MA_ASSERT(openMode != 0);
39024  MA_ASSERT(pFile != NULL);
39025 
39026  (void)pVFS;
39027 
39028  if ((openMode & MA_OPEN_MODE_READ) != 0) {
39029  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
39030  pOpenModeStr = L"r+";
39031  } else {
39032  pOpenModeStr = L"rb";
39033  }
39034  } else {
39035  pOpenModeStr = L"wb";
39036  }
39037 
39038  result = ma_wfopen(&pFileStd, pFilePath, pOpenModeStr, (pVFS != NULL) ? &((ma_default_vfs*)pVFS)->allocationCallbacks : NULL);
39039  if (result != MA_SUCCESS) {
39040  return result;
39041  }
39042 
39043  *pFile = pFileStd;
39044 
39045  return MA_SUCCESS;
39046 }
39047 
39049 {
39050  MA_ASSERT(file != NULL);
39051 
39052  (void)pVFS;
39053 
39054  fclose((FILE*)file);
39055 
39056  return MA_SUCCESS;
39057 }
39058 
39059 static ma_result ma_default_vfs_read__stdio(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
39060 {
39061  size_t result;
39062 
39063  MA_ASSERT(file != NULL);
39064  MA_ASSERT(pDst != NULL);
39065 
39066  (void)pVFS;
39067 
39068  result = fread(pDst, 1, sizeInBytes, (FILE*)file);
39069 
39070  if (pBytesRead != NULL) {
39071  *pBytesRead = result;
39072  }
39073 
39074  if (result != sizeInBytes) {
39075  if (result == 0 && feof((FILE*)file)) {
39076  return MA_AT_END;
39077  } else {
39078  return ma_result_from_errno(ferror((FILE*)file));
39079  }
39080  }
39081 
39082  return MA_SUCCESS;
39083 }
39084 
39085 static ma_result ma_default_vfs_write__stdio(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
39086 {
39087  size_t result;
39088 
39089  MA_ASSERT(file != NULL);
39090  MA_ASSERT(pSrc != NULL);
39091 
39092  (void)pVFS;
39093 
39094  result = fwrite(pSrc, 1, sizeInBytes, (FILE*)file);
39095 
39096  if (pBytesWritten != NULL) {
39097  *pBytesWritten = result;
39098  }
39099 
39100  if (result != sizeInBytes) {
39101  return ma_result_from_errno(ferror((FILE*)file));
39102  }
39103 
39104  return MA_SUCCESS;
39105 }
39106 
39108 {
39109  int result;
39110  int whence;
39111 
39112  MA_ASSERT(file != NULL);
39113 
39114  (void)pVFS;
39115 
39116  if (origin == ma_seek_origin_start) {
39117  whence = SEEK_SET;
39118  } else if (origin == ma_seek_origin_end) {
39119  whence = SEEK_END;
39120  } else {
39121  whence = SEEK_CUR;
39122  }
39123 
39124 #if defined(_WIN32)
39125  #if defined(_MSC_VER) && _MSC_VER > 1200
39126  result = _fseeki64((FILE*)file, offset, whence);
39127  #else
39128  /* No _fseeki64() so restrict to 31 bits. */
39129  if (origin > 0x7FFFFFFF) {
39130  return MA_OUT_OF_RANGE;
39131  }
39132 
39133  result = fseek((FILE*)file, (int)offset, whence);
39134  #endif
39135 #else
39136  result = fseek((FILE*)file, (long int)offset, whence);
39137 #endif
39138  if (result != 0) {
39139  return MA_ERROR;
39140  }
39141 
39142  return MA_SUCCESS;
39143 }
39144 
39146 {
39147  ma_int64 result;
39148 
39149  MA_ASSERT(file != NULL);
39150  MA_ASSERT(pCursor != NULL);
39151 
39152  (void)pVFS;
39153 
39154 #if defined(_WIN32)
39155  #if defined(_MSC_VER) && _MSC_VER > 1200
39156  result = _ftelli64((FILE*)file);
39157  #else
39158  result = ftell((FILE*)file);
39159  #endif
39160 #else
39161  result = ftell((FILE*)file);
39162 #endif
39163 
39164  *pCursor = result;
39165 
39166  return MA_SUCCESS;
39167 }
39168 
39169 #if !defined(_MSC_VER) && !((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)) && !defined(MA_BSD)
39170 int fileno(FILE *stream);
39171 #endif
39172 
39174 {
39175  int fd;
39176  struct stat info;
39177 
39178  MA_ASSERT(file != NULL);
39179  MA_ASSERT(pInfo != NULL);
39180 
39181  (void)pVFS;
39182 
39183 #if defined(_MSC_VER)
39184  fd = _fileno((FILE*)file);
39185 #else
39186  fd = fileno((FILE*)file);
39187 #endif
39188 
39189  if (fstat(fd, &info) != 0) {
39190  return ma_result_from_errno(errno);
39191  }
39192 
39193  pInfo->sizeInBytes = info.st_size;
39194 
39195  return MA_SUCCESS;
39196 }
39197 #endif
39198 
39199 
39200 static ma_result ma_default_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
39201 {
39202  if (pFile == NULL) {
39203  return MA_INVALID_ARGS;
39204  }
39205 
39206  *pFile = NULL;
39207 
39208  if (pFilePath == NULL || openMode == 0) {
39209  return MA_INVALID_ARGS;
39210  }
39211 
39212 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39213  return ma_default_vfs_open__win32(pVFS, pFilePath, openMode, pFile);
39214 #else
39215  return ma_default_vfs_open__stdio(pVFS, pFilePath, openMode, pFile);
39216 #endif
39217 }
39218 
39219 static ma_result ma_default_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
39220 {
39221  if (pFile == NULL) {
39222  return MA_INVALID_ARGS;
39223  }
39224 
39225  *pFile = NULL;
39226 
39227  if (pFilePath == NULL || openMode == 0) {
39228  return MA_INVALID_ARGS;
39229  }
39230 
39231 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39232  return ma_default_vfs_open_w__win32(pVFS, pFilePath, openMode, pFile);
39233 #else
39234  return ma_default_vfs_open_w__stdio(pVFS, pFilePath, openMode, pFile);
39235 #endif
39236 }
39237 
39239 {
39240  if (file == NULL) {
39241  return MA_INVALID_ARGS;
39242  }
39243 
39244 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39245  return ma_default_vfs_close__win32(pVFS, file);
39246 #else
39247  return ma_default_vfs_close__stdio(pVFS, file);
39248 #endif
39249 }
39250 
39251 static ma_result ma_default_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
39252 {
39253  if (pBytesRead != NULL) {
39254  *pBytesRead = 0;
39255  }
39256 
39257  if (file == NULL || pDst == NULL) {
39258  return MA_INVALID_ARGS;
39259  }
39260 
39261 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39262  return ma_default_vfs_read__win32(pVFS, file, pDst, sizeInBytes, pBytesRead);
39263 #else
39264  return ma_default_vfs_read__stdio(pVFS, file, pDst, sizeInBytes, pBytesRead);
39265 #endif
39266 }
39267 
39268 static ma_result ma_default_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
39269 {
39270  if (pBytesWritten != NULL) {
39271  *pBytesWritten = 0;
39272  }
39273 
39274  if (file == NULL || pSrc == NULL) {
39275  return MA_INVALID_ARGS;
39276  }
39277 
39278 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39279  return ma_default_vfs_write__win32(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
39280 #else
39281  return ma_default_vfs_write__stdio(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
39282 #endif
39283 }
39284 
39286 {
39287  if (file == NULL) {
39288  return MA_INVALID_ARGS;
39289  }
39290 
39291 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39292  return ma_default_vfs_seek__win32(pVFS, file, offset, origin);
39293 #else
39294  return ma_default_vfs_seek__stdio(pVFS, file, offset, origin);
39295 #endif
39296 }
39297 
39299 {
39300  if (pCursor == NULL) {
39301  return MA_INVALID_ARGS;
39302  }
39303 
39304  *pCursor = 0;
39305 
39306  if (file == NULL) {
39307  return MA_INVALID_ARGS;
39308  }
39309 
39310 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39311  return ma_default_vfs_tell__win32(pVFS, file, pCursor);
39312 #else
39313  return ma_default_vfs_tell__stdio(pVFS, file, pCursor);
39314 #endif
39315 }
39316 
39318 {
39319  if (pInfo == NULL) {
39320  return MA_INVALID_ARGS;
39321  }
39322 
39323  MA_ZERO_OBJECT(pInfo);
39324 
39325  if (file == NULL) {
39326  return MA_INVALID_ARGS;
39327  }
39328 
39329 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
39330  return ma_default_vfs_info__win32(pVFS, file, pInfo);
39331 #else
39332  return ma_default_vfs_info__stdio(pVFS, file, pInfo);
39333 #endif
39334 }
39335 
39336 
39338 {
39339  if (pVFS == NULL) {
39340  return MA_INVALID_ARGS;
39341  }
39342 
39343  pVFS->cb.onOpen = ma_default_vfs_open;
39346  pVFS->cb.onRead = ma_default_vfs_read;
39348  pVFS->cb.onSeek = ma_default_vfs_seek;
39349  pVFS->cb.onTell = ma_default_vfs_tell;
39350  pVFS->cb.onInfo = ma_default_vfs_info;
39351  ma_allocation_callbacks_init_copy(&pVFS->allocationCallbacks, pAllocationCallbacks);
39352 
39353  return MA_SUCCESS;
39354 }
39355 
39356 
39357 MA_API ma_result ma_vfs_or_default_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
39358 {
39359  if (pVFS != NULL) {
39360  return ma_vfs_open(pVFS, pFilePath, openMode, pFile);
39361  } else {
39362  return ma_default_vfs_open(pVFS, pFilePath, openMode, pFile);
39363  }
39364 }
39365 
39366 MA_API ma_result ma_vfs_or_default_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
39367 {
39368  if (pVFS != NULL) {
39369  return ma_vfs_open_w(pVFS, pFilePath, openMode, pFile);
39370  } else {
39371  return ma_default_vfs_open_w(pVFS, pFilePath, openMode, pFile);
39372  }
39373 }
39374 
39376 {
39377  if (pVFS != NULL) {
39378  return ma_vfs_close(pVFS, file);
39379  } else {
39380  return ma_default_vfs_close(pVFS, file);
39381  }
39382 }
39383 
39384 MA_API ma_result ma_vfs_or_default_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
39385 {
39386  if (pVFS != NULL) {
39387  return ma_vfs_read(pVFS, file, pDst, sizeInBytes, pBytesRead);
39388  } else {
39389  return ma_default_vfs_read(pVFS, file, pDst, sizeInBytes, pBytesRead);
39390  }
39391 }
39392 
39393 MA_API ma_result ma_vfs_or_default_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
39394 {
39395  if (pVFS != NULL) {
39396  return ma_vfs_write(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
39397  } else {
39398  return ma_default_vfs_write(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
39399  }
39400 }
39401 
39403 {
39404  if (pVFS != NULL) {
39405  return ma_vfs_seek(pVFS, file, offset, origin);
39406  } else {
39407  return ma_default_vfs_seek(pVFS, file, offset, origin);
39408  }
39409 }
39410 
39412 {
39413  if (pVFS != NULL) {
39414  return ma_vfs_tell(pVFS, file, pCursor);
39415  } else {
39416  return ma_default_vfs_tell(pVFS, file, pCursor);
39417  }
39418 }
39419 
39421 {
39422  if (pVFS != NULL) {
39423  return ma_vfs_info(pVFS, file, pInfo);
39424  } else {
39425  return ma_default_vfs_info(pVFS, file, pInfo);
39426  }
39427 }
39428 
39429 
39430 
39431 /**************************************************************************************************************************************************************
39432 
39433 Decoding and Encoding Headers. These are auto-generated from a tool.
39434 
39435 **************************************************************************************************************************************************************/
39436 #if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING))
39437 /* dr_wav_h begin */
39438 #ifndef dr_wav_h
39439 #define dr_wav_h
39440 #ifdef __cplusplus
39441 extern "C" {
39442 #endif
39443 #define DRWAV_STRINGIFY(x) #x
39444 #define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
39445 #define DRWAV_VERSION_MAJOR 0
39446 #define DRWAV_VERSION_MINOR 13
39447 #define DRWAV_VERSION_REVISION 1
39448 #define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
39449 #include <stddef.h>
39450 typedef signed char drwav_int8;
39451 typedef unsigned char drwav_uint8;
39452 typedef signed short drwav_int16;
39453 typedef unsigned short drwav_uint16;
39454 typedef signed int drwav_int32;
39455 typedef unsigned int drwav_uint32;
39456 #if defined(_MSC_VER) && !defined(__clang__)
39457  typedef signed __int64 drwav_int64;
39458  typedef unsigned __int64 drwav_uint64;
39459 #else
39460  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
39461  #pragma GCC diagnostic push
39462  #pragma GCC diagnostic ignored "-Wlong-long"
39463  #if defined(__clang__)
39464  #pragma GCC diagnostic ignored "-Wc++11-long-long"
39465  #endif
39466  #endif
39467  typedef signed long long drwav_int64;
39468  typedef unsigned long long drwav_uint64;
39469  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
39470  #pragma GCC diagnostic pop
39471  #endif
39472 #endif
39473 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
39474  typedef drwav_uint64 drwav_uintptr;
39475 #else
39477 #endif
39480 #define DRWAV_TRUE 1
39481 #define DRWAV_FALSE 0
39482 #if !defined(DRWAV_API)
39483  #if defined(DRWAV_DLL)
39484  #if defined(_WIN32)
39485  #define DRWAV_DLL_IMPORT __declspec(dllimport)
39486  #define DRWAV_DLL_EXPORT __declspec(dllexport)
39487  #define DRWAV_DLL_PRIVATE static
39488  #else
39489  #if defined(__GNUC__) && __GNUC__ >= 4
39490  #define DRWAV_DLL_IMPORT __attribute__((visibility("default")))
39491  #define DRWAV_DLL_EXPORT __attribute__((visibility("default")))
39492  #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
39493  #else
39494  #define DRWAV_DLL_IMPORT
39495  #define DRWAV_DLL_EXPORT
39496  #define DRWAV_DLL_PRIVATE static
39497  #endif
39498  #endif
39499  #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
39500  #define DRWAV_API DRWAV_DLL_EXPORT
39501  #else
39502  #define DRWAV_API DRWAV_DLL_IMPORT
39503  #endif
39504  #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
39505  #else
39506  #define DRWAV_API extern
39507  #define DRWAV_PRIVATE static
39508  #endif
39509 #endif
39511 #define DRWAV_SUCCESS 0
39512 #define DRWAV_ERROR -1
39513 #define DRWAV_INVALID_ARGS -2
39514 #define DRWAV_INVALID_OPERATION -3
39515 #define DRWAV_OUT_OF_MEMORY -4
39516 #define DRWAV_OUT_OF_RANGE -5
39517 #define DRWAV_ACCESS_DENIED -6
39518 #define DRWAV_DOES_NOT_EXIST -7
39519 #define DRWAV_ALREADY_EXISTS -8
39520 #define DRWAV_TOO_MANY_OPEN_FILES -9
39521 #define DRWAV_INVALID_FILE -10
39522 #define DRWAV_TOO_BIG -11
39523 #define DRWAV_PATH_TOO_LONG -12
39524 #define DRWAV_NAME_TOO_LONG -13
39525 #define DRWAV_NOT_DIRECTORY -14
39526 #define DRWAV_IS_DIRECTORY -15
39527 #define DRWAV_DIRECTORY_NOT_EMPTY -16
39528 #define DRWAV_END_OF_FILE -17
39529 #define DRWAV_NO_SPACE -18
39530 #define DRWAV_BUSY -19
39531 #define DRWAV_IO_ERROR -20
39532 #define DRWAV_INTERRUPT -21
39533 #define DRWAV_UNAVAILABLE -22
39534 #define DRWAV_ALREADY_IN_USE -23
39535 #define DRWAV_BAD_ADDRESS -24
39536 #define DRWAV_BAD_SEEK -25
39537 #define DRWAV_BAD_PIPE -26
39538 #define DRWAV_DEADLOCK -27
39539 #define DRWAV_TOO_MANY_LINKS -28
39540 #define DRWAV_NOT_IMPLEMENTED -29
39541 #define DRWAV_NO_MESSAGE -30
39542 #define DRWAV_BAD_MESSAGE -31
39543 #define DRWAV_NO_DATA_AVAILABLE -32
39544 #define DRWAV_INVALID_DATA -33
39545 #define DRWAV_TIMEOUT -34
39546 #define DRWAV_NO_NETWORK -35
39547 #define DRWAV_NOT_UNIQUE -36
39548 #define DRWAV_NOT_SOCKET -37
39549 #define DRWAV_NO_ADDRESS -38
39550 #define DRWAV_BAD_PROTOCOL -39
39551 #define DRWAV_PROTOCOL_UNAVAILABLE -40
39552 #define DRWAV_PROTOCOL_NOT_SUPPORTED -41
39553 #define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
39554 #define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED -43
39555 #define DRWAV_SOCKET_NOT_SUPPORTED -44
39556 #define DRWAV_CONNECTION_RESET -45
39557 #define DRWAV_ALREADY_CONNECTED -46
39558 #define DRWAV_NOT_CONNECTED -47
39559 #define DRWAV_CONNECTION_REFUSED -48
39560 #define DRWAV_NO_HOST -49
39561 #define DRWAV_IN_PROGRESS -50
39562 #define DRWAV_CANCELLED -51
39563 #define DRWAV_MEMORY_ALREADY_MAPPED -52
39564 #define DRWAV_AT_END -53
39565 #define DR_WAVE_FORMAT_PCM 0x1
39566 #define DR_WAVE_FORMAT_ADPCM 0x2
39567 #define DR_WAVE_FORMAT_IEEE_FLOAT 0x3
39568 #define DR_WAVE_FORMAT_ALAW 0x6
39569 #define DR_WAVE_FORMAT_MULAW 0x7
39570 #define DR_WAVE_FORMAT_DVI_ADPCM 0x11
39571 #define DR_WAVE_FORMAT_EXTENSIBLE 0xFFFE
39572 #define DRWAV_SEQUENTIAL 0x00000001
39573 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
39574 DRWAV_API const char* drwav_version_string(void);
39575 typedef enum
39576 {
39580 typedef enum
39581 {
39585 } drwav_container;
39586 typedef struct
39587 {
39588  union
39589  {
39590  drwav_uint8 fourcc[4];
39591  drwav_uint8 guid[16];
39592  } id;
39593  drwav_uint64 sizeInBytes;
39594  unsigned int paddingSize;
39596 typedef struct
39597 {
39598  drwav_uint16 formatTag;
39599  drwav_uint16 channels;
39600  drwav_uint32 sampleRate;
39601  drwav_uint32 avgBytesPerSec;
39602  drwav_uint16 blockAlign;
39603  drwav_uint16 bitsPerSample;
39604  drwav_uint16 extendedSize;
39605  drwav_uint16 validBitsPerSample;
39606  drwav_uint32 channelMask;
39607  drwav_uint8 subFormat[16];
39608 } drwav_fmt;
39610 typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
39611 typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
39612 typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
39613 typedef drwav_uint64 (* drwav_chunk_proc)(void* pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_chunk_header* pChunkHeader, drwav_container container, const drwav_fmt* pFMT);
39614 typedef struct
39615 {
39616  void* pUserData;
39617  void* (* onMalloc)(size_t sz, void* pUserData);
39618  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
39619  void (* onFree)(void* p, void* pUserData);
39621 typedef struct
39622 {
39623  const drwav_uint8* data;
39624  size_t dataSize;
39625  size_t currentReadPos;
39627 typedef struct
39628 {
39629  void** ppData;
39630  size_t* pDataSize;
39631  size_t dataSize;
39632  size_t dataCapacity;
39633  size_t currentWritePos;
39635 typedef struct
39636 {
39637  drwav_container container;
39638  drwav_uint32 format;
39639  drwav_uint32 channels;
39640  drwav_uint32 sampleRate;
39641  drwav_uint32 bitsPerSample;
39643 typedef enum
39644 {
39679 typedef enum
39680 {
39685 typedef struct
39686 {
39687  drwav_uint32 cuePointId;
39688  drwav_uint32 type;
39689  drwav_uint32 firstSampleByteOffset;
39690  drwav_uint32 lastSampleByteOffset;
39691  drwav_uint32 sampleFraction;
39692  drwav_uint32 playCount;
39693 } drwav_smpl_loop;
39694 typedef struct
39695 {
39696  drwav_uint32 manufacturerId;
39697  drwav_uint32 productId;
39698  drwav_uint32 samplePeriodNanoseconds;
39699  drwav_uint32 midiUnityNote;
39700  drwav_uint32 midiPitchFraction;
39701  drwav_uint32 smpteFormat;
39702  drwav_uint32 smpteOffset;
39703  drwav_uint32 sampleLoopCount;
39704  drwav_uint32 samplerSpecificDataSizeInBytes;
39705  drwav_smpl_loop* pLoops;
39706  drwav_uint8* pSamplerSpecificData;
39707 } drwav_smpl;
39708 typedef struct
39709 {
39710  drwav_int8 midiUnityNote;
39711  drwav_int8 fineTuneCents;
39712  drwav_int8 gainDecibels;
39713  drwav_int8 lowNote;
39714  drwav_int8 highNote;
39715  drwav_int8 lowVelocity;
39716  drwav_int8 highVelocity;
39717 } drwav_inst;
39718 typedef struct
39719 {
39720  drwav_uint32 id;
39721  drwav_uint32 playOrderPosition;
39722  drwav_uint8 dataChunkId[4];
39723  drwav_uint32 chunkStart;
39724  drwav_uint32 blockStart;
39725  drwav_uint32 sampleByteOffset;
39726 } drwav_cue_point;
39727 typedef struct
39728 {
39729  drwav_uint32 cuePointCount;
39730  drwav_cue_point *pCuePoints;
39731 } drwav_cue;
39732 typedef enum
39733 {
39739 } drwav_acid_flag;
39740 typedef struct
39741 {
39742  drwav_uint32 flags;
39743  drwav_uint16 midiUnityNote;
39744  drwav_uint16 reserved1;
39745  float reserved2;
39746  drwav_uint32 numBeats;
39747  drwav_uint16 meterDenominator;
39748  drwav_uint16 meterNumerator;
39749  float tempo;
39750 } drwav_acid;
39751 typedef struct
39752 {
39753  drwav_uint32 cuePointId;
39754  drwav_uint32 stringLength;
39755  char* pString;
39757 typedef struct
39758 {
39759  char* pDescription;
39760  char* pOriginatorName;
39761  char* pOriginatorReference;
39762  char pOriginationDate[10];
39763  char pOriginationTime[8];
39764  drwav_uint64 timeReference;
39766  char* pCodingHistory;
39767  drwav_uint32 codingHistorySize;
39768  drwav_uint8* pUMID;
39769  drwav_uint16 loudnessValue;
39770  drwav_uint16 loudnessRange;
39771  drwav_uint16 maxTruePeakLevel;
39772  drwav_uint16 maxMomentaryLoudness;
39773  drwav_uint16 maxShortTermLoudness;
39774 } drwav_bext;
39775 typedef struct
39776 {
39777  drwav_uint32 stringLength;
39778  char* pString;
39780 typedef struct
39781 {
39782  drwav_uint32 cuePointId;
39783  drwav_uint32 sampleLength;
39784  drwav_uint8 purposeId[4];
39785  drwav_uint16 country;
39786  drwav_uint16 language;
39787  drwav_uint16 dialect;
39788  drwav_uint16 codePage;
39789  drwav_uint32 stringLength;
39790  char* pString;
39792 typedef enum
39793 {
39799 typedef struct
39800 {
39801  drwav_uint8 id[4];
39802  drwav_metadata_location chunkLocation;
39803  drwav_uint32 dataSizeInBytes;
39804  drwav_uint8* pData;
39806 typedef struct
39807 {
39808  drwav_metadata_type type;
39809  union
39810  {
39811  drwav_cue cue;
39812  drwav_smpl smpl;
39813  drwav_acid acid;
39814  drwav_inst inst;
39815  drwav_bext bext;
39816  drwav_list_label_or_note labelOrNote;
39817  drwav_list_labelled_cue_region labelledCueRegion;
39818  drwav_list_info_text infoText;
39819  drwav_unknown_metadata unknown;
39820  } data;
39821 } drwav_metadata;
39822 typedef struct
39823 {
39824  drwav_read_proc onRead;
39825  drwav_write_proc onWrite;
39826  drwav_seek_proc onSeek;
39827  void* pUserData;
39828  drwav_allocation_callbacks allocationCallbacks;
39829  drwav_container container;
39830  drwav_fmt fmt;
39831  drwav_uint32 sampleRate;
39832  drwav_uint16 channels;
39833  drwav_uint16 bitsPerSample;
39834  drwav_uint16 translatedFormatTag;
39835  drwav_uint64 totalPCMFrameCount;
39836  drwav_uint64 dataChunkDataSize;
39837  drwav_uint64 dataChunkDataPos;
39838  drwav_uint64 bytesRemaining;
39839  drwav_uint64 readCursorInPCMFrames;
39840  drwav_uint64 dataChunkDataSizeTargetWrite;
39841  drwav_bool32 isSequentialWrite;
39842  drwav_metadata_type allowedMetadataTypes;
39843  drwav_metadata* pMetadata;
39844  drwav_uint32 metadataCount;
39845  drwav__memory_stream memoryStream;
39846  drwav__memory_stream_write memoryStreamWrite;
39847  struct
39848  {
39849  drwav_uint32 bytesRemainingInBlock;
39850  drwav_uint16 predictor[2];
39851  drwav_int32 delta[2];
39852  drwav_int32 cachedFrames[4];
39853  drwav_uint32 cachedFrameCount;
39854  drwav_int32 prevFrames[2][2];
39855  } msadpcm;
39856  struct
39857  {
39858  drwav_uint32 bytesRemainingInBlock;
39859  drwav_int32 predictor[2];
39860  drwav_int32 stepIndex[2];
39861  drwav_int32 cachedFrames[16];
39862  drwav_uint32 cachedFrameCount;
39863  } ima;
39864 } drwav;
39865 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
39866 DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39867 DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39868 DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
39869 DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
39870 DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
39871 DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
39872 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
39875 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
39876 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
39877 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
39878 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
39882 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
39883 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
39884 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
39885 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
39886 #ifndef DR_WAV_NO_CONVERSION_API
39890 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
39891 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
39892 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
39893 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
39894 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
39895 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
39896 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
39897 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
39898 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
39899 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
39900 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
39901 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
39902 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
39903 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
39904 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
39905 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
39906 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
39910 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
39911 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
39912 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
39913 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
39914 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
39915 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
39916 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
39917 #endif
39918 #ifndef DR_WAV_NO_STDIO
39919 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
39920 DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39921 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
39922 DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39923 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39924 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39925 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
39926 DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
39927 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
39928 DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
39929 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
39930 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
39931 #endif
39932 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
39933 DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39934 DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void* data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
39935 DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
39936 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
39937 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
39938 #ifndef DR_WAV_NO_CONVERSION_API
39939 DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39940 DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39941 DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39942 #ifndef DR_WAV_NO_STDIO
39943 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39944 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39945 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39946 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39947 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39948 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39949 #endif
39950 DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39951 DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39952 DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
39953 #endif
39954 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
39961 DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data);
39963 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
39964 #ifdef __cplusplus
39965 }
39966 #endif
39967 #endif
39968 /* dr_wav_h end */
39969 #endif /* MA_NO_WAV */
39970 
39971 #if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING)
39972 /* dr_flac_h begin */
39973 #ifndef dr_flac_h
39974 #define dr_flac_h
39975 #ifdef __cplusplus
39976 extern "C" {
39977 #endif
39978 #define DRFLAC_STRINGIFY(x) #x
39979 #define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
39980 #define DRFLAC_VERSION_MAJOR 0
39981 #define DRFLAC_VERSION_MINOR 12
39982 #define DRFLAC_VERSION_REVISION 30
39983 #define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
39984 #include <stddef.h>
39985 typedef signed char drflac_int8;
39986 typedef unsigned char drflac_uint8;
39987 typedef signed short drflac_int16;
39988 typedef unsigned short drflac_uint16;
39989 typedef signed int drflac_int32;
39990 typedef unsigned int drflac_uint32;
39991 #if defined(_MSC_VER)
39992  typedef signed __int64 drflac_int64;
39993  typedef unsigned __int64 drflac_uint64;
39994 #else
39995  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
39996  #pragma GCC diagnostic push
39997  #pragma GCC diagnostic ignored "-Wlong-long"
39998  #if defined(__clang__)
39999  #pragma GCC diagnostic ignored "-Wc++11-long-long"
40000  #endif
40001  #endif
40002  typedef signed long long drflac_int64;
40003  typedef unsigned long long drflac_uint64;
40004  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
40005  #pragma GCC diagnostic pop
40006  #endif
40007 #endif
40008 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
40009  typedef drflac_uint64 drflac_uintptr;
40010 #else
40012 #endif
40015 #define DRFLAC_TRUE 1
40016 #define DRFLAC_FALSE 0
40017 #if !defined(DRFLAC_API)
40018  #if defined(DRFLAC_DLL)
40019  #if defined(_WIN32)
40020  #define DRFLAC_DLL_IMPORT __declspec(dllimport)
40021  #define DRFLAC_DLL_EXPORT __declspec(dllexport)
40022  #define DRFLAC_DLL_PRIVATE static
40023  #else
40024  #if defined(__GNUC__) && __GNUC__ >= 4
40025  #define DRFLAC_DLL_IMPORT __attribute__((visibility("default")))
40026  #define DRFLAC_DLL_EXPORT __attribute__((visibility("default")))
40027  #define DRFLAC_DLL_PRIVATE __attribute__((visibility("hidden")))
40028  #else
40029  #define DRFLAC_DLL_IMPORT
40030  #define DRFLAC_DLL_EXPORT
40031  #define DRFLAC_DLL_PRIVATE static
40032  #endif
40033  #endif
40034  #if defined(DR_FLAC_IMPLEMENTATION) || defined(DRFLAC_IMPLEMENTATION)
40035  #define DRFLAC_API DRFLAC_DLL_EXPORT
40036  #else
40037  #define DRFLAC_API DRFLAC_DLL_IMPORT
40038  #endif
40039  #define DRFLAC_PRIVATE DRFLAC_DLL_PRIVATE
40040  #else
40041  #define DRFLAC_API extern
40042  #define DRFLAC_PRIVATE static
40043  #endif
40044 #endif
40045 #if defined(_MSC_VER) && _MSC_VER >= 1700
40046  #define DRFLAC_DEPRECATED __declspec(deprecated)
40047 #elif (defined(__GNUC__) && __GNUC__ >= 4)
40048  #define DRFLAC_DEPRECATED __attribute__((deprecated))
40049 #elif defined(__has_feature)
40050  #if __has_feature(attribute_deprecated)
40051  #define DRFLAC_DEPRECATED __attribute__((deprecated))
40052  #else
40053  #define DRFLAC_DEPRECATED
40054  #endif
40055 #else
40056  #define DRFLAC_DEPRECATED
40057 #endif
40058 DRFLAC_API void drflac_version(drflac_uint32* pMajor, drflac_uint32* pMinor, drflac_uint32* pRevision);
40059 DRFLAC_API const char* drflac_version_string(void);
40060 #ifndef DR_FLAC_BUFFER_SIZE
40061 #define DR_FLAC_BUFFER_SIZE 4096
40062 #endif
40063 #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
40064 #define DRFLAC_64BIT
40065 #endif
40066 #ifdef DRFLAC_64BIT
40068 #else
40070 #endif
40071 #define DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO 0
40072 #define DRFLAC_METADATA_BLOCK_TYPE_PADDING 1
40073 #define DRFLAC_METADATA_BLOCK_TYPE_APPLICATION 2
40074 #define DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE 3
40075 #define DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT 4
40076 #define DRFLAC_METADATA_BLOCK_TYPE_CUESHEET 5
40077 #define DRFLAC_METADATA_BLOCK_TYPE_PICTURE 6
40078 #define DRFLAC_METADATA_BLOCK_TYPE_INVALID 127
40079 #define DRFLAC_PICTURE_TYPE_OTHER 0
40080 #define DRFLAC_PICTURE_TYPE_FILE_ICON 1
40081 #define DRFLAC_PICTURE_TYPE_OTHER_FILE_ICON 2
40082 #define DRFLAC_PICTURE_TYPE_COVER_FRONT 3
40083 #define DRFLAC_PICTURE_TYPE_COVER_BACK 4
40084 #define DRFLAC_PICTURE_TYPE_LEAFLET_PAGE 5
40085 #define DRFLAC_PICTURE_TYPE_MEDIA 6
40086 #define DRFLAC_PICTURE_TYPE_LEAD_ARTIST 7
40087 #define DRFLAC_PICTURE_TYPE_ARTIST 8
40088 #define DRFLAC_PICTURE_TYPE_CONDUCTOR 9
40089 #define DRFLAC_PICTURE_TYPE_BAND 10
40090 #define DRFLAC_PICTURE_TYPE_COMPOSER 11
40091 #define DRFLAC_PICTURE_TYPE_LYRICIST 12
40092 #define DRFLAC_PICTURE_TYPE_RECORDING_LOCATION 13
40093 #define DRFLAC_PICTURE_TYPE_DURING_RECORDING 14
40094 #define DRFLAC_PICTURE_TYPE_DURING_PERFORMANCE 15
40095 #define DRFLAC_PICTURE_TYPE_SCREEN_CAPTURE 16
40096 #define DRFLAC_PICTURE_TYPE_BRIGHT_COLORED_FISH 17
40097 #define DRFLAC_PICTURE_TYPE_ILLUSTRATION 18
40098 #define DRFLAC_PICTURE_TYPE_BAND_LOGOTYPE 19
40099 #define DRFLAC_PICTURE_TYPE_PUBLISHER_LOGOTYPE 20
40100 typedef enum
40101 {
40106 typedef enum
40107 {
40111 #pragma pack(2)
40112 typedef struct
40113 {
40114  drflac_uint64 firstPCMFrame;
40115  drflac_uint64 flacFrameOffset;
40116  drflac_uint16 pcmFrameCount;
40118 #pragma pack()
40119 typedef struct
40120 {
40121  drflac_uint16 minBlockSizeInPCMFrames;
40122  drflac_uint16 maxBlockSizeInPCMFrames;
40123  drflac_uint32 minFrameSizeInPCMFrames;
40124  drflac_uint32 maxFrameSizeInPCMFrames;
40125  drflac_uint32 sampleRate;
40126  drflac_uint8 channels;
40127  drflac_uint8 bitsPerSample;
40128  drflac_uint64 totalPCMFrameCount;
40129  drflac_uint8 md5[16];
40131 typedef struct
40132 {
40133  drflac_uint32 type;
40134  const void* pRawData;
40135  drflac_uint32 rawDataSize;
40136  union
40137  {
40138  drflac_streaminfo streaminfo;
40139  struct
40140  {
40141  int unused;
40142  } padding;
40143  struct
40144  {
40145  drflac_uint32 id;
40146  const void* pData;
40147  drflac_uint32 dataSize;
40148  } application;
40149  struct
40150  {
40151  drflac_uint32 seekpointCount;
40152  const drflac_seekpoint* pSeekpoints;
40153  } seektable;
40154  struct
40155  {
40156  drflac_uint32 vendorLength;
40157  const char* vendor;
40158  drflac_uint32 commentCount;
40159  const void* pComments;
40160  } vorbis_comment;
40161  struct
40162  {
40163  char catalog[128];
40164  drflac_uint64 leadInSampleCount;
40165  drflac_bool32 isCD;
40166  drflac_uint8 trackCount;
40167  const void* pTrackData;
40168  } cuesheet;
40169  struct
40170  {
40171  drflac_uint32 type;
40172  drflac_uint32 mimeLength;
40173  const char* mime;
40174  drflac_uint32 descriptionLength;
40175  const char* description;
40176  drflac_uint32 width;
40177  drflac_uint32 height;
40178  drflac_uint32 colorDepth;
40179  drflac_uint32 indexColorCount;
40180  drflac_uint32 pictureDataSize;
40181  const drflac_uint8* pPictureData;
40182  } picture;
40183  } data;
40184 } drflac_metadata;
40185 typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
40186 typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
40187 typedef void (* drflac_meta_proc)(void* pUserData, drflac_metadata* pMetadata);
40188 typedef struct
40189 {
40190  void* pUserData;
40191  void* (* onMalloc)(size_t sz, void* pUserData);
40192  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
40193  void (* onFree)(void* p, void* pUserData);
40195 typedef struct
40196 {
40197  const drflac_uint8* data;
40198  size_t dataSize;
40199  size_t currentReadPos;
40201 typedef struct
40202 {
40203  drflac_read_proc onRead;
40204  drflac_seek_proc onSeek;
40205  void* pUserData;
40206  size_t unalignedByteCount;
40207  drflac_cache_t unalignedCache;
40208  drflac_uint32 nextL2Line;
40209  drflac_uint32 consumedBits;
40210  drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)];
40211  drflac_cache_t cache;
40212  drflac_uint16 crc16;
40213  drflac_cache_t crc16Cache;
40214  drflac_uint32 crc16CacheIgnoredBytes;
40215 } drflac_bs;
40216 typedef struct
40217 {
40218  drflac_uint8 subframeType;
40219  drflac_uint8 wastedBitsPerSample;
40220  drflac_uint8 lpcOrder;
40221  drflac_int32* pSamplesS32;
40222 } drflac_subframe;
40223 typedef struct
40224 {
40225  drflac_uint64 pcmFrameNumber;
40226  drflac_uint32 flacFrameNumber;
40227  drflac_uint32 sampleRate;
40228  drflac_uint16 blockSizeInPCMFrames;
40229  drflac_uint8 channelAssignment;
40230  drflac_uint8 bitsPerSample;
40231  drflac_uint8 crc8;
40233 typedef struct
40234 {
40236  drflac_uint32 pcmFramesRemaining;
40237  drflac_subframe subframes[8];
40238 } drflac_frame;
40239 typedef struct
40240 {
40241  drflac_meta_proc onMeta;
40242  void* pUserDataMD;
40243  drflac_allocation_callbacks allocationCallbacks;
40244  drflac_uint32 sampleRate;
40245  drflac_uint8 channels;
40246  drflac_uint8 bitsPerSample;
40247  drflac_uint16 maxBlockSizeInPCMFrames;
40248  drflac_uint64 totalPCMFrameCount;
40249  drflac_container container;
40250  drflac_uint32 seekpointCount;
40251  drflac_frame currentFLACFrame;
40252  drflac_uint64 currentPCMFrame;
40253  drflac_uint64 firstFLACFramePosInBytes;
40254  drflac__memory_stream memoryStream;
40255  drflac_int32* pDecodedSamples;
40256  drflac_seekpoint* pSeekpoints;
40257  void* _oggbs;
40258  drflac_bool32 _noSeekTableSeek : 1;
40259  drflac_bool32 _noBinarySearchSeek : 1;
40260  drflac_bool32 _noBruteForceSeek : 1;
40261  drflac_bs bs;
40262  drflac_uint8 pExtraData[1];
40263 } drflac;
40264 DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40265 DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40266 DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40267 DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40268 DRFLAC_API void drflac_close(drflac* pFlac);
40271 DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut);
40273 #ifndef DR_FLAC_NO_STDIO
40274 DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
40275 DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
40276 DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40277 DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40278 #endif
40279 DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks);
40280 DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t dataSize, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
40281 DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40282 DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40283 DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40284 #ifndef DR_FLAC_NO_STDIO
40285 DRFLAC_API drflac_int32* drflac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40286 DRFLAC_API drflac_int16* drflac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40287 DRFLAC_API float* drflac_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40288 #endif
40289 DRFLAC_API drflac_int32* drflac_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40290 DRFLAC_API drflac_int16* drflac_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40291 DRFLAC_API float* drflac_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
40292 DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks);
40293 typedef struct
40294 {
40295  drflac_uint32 countRemaining;
40296  const char* pRunningData;
40298 DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments);
40300 typedef struct
40301 {
40302  drflac_uint32 countRemaining;
40303  const char* pRunningData;
40305 #pragma pack(4)
40306 typedef struct
40307 {
40308  drflac_uint64 offset;
40309  drflac_uint8 index;
40310  drflac_uint8 reserved[3];
40312 #pragma pack()
40313 typedef struct
40314 {
40315  drflac_uint64 offset;
40316  drflac_uint8 trackNumber;
40317  char ISRC[12];
40318  drflac_bool8 isAudio;
40319  drflac_bool8 preEmphasis;
40320  drflac_uint8 indexCount;
40321  const drflac_cuesheet_track_index* pIndexPoints;
40323 DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData);
40325 #ifdef __cplusplus
40326 }
40327 #endif
40328 #endif
40329 /* dr_flac_h end */
40330 #endif /* MA_NO_FLAC */
40331 
40332 #if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
40333 /* dr_mp3_h begin */
40334 #ifndef dr_mp3_h
40335 #define dr_mp3_h
40336 #ifdef __cplusplus
40337 extern "C" {
40338 #endif
40339 #define DRMP3_STRINGIFY(x) #x
40340 #define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
40341 #define DRMP3_VERSION_MAJOR 0
40342 #define DRMP3_VERSION_MINOR 6
40343 #define DRMP3_VERSION_REVISION 28
40344 #define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
40345 #include <stddef.h>
40346 typedef signed char drmp3_int8;
40347 typedef unsigned char drmp3_uint8;
40348 typedef signed short drmp3_int16;
40349 typedef unsigned short drmp3_uint16;
40350 typedef signed int drmp3_int32;
40351 typedef unsigned int drmp3_uint32;
40352 #if defined(_MSC_VER)
40353  typedef signed __int64 drmp3_int64;
40354  typedef unsigned __int64 drmp3_uint64;
40355 #else
40356  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
40357  #pragma GCC diagnostic push
40358  #pragma GCC diagnostic ignored "-Wlong-long"
40359  #if defined(__clang__)
40360  #pragma GCC diagnostic ignored "-Wc++11-long-long"
40361  #endif
40362  #endif
40363  typedef signed long long drmp3_int64;
40364  typedef unsigned long long drmp3_uint64;
40365  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
40366  #pragma GCC diagnostic pop
40367  #endif
40368 #endif
40369 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
40370  typedef drmp3_uint64 drmp3_uintptr;
40371 #else
40373 #endif
40376 #define DRMP3_TRUE 1
40377 #define DRMP3_FALSE 0
40378 #if !defined(DRMP3_API)
40379  #if defined(DRMP3_DLL)
40380  #if defined(_WIN32)
40381  #define DRMP3_DLL_IMPORT __declspec(dllimport)
40382  #define DRMP3_DLL_EXPORT __declspec(dllexport)
40383  #define DRMP3_DLL_PRIVATE static
40384  #else
40385  #if defined(__GNUC__) && __GNUC__ >= 4
40386  #define DRMP3_DLL_IMPORT __attribute__((visibility("default")))
40387  #define DRMP3_DLL_EXPORT __attribute__((visibility("default")))
40388  #define DRMP3_DLL_PRIVATE __attribute__((visibility("hidden")))
40389  #else
40390  #define DRMP3_DLL_IMPORT
40391  #define DRMP3_DLL_EXPORT
40392  #define DRMP3_DLL_PRIVATE static
40393  #endif
40394  #endif
40395  #if defined(DR_MP3_IMPLEMENTATION) || defined(DRMP3_IMPLEMENTATION)
40396  #define DRMP3_API DRMP3_DLL_EXPORT
40397  #else
40398  #define DRMP3_API DRMP3_DLL_IMPORT
40399  #endif
40400  #define DRMP3_PRIVATE DRMP3_DLL_PRIVATE
40401  #else
40402  #define DRMP3_API extern
40403  #define DRMP3_PRIVATE static
40404  #endif
40405 #endif
40407 #define DRMP3_SUCCESS 0
40408 #define DRMP3_ERROR -1
40409 #define DRMP3_INVALID_ARGS -2
40410 #define DRMP3_INVALID_OPERATION -3
40411 #define DRMP3_OUT_OF_MEMORY -4
40412 #define DRMP3_OUT_OF_RANGE -5
40413 #define DRMP3_ACCESS_DENIED -6
40414 #define DRMP3_DOES_NOT_EXIST -7
40415 #define DRMP3_ALREADY_EXISTS -8
40416 #define DRMP3_TOO_MANY_OPEN_FILES -9
40417 #define DRMP3_INVALID_FILE -10
40418 #define DRMP3_TOO_BIG -11
40419 #define DRMP3_PATH_TOO_LONG -12
40420 #define DRMP3_NAME_TOO_LONG -13
40421 #define DRMP3_NOT_DIRECTORY -14
40422 #define DRMP3_IS_DIRECTORY -15
40423 #define DRMP3_DIRECTORY_NOT_EMPTY -16
40424 #define DRMP3_END_OF_FILE -17
40425 #define DRMP3_NO_SPACE -18
40426 #define DRMP3_BUSY -19
40427 #define DRMP3_IO_ERROR -20
40428 #define DRMP3_INTERRUPT -21
40429 #define DRMP3_UNAVAILABLE -22
40430 #define DRMP3_ALREADY_IN_USE -23
40431 #define DRMP3_BAD_ADDRESS -24
40432 #define DRMP3_BAD_SEEK -25
40433 #define DRMP3_BAD_PIPE -26
40434 #define DRMP3_DEADLOCK -27
40435 #define DRMP3_TOO_MANY_LINKS -28
40436 #define DRMP3_NOT_IMPLEMENTED -29
40437 #define DRMP3_NO_MESSAGE -30
40438 #define DRMP3_BAD_MESSAGE -31
40439 #define DRMP3_NO_DATA_AVAILABLE -32
40440 #define DRMP3_INVALID_DATA -33
40441 #define DRMP3_TIMEOUT -34
40442 #define DRMP3_NO_NETWORK -35
40443 #define DRMP3_NOT_UNIQUE -36
40444 #define DRMP3_NOT_SOCKET -37
40445 #define DRMP3_NO_ADDRESS -38
40446 #define DRMP3_BAD_PROTOCOL -39
40447 #define DRMP3_PROTOCOL_UNAVAILABLE -40
40448 #define DRMP3_PROTOCOL_NOT_SUPPORTED -41
40449 #define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED -42
40450 #define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED -43
40451 #define DRMP3_SOCKET_NOT_SUPPORTED -44
40452 #define DRMP3_CONNECTION_RESET -45
40453 #define DRMP3_ALREADY_CONNECTED -46
40454 #define DRMP3_NOT_CONNECTED -47
40455 #define DRMP3_CONNECTION_REFUSED -48
40456 #define DRMP3_NO_HOST -49
40457 #define DRMP3_IN_PROGRESS -50
40458 #define DRMP3_CANCELLED -51
40459 #define DRMP3_MEMORY_ALREADY_MAPPED -52
40460 #define DRMP3_AT_END -53
40461 #define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
40462 #define DRMP3_MAX_SAMPLES_PER_FRAME (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2)
40463 #ifdef _MSC_VER
40464  #define DRMP3_INLINE __forceinline
40465 #elif defined(__GNUC__)
40466  #if defined(__STRICT_ANSI__)
40467  #define DRMP3_INLINE __inline__ __attribute__((always_inline))
40468  #else
40469  #define DRMP3_INLINE inline __attribute__((always_inline))
40470  #endif
40471 #elif defined(__WATCOMC__)
40472  #define DRMP3_INLINE __inline
40473 #else
40474  #define DRMP3_INLINE
40475 #endif
40476 DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision);
40477 DRMP3_API const char* drmp3_version_string(void);
40478 typedef struct
40479 {
40480  int frame_bytes, channels, hz, layer, bitrate_kbps;
40482 typedef struct
40483 {
40484  float mdct_overlap[2][9*32], qmf_state[15*2*32];
40485  int reserv, free_format_bytes;
40486  drmp3_uint8 header[4], reserv_buf[511];
40487 } drmp3dec;
40488 DRMP3_API void drmp3dec_init(drmp3dec *dec);
40489 DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info);
40490 DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples);
40491 typedef enum
40492 {
40496 typedef struct
40497 {
40498  drmp3_uint64 seekPosInBytes;
40499  drmp3_uint64 pcmFrameIndex;
40500  drmp3_uint16 mp3FramesToDiscard;
40501  drmp3_uint16 pcmFramesToDiscard;
40503 typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
40504 typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin);
40505 typedef struct
40506 {
40507  void* pUserData;
40508  void* (* onMalloc)(size_t sz, void* pUserData);
40509  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
40510  void (* onFree)(void* p, void* pUserData);
40512 typedef struct
40513 {
40514  drmp3_uint32 channels;
40515  drmp3_uint32 sampleRate;
40516 } drmp3_config;
40517 typedef struct
40518 {
40519  drmp3dec decoder;
40520  drmp3dec_frame_info frameInfo;
40521  drmp3_uint32 channels;
40522  drmp3_uint32 sampleRate;
40523  drmp3_read_proc onRead;
40524  drmp3_seek_proc onSeek;
40525  void* pUserData;
40526  drmp3_allocation_callbacks allocationCallbacks;
40527  drmp3_uint32 mp3FrameChannels;
40528  drmp3_uint32 mp3FrameSampleRate;
40529  drmp3_uint32 pcmFramesConsumedInMP3Frame;
40530  drmp3_uint32 pcmFramesRemainingInMP3Frame;
40531  drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME];
40532  drmp3_uint64 currentPCMFrame;
40533  drmp3_uint64 streamCursor;
40534  drmp3_seek_point* pSeekPoints;
40535  drmp3_uint32 seekPointCount;
40536  size_t dataSize;
40537  size_t dataCapacity;
40538  size_t dataConsumed;
40539  drmp3_uint8* pData;
40540  drmp3_bool32 atEnd : 1;
40541  struct
40542  {
40543  const drmp3_uint8* pData;
40544  size_t dataSize;
40545  size_t currentReadPos;
40546  } memory;
40547 } drmp3;
40548 DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks);
40549 DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks);
40550 #ifndef DR_MP3_NO_STDIO
40551 DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
40552 DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
40553 #endif
40554 DRMP3_API void drmp3_uninit(drmp3* pMP3);
40555 DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut);
40562 DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints);
40563 DRMP3_API float* drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
40564 DRMP3_API drmp3_int16* drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
40565 DRMP3_API float* drmp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
40566 DRMP3_API drmp3_int16* drmp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
40567 #ifndef DR_MP3_NO_STDIO
40568 DRMP3_API float* drmp3_open_file_and_read_pcm_frames_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
40569 DRMP3_API drmp3_int16* drmp3_open_file_and_read_pcm_frames_s16(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
40570 #endif
40571 DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks);
40572 DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks);
40573 #ifdef __cplusplus
40574 }
40575 #endif
40576 #endif
40577 /* dr_mp3_h end */
40578 #endif /* MA_NO_MP3 */
40579 
40580 
40581 /**************************************************************************************************************************************************************
40582 
40583 Decoding
40584 
40585 **************************************************************************************************************************************************************/
40586 #ifndef MA_NO_DECODING
40587 
40588 static ma_result ma_decoder_read_bytes(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead)
40589 {
40590  size_t bytesRead;
40591 
40592  MA_ASSERT(pDecoder != NULL);
40593  MA_ASSERT(pBufferOut != NULL);
40594  MA_ASSERT(bytesToRead > 0); /* It's an error to call this with a byte count of zero. */
40595 
40596  bytesRead = pDecoder->onRead(pDecoder, pBufferOut, bytesToRead);
40597 
40598  if (pBytesRead != NULL) {
40599  *pBytesRead = bytesRead;
40600  }
40601 
40602  if (bytesRead == 0) {
40603  return MA_AT_END;
40604  }
40605 
40606  return MA_SUCCESS;
40607 }
40608 
40610 {
40611  ma_bool32 wasSuccessful;
40612 
40613  MA_ASSERT(pDecoder != NULL);
40614 
40615  wasSuccessful = pDecoder->onSeek(pDecoder, byteOffset, origin);
40616  if (wasSuccessful) {
40617  return MA_SUCCESS;
40618  } else {
40619  return MA_ERROR;
40620  }
40621 }
40622 
40624 {
40625  MA_ASSERT(pDecoder != NULL);
40626 
40627  if (pDecoder->onTell == NULL) {
40628  return MA_NOT_IMPLEMENTED;
40629  }
40630 
40631  return pDecoder->onTell(pDecoder, pCursor);
40632 }
40633 
40634 
40636 {
40638 
40640  config.preferredFormat = preferredFormat;
40641 
40642  return config;
40643 }
40644 
40645 
40646 MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint32 outputChannels, ma_uint32 outputSampleRate)
40647 {
40650  config.format = outputFormat;
40651  config.channels = ma_min(outputChannels, ma_countof(config.channelMap));
40652  config.sampleRate = outputSampleRate;
40653  config.resampling.algorithm = ma_resample_algorithm_linear;
40654  config.resampling.linear.lpfOrder = ma_min(MA_DEFAULT_RESAMPLER_LPF_ORDER, MA_MAX_FILTER_ORDER);
40655  config.resampling.speex.quality = 3;
40656  config.encodingFormat = ma_encoding_format_unknown;
40657 
40658  /* Note that we are intentionally leaving the channel map empty here which will cause the default channel map to be used. */
40659 
40660  return config;
40661 }
40662 
40664 {
40666 }
40667 
40669 {
40671  if (pConfig != NULL) {
40672  config = *pConfig;
40673  } else {
40675  }
40676 
40677  return config;
40678 }
40679 
40681 {
40682  ma_result result;
40683  ma_data_converter_config converterConfig;
40684  ma_format internalFormat;
40685  ma_uint32 internalChannels;
40686  ma_uint32 internalSampleRate;
40687  ma_channel internalChannelMap[MA_MAX_CHANNELS];
40688 
40689  MA_ASSERT(pDecoder != NULL);
40690  MA_ASSERT(pConfig != NULL);
40691 
40692  result = ma_data_source_get_data_format(pDecoder->pBackend, &internalFormat, &internalChannels, &internalSampleRate);
40693  if (result != MA_SUCCESS) {
40694  return result; /* Failed to retrieve the internal data format. */
40695  }
40696 
40697  /* Channel map needs to be retrieved separately. */
40698  if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onGetChannelMap != NULL) {
40699  pDecoder->pBackendVTable->onGetChannelMap(pDecoder->pBackendUserData, pDecoder->pBackend, internalChannelMap, ma_countof(internalChannelMap));
40700  } else {
40701  ma_get_standard_channel_map(ma_standard_channel_map_default, ma_min(internalChannels, ma_countof(internalChannelMap)), internalChannelMap);
40702  }
40703 
40704 
40705 
40706  /* Make sure we're not asking for too many channels. */
40707  if (pConfig->channels > MA_MAX_CHANNELS) {
40708  return MA_INVALID_ARGS;
40709  }
40710 
40711  /* The internal channels should have already been validated at a higher level, but we'll do it again explicitly here for safety. */
40712  if (internalChannels > MA_MAX_CHANNELS) {
40713  return MA_INVALID_ARGS;
40714  }
40715 
40716 
40717  /* Output format. */
40718  if (pConfig->format == ma_format_unknown) {
40719  pDecoder->outputFormat = internalFormat;
40720  } else {
40721  pDecoder->outputFormat = pConfig->format;
40722  }
40723 
40724  if (pConfig->channels == 0) {
40725  pDecoder->outputChannels = internalChannels;
40726  } else {
40727  pDecoder->outputChannels = pConfig->channels;
40728  }
40729 
40730  if (pConfig->sampleRate == 0) {
40731  pDecoder->outputSampleRate = internalSampleRate;
40732  } else {
40733  pDecoder->outputSampleRate = pConfig->sampleRate;
40734  }
40735 
40736  if (ma_channel_map_blank(pDecoder->outputChannels, pConfig->channelMap)) {
40738  } else {
40739  MA_COPY_MEMORY(pDecoder->outputChannelMap, pConfig->channelMap, sizeof(pConfig->channelMap));
40740  }
40741 
40742 
40743  converterConfig = ma_data_converter_config_init(
40744  internalFormat, pDecoder->outputFormat,
40745  internalChannels, pDecoder->outputChannels,
40746  internalSampleRate, pDecoder->outputSampleRate
40747  );
40748  ma_channel_map_copy(converterConfig.channelMapIn, internalChannelMap, internalChannels);
40749  ma_channel_map_copy(converterConfig.channelMapOut, pDecoder->outputChannelMap, pDecoder->outputChannels);
40750  converterConfig.channelMixMode = pConfig->channelMixMode;
40751  converterConfig.ditherMode = pConfig->ditherMode;
40752  converterConfig.resampling.allowDynamicSampleRate = MA_FALSE; /* Never allow dynamic sample rate conversion. Setting this to true will disable passthrough optimizations. */
40753  converterConfig.resampling.algorithm = pConfig->resampling.algorithm;
40754  converterConfig.resampling.linear.lpfOrder = pConfig->resampling.linear.lpfOrder;
40755  converterConfig.resampling.speex.quality = pConfig->resampling.speex.quality;
40756 
40757  return ma_data_converter_init(&converterConfig, &pDecoder->converter);
40758 }
40759 
40760 
40761 
40762 static ma_result ma_decoder_internal_on_read__custom(void* pUserData, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead)
40763 {
40764  ma_decoder* pDecoder = (ma_decoder*)pUserData;
40765  MA_ASSERT(pDecoder != NULL);
40766 
40767  return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead, pBytesRead);
40768 }
40769 
40771 {
40772  ma_decoder* pDecoder = (ma_decoder*)pUserData;
40773  MA_ASSERT(pDecoder != NULL);
40774 
40775  return ma_decoder_seek_bytes(pDecoder, offset, origin);
40776 }
40777 
40778 static ma_result ma_decoder_internal_on_tell__custom(void* pUserData, ma_int64* pCursor)
40779 {
40780  ma_decoder* pDecoder = (ma_decoder*)pUserData;
40781  MA_ASSERT(pDecoder != NULL);
40782 
40783  return ma_decoder_tell_bytes(pDecoder, pCursor);
40784 }
40785 
40786 
40787 static ma_result ma_decoder_init_from_vtable(const ma_decoding_backend_vtable* pVTable, void* pVTableUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
40788 {
40789  ma_result result;
40790  ma_decoding_backend_config backendConfig;
40791  ma_data_source* pBackend;
40792 
40793  MA_ASSERT(pVTable != NULL);
40794  MA_ASSERT(pConfig != NULL);
40795  MA_ASSERT(pDecoder != NULL);
40796 
40797  if (pVTable->onInit == NULL) {
40798  return MA_NOT_IMPLEMENTED;
40799  }
40800 
40801  backendConfig = ma_decoding_backend_config_init(pConfig->format);
40802 
40803  result = pVTable->onInit(pVTableUserData, ma_decoder_internal_on_read__custom, ma_decoder_internal_on_seek__custom, ma_decoder_internal_on_tell__custom, pDecoder, &backendConfig, &pDecoder->allocationCallbacks, &pBackend);
40804  if (result != MA_SUCCESS) {
40805  return result; /* Failed to initialize the backend from this vtable. */
40806  }
40807 
40808  /* Getting here means we were able to initialize the backend so we can now initialize the decoder. */
40809  pDecoder->pBackend = pBackend;
40810  pDecoder->pBackendVTable = pVTable;
40811  pDecoder->pBackendUserData = pConfig->pCustomBackendUserData;
40812 
40813  return MA_SUCCESS;
40814 }
40815 
40816 
40817 
40819 {
40820  ma_result result = MA_NO_BACKEND;
40821  size_t ivtable;
40822 
40823  MA_ASSERT(pConfig != NULL);
40824  MA_ASSERT(pDecoder != NULL);
40825 
40826  if (pConfig->ppCustomBackendVTables == NULL) {
40827  return MA_NO_BACKEND;
40828  }
40829 
40830  /* The order each backend is listed is what defines the priority. */
40831  for (ivtable = 0; ivtable < pConfig->customBackendCount; ivtable += 1) {
40832  const ma_decoding_backend_vtable* pVTable = pConfig->ppCustomBackendVTables[ivtable];
40833  if (pVTable != NULL && pVTable->onInit != NULL) {
40834  result = ma_decoder_init_from_vtable(pVTable, pConfig->pCustomBackendUserData, pConfig, pDecoder);
40835  if (result == MA_SUCCESS) {
40836  return MA_SUCCESS;
40837  } else {
40838  /* Initialization failed. Move on to the next one, but seek back to the start first so the next vtable starts from the first byte of the file. */
40839  result = ma_decoder_seek_bytes(pDecoder, 0, ma_seek_origin_start);
40840  if (result != MA_SUCCESS) {
40841  return result; /* Failed to seek back to the start. */
40842  }
40843  }
40844  } else {
40845  /* No vtable. */
40846  }
40847  }
40848 
40849  /* Getting here means we couldn't find a backend. */
40850  return MA_NO_BACKEND;
40851 }
40852 
40853 
40854 /* WAV */
40855 #ifdef dr_wav_h
40856 #define MA_HAS_WAV
40857 
40858 typedef struct
40859 {
40865  ma_format format; /* Can be f32, s16 or s32. */
40866 #if !defined(MA_NO_WAV)
40868 #endif
40869 } ma_wav;
40870 
40871 MA_API ma_result ma_wav_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav);
40872 MA_API ma_result ma_wav_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav);
40873 MA_API ma_result ma_wav_init_file_w(const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav);
40874 MA_API ma_result ma_wav_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav);
40875 MA_API void ma_wav_uninit(ma_wav* pWav, const ma_allocation_callbacks* pAllocationCallbacks);
40876 MA_API ma_result ma_wav_read_pcm_frames(ma_wav* pWav, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
40878 MA_API ma_result ma_wav_get_data_format(ma_wav* pWav, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
40881 
40882 
40883 static ma_result ma_wav_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
40884 {
40885  return ma_wav_read_pcm_frames((ma_wav*)pDataSource, pFramesOut, frameCount, pFramesRead);
40886 }
40887 
40888 static ma_result ma_wav_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
40889 {
40890  return ma_wav_seek_to_pcm_frame((ma_wav*)pDataSource, frameIndex);
40891 }
40892 
40893 static ma_result ma_wav_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
40894 {
40895  return ma_wav_get_data_format((ma_wav*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
40896 }
40897 
40899 {
40900  return ma_wav_get_cursor_in_pcm_frames((ma_wav*)pDataSource, pCursor);
40901 }
40902 
40904 {
40905  return ma_wav_get_length_in_pcm_frames((ma_wav*)pDataSource, pLength);
40906 }
40907 
40909 {
40912  NULL, /* onMap() */
40913  NULL, /* onUnmap() */
40917 };
40918 
40919 
40920 #if !defined(MA_NO_WAV)
40922 {
40923  drwav_allocation_callbacks callbacks;
40924 
40925  if (pAllocationCallbacks != NULL) {
40926  callbacks.onMalloc = pAllocationCallbacks->onMalloc;
40927  callbacks.onRealloc = pAllocationCallbacks->onRealloc;
40928  callbacks.onFree = pAllocationCallbacks->onFree;
40929  callbacks.pUserData = pAllocationCallbacks->pUserData;
40930  } else {
40931  callbacks.onMalloc = ma__malloc_default;
40932  callbacks.onRealloc = ma__realloc_default;
40933  callbacks.onFree = ma__free_default;
40934  callbacks.pUserData = NULL;
40935  }
40936 
40937  return callbacks;
40938 }
40939 
40940 static size_t ma_wav_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
40941 {
40942  ma_wav* pWav = (ma_wav*)pUserData;
40943  ma_result result;
40944  size_t bytesRead;
40945 
40946  MA_ASSERT(pWav != NULL);
40947 
40948  result = pWav->onRead(pWav->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
40949  (void)result;
40950 
40951  return bytesRead;
40952 }
40953 
40954 static drwav_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, drwav_seek_origin origin)
40955 {
40956  ma_wav* pWav = (ma_wav*)pUserData;
40957  ma_result result;
40958  ma_seek_origin maSeekOrigin;
40959 
40960  MA_ASSERT(pWav != NULL);
40961 
40962  maSeekOrigin = ma_seek_origin_start;
40963  if (origin == drwav_seek_origin_current) {
40964  maSeekOrigin = ma_seek_origin_current;
40965  }
40966 
40967  result = pWav->onSeek(pWav->pReadSeekTellUserData, offset, maSeekOrigin);
40968  if (result != MA_SUCCESS) {
40969  return MA_FALSE;
40970  }
40971 
40972  return MA_TRUE;
40973 }
40974 #endif
40975 
40977 {
40978  ma_result result;
40979  ma_data_source_config dataSourceConfig;
40980 
40981  if (pWav == NULL) {
40982  return MA_INVALID_ARGS;
40983  }
40984 
40985  MA_ZERO_OBJECT(pWav);
40986  pWav->format = ma_format_f32; /* f32 by default. */
40987 
40988  if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16 || pConfig->preferredFormat == ma_format_s32)) {
40989  pWav->format = pConfig->preferredFormat;
40990  } else {
40991  /* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
40992  }
40993 
40994  dataSourceConfig = ma_data_source_config_init();
40995  dataSourceConfig.vtable = &g_ma_wav_ds_vtable;
40996 
40997  result = ma_data_source_init(&dataSourceConfig, &pWav->ds);
40998  if (result != MA_SUCCESS) {
40999  return result; /* Failed to initialize the base data source. */
41000  }
41001 
41002  return MA_SUCCESS;
41003 }
41004 
41005 MA_API ma_result ma_wav_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav)
41006 {
41007  ma_result result;
41008 
41009  result = ma_wav_init_internal(pConfig, pWav);
41010  if (result != MA_SUCCESS) {
41011  return result;
41012  }
41013 
41014  if (onRead == NULL || onSeek == NULL) {
41015  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
41016  }
41017 
41018  pWav->onRead = onRead;
41019  pWav->onSeek = onSeek;
41020  pWav->onTell = onTell;
41021  pWav->pReadSeekTellUserData = pReadSeekTellUserData;
41022 
41023  #if !defined(MA_NO_WAV)
41024  {
41025  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41026  drwav_bool32 wavResult;
41027 
41028  wavResult = drwav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, pWav, &wavAllocationCallbacks);
41029  if (wavResult != MA_TRUE) {
41030  return MA_INVALID_FILE;
41031  }
41032 
41033  return MA_SUCCESS;
41034  }
41035  #else
41036  {
41037  /* wav is disabled. */
41038  (void)pAllocationCallbacks;
41039  return MA_NOT_IMPLEMENTED;
41040  }
41041  #endif
41042 }
41043 
41044 MA_API ma_result ma_wav_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav)
41045 {
41046  ma_result result;
41047 
41048  result = ma_wav_init_internal(pConfig, pWav);
41049  if (result != MA_SUCCESS) {
41050  return result;
41051  }
41052 
41053  #if !defined(MA_NO_WAV)
41054  {
41055  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41056  drwav_bool32 wavResult;
41057 
41058  wavResult = drwav_init_file(&pWav->dr, pFilePath, &wavAllocationCallbacks);
41059  if (wavResult != MA_TRUE) {
41060  return MA_INVALID_FILE;
41061  }
41062 
41063  return MA_SUCCESS;
41064  }
41065  #else
41066  {
41067  /* wav is disabled. */
41068  (void)pFilePath;
41069  (void)pAllocationCallbacks;
41070  return MA_NOT_IMPLEMENTED;
41071  }
41072  #endif
41073 }
41074 
41075 MA_API ma_result ma_wav_init_file_w(const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav)
41076 {
41077  ma_result result;
41078 
41079  result = ma_wav_init_internal(pConfig, pWav);
41080  if (result != MA_SUCCESS) {
41081  return result;
41082  }
41083 
41084  #if !defined(MA_NO_WAV)
41085  {
41086  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41087  drwav_bool32 wavResult;
41088 
41089  wavResult = drwav_init_file_w(&pWav->dr, pFilePath, &wavAllocationCallbacks);
41090  if (wavResult != MA_TRUE) {
41091  return MA_INVALID_FILE;
41092  }
41093 
41094  return MA_SUCCESS;
41095  }
41096  #else
41097  {
41098  /* wav is disabled. */
41099  (void)pFilePath;
41100  (void)pAllocationCallbacks;
41101  return MA_NOT_IMPLEMENTED;
41102  }
41103  #endif
41104 }
41105 
41106 MA_API ma_result ma_wav_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_wav* pWav)
41107 {
41108  ma_result result;
41109 
41110  result = ma_wav_init_internal(pConfig, pWav);
41111  if (result != MA_SUCCESS) {
41112  return result;
41113  }
41114 
41115  #if !defined(MA_NO_WAV)
41116  {
41117  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41118  drwav_bool32 wavResult;
41119 
41120  wavResult = drwav_init_memory(&pWav->dr, pData, dataSize, &wavAllocationCallbacks);
41121  if (wavResult != MA_TRUE) {
41122  return MA_INVALID_FILE;
41123  }
41124 
41125  return MA_SUCCESS;
41126  }
41127  #else
41128  {
41129  /* wav is disabled. */
41130  (void)pData;
41131  (void)dataSize;
41132  (void)pAllocationCallbacks;
41133  return MA_NOT_IMPLEMENTED;
41134  }
41135  #endif
41136 }
41137 
41138 MA_API void ma_wav_uninit(ma_wav* pWav, const ma_allocation_callbacks* pAllocationCallbacks)
41139 {
41140  if (pWav == NULL) {
41141  return;
41142  }
41143 
41144  (void)pAllocationCallbacks;
41145 
41146  #if !defined(MA_NO_WAV)
41147  {
41148  drwav_uninit(&pWav->dr);
41149  }
41150  #else
41151  {
41152  /* wav is disabled. Should never hit this since initialization would have failed. */
41154  }
41155  #endif
41156 
41157  ma_data_source_uninit(&pWav->ds);
41158 }
41159 
41160 MA_API ma_result ma_wav_read_pcm_frames(ma_wav* pWav, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
41161 {
41162  if (pWav == NULL) {
41163  return MA_INVALID_ARGS;
41164  }
41165 
41166  #if !defined(MA_NO_WAV)
41167  {
41168  /* We always use floating point format. */
41169  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
41170  ma_uint64 totalFramesRead = 0;
41171  ma_format format;
41172 
41173  ma_wav_get_data_format(pWav, &format, NULL, NULL, NULL, 0);
41174 
41175  switch (format)
41176  {
41177  case ma_format_f32:
41178  {
41179  totalFramesRead = drwav_read_pcm_frames_f32(&pWav->dr, frameCount, (float*)pFramesOut);
41180  } break;
41181 
41182  case ma_format_s16:
41183  {
41184  totalFramesRead = drwav_read_pcm_frames_s16(&pWav->dr, frameCount, (drwav_int16*)pFramesOut);
41185  } break;
41186 
41187  case ma_format_s32:
41188  {
41189  totalFramesRead = drwav_read_pcm_frames_s32(&pWav->dr, frameCount, (drwav_int32*)pFramesOut);
41190  } break;
41191 
41192  /* Fallback to a raw read. */
41193  case ma_format_unknown: return MA_INVALID_OPERATION; /* <-- this should never be hit because initialization would just fall back to supported format. */
41194  default:
41195  {
41196  totalFramesRead = drwav_read_pcm_frames(&pWav->dr, frameCount, pFramesOut);
41197  } break;
41198  }
41199 
41200  /* In the future we'll update dr_wav to return MA_AT_END for us. */
41201  if (totalFramesRead == 0) {
41202  result = MA_AT_END;
41203  }
41204 
41205  if (pFramesRead != NULL) {
41206  *pFramesRead = totalFramesRead;
41207  }
41208 
41209  return result;
41210  }
41211  #else
41212  {
41213  /* wav is disabled. Should never hit this since initialization would have failed. */
41215 
41216  (void)pFramesOut;
41217  (void)frameCount;
41218  (void)pFramesRead;
41219 
41220  return MA_NOT_IMPLEMENTED;
41221  }
41222  #endif
41223 }
41224 
41226 {
41227  if (pWav == NULL) {
41228  return MA_INVALID_ARGS;
41229  }
41230 
41231  #if !defined(MA_NO_WAV)
41232  {
41233  drwav_bool32 wavResult;
41234 
41235  wavResult = drwav_seek_to_pcm_frame(&pWav->dr, frameIndex);
41236  if (wavResult != DRWAV_TRUE) {
41237  return MA_ERROR;
41238  }
41239 
41240  return MA_SUCCESS;
41241  }
41242  #else
41243  {
41244  /* wav is disabled. Should never hit this since initialization would have failed. */
41246 
41247  (void)frameIndex;
41248 
41249  return MA_NOT_IMPLEMENTED;
41250  }
41251  #endif
41252 }
41253 
41254 MA_API ma_result ma_wav_get_data_format(ma_wav* pWav, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
41255 {
41256  /* Defaults for safety. */
41257  if (pFormat != NULL) {
41258  *pFormat = ma_format_unknown;
41259  }
41260  if (pChannels != NULL) {
41261  *pChannels = 0;
41262  }
41263  if (pSampleRate != NULL) {
41264  *pSampleRate = 0;
41265  }
41266  if (pChannelMap != NULL) {
41267  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
41268  }
41269 
41270  if (pWav == NULL) {
41271  return MA_INVALID_OPERATION;
41272  }
41273 
41274  if (pFormat != NULL) {
41275  *pFormat = pWav->format;
41276  }
41277 
41278  #if !defined(MA_NO_WAV)
41279  {
41280  if (pChannels != NULL) {
41281  *pChannels = pWav->dr.channels;
41282  }
41283 
41284  if (pSampleRate != NULL) {
41285  *pSampleRate = pWav->dr.sampleRate;
41286  }
41287 
41288  if (pChannelMap != NULL) {
41290  }
41291 
41292  return MA_SUCCESS;
41293  }
41294  #else
41295  {
41296  /* wav is disabled. Should never hit this since initialization would have failed. */
41298  return MA_NOT_IMPLEMENTED;
41299  }
41300  #endif
41301 }
41302 
41304 {
41305  if (pCursor == NULL) {
41306  return MA_INVALID_ARGS;
41307  }
41308 
41309  *pCursor = 0; /* Safety. */
41310 
41311  if (pWav == NULL) {
41312  return MA_INVALID_ARGS;
41313  }
41314 
41315  #if !defined(MA_NO_WAV)
41316  {
41317  drwav_result wavResult = drwav_get_cursor_in_pcm_frames(&pWav->dr, pCursor);
41318  if (wavResult != DRWAV_SUCCESS) {
41319  return (ma_result)wavResult; /* dr_wav result codes map to miniaudio's. */
41320  }
41321 
41322  return MA_SUCCESS;
41323  }
41324  #else
41325  {
41326  /* wav is disabled. Should never hit this since initialization would have failed. */
41328  return MA_NOT_IMPLEMENTED;
41329  }
41330  #endif
41331 }
41332 
41334 {
41335  if (pLength == NULL) {
41336  return MA_INVALID_ARGS;
41337  }
41338 
41339  *pLength = 0; /* Safety. */
41340 
41341  if (pWav == NULL) {
41342  return MA_INVALID_ARGS;
41343  }
41344 
41345  #if !defined(MA_NO_WAV)
41346  {
41347  drwav_result wavResult = drwav_get_length_in_pcm_frames(&pWav->dr, pLength);
41348  if (wavResult != DRWAV_SUCCESS) {
41349  return (ma_result)wavResult; /* dr_wav result codes map to miniaudio's. */
41350  }
41351 
41352  return MA_SUCCESS;
41353  }
41354  #else
41355  {
41356  /* wav is disabled. Should never hit this since initialization would have failed. */
41358  return MA_NOT_IMPLEMENTED;
41359  }
41360  #endif
41361 }
41362 
41363 
41364 static ma_result ma_decoding_backend_init__wav(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
41365 {
41366  ma_result result;
41367  ma_wav* pWav;
41368 
41369  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
41370 
41371  /* For now we're just allocating the decoder backend on the heap. */
41372  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
41373  if (pWav == NULL) {
41374  return MA_OUT_OF_MEMORY;
41375  }
41376 
41377  result = ma_wav_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pWav);
41378  if (result != MA_SUCCESS) {
41379  ma_free(pWav, pAllocationCallbacks);
41380  return result;
41381  }
41382 
41383  *ppBackend = pWav;
41384 
41385  return MA_SUCCESS;
41386 }
41387 
41388 static ma_result ma_decoding_backend_init_file__wav(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
41389 {
41390  ma_result result;
41391  ma_wav* pWav;
41392 
41393  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
41394 
41395  /* For now we're just allocating the decoder backend on the heap. */
41396  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
41397  if (pWav == NULL) {
41398  return MA_OUT_OF_MEMORY;
41399  }
41400 
41401  result = ma_wav_init_file(pFilePath, pConfig, pAllocationCallbacks, pWav);
41402  if (result != MA_SUCCESS) {
41403  ma_free(pWav, pAllocationCallbacks);
41404  return result;
41405  }
41406 
41407  *ppBackend = pWav;
41408 
41409  return MA_SUCCESS;
41410 }
41411 
41412 static ma_result ma_decoding_backend_init_file_w__wav(void* pUserData, const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
41413 {
41414  ma_result result;
41415  ma_wav* pWav;
41416 
41417  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
41418 
41419  /* For now we're just allocating the decoder backend on the heap. */
41420  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
41421  if (pWav == NULL) {
41422  return MA_OUT_OF_MEMORY;
41423  }
41424 
41425  result = ma_wav_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pWav);
41426  if (result != MA_SUCCESS) {
41427  ma_free(pWav, pAllocationCallbacks);
41428  return result;
41429  }
41430 
41431  *ppBackend = pWav;
41432 
41433  return MA_SUCCESS;
41434 }
41435 
41436 static ma_result ma_decoding_backend_init_memory__wav(void* pUserData, const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
41437 {
41438  ma_result result;
41439  ma_wav* pWav;
41440 
41441  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
41442 
41443  /* For now we're just allocating the decoder backend on the heap. */
41444  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
41445  if (pWav == NULL) {
41446  return MA_OUT_OF_MEMORY;
41447  }
41448 
41449  result = ma_wav_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pWav);
41450  if (result != MA_SUCCESS) {
41451  ma_free(pWav, pAllocationCallbacks);
41452  return result;
41453  }
41454 
41455  *ppBackend = pWav;
41456 
41457  return MA_SUCCESS;
41458 }
41459 
41460 static void ma_decoding_backend_uninit__wav(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
41461 {
41462  ma_wav* pWav = (ma_wav*)pBackend;
41463 
41464  (void)pUserData;
41465 
41466  ma_wav_uninit(pWav, pAllocationCallbacks);
41467  ma_free(pWav, pAllocationCallbacks);
41468 }
41469 
41470 static ma_result ma_decoding_backend_get_channel_map__wav(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
41471 {
41472  ma_wav* pWav = (ma_wav*)pBackend;
41473 
41474  (void)pUserData;
41475 
41476  return ma_wav_get_data_format(pWav, NULL, NULL, NULL, pChannelMap, channelMapCap);
41477 }
41478 
41480 {
41487 };
41488 
41490 {
41492 }
41493 #endif /* dr_wav_h */
41494 
41495 /* FLAC */
41496 #ifdef dr_flac_h
41497 #define MA_HAS_FLAC
41498 
41499 typedef struct
41500 {
41506  ma_format format; /* Can be f32, s16 or s32. */
41507 #if !defined(MA_NO_FLAC)
41509 #endif
41510 } ma_flac;
41511 
41512 MA_API ma_result ma_flac_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac);
41513 MA_API ma_result ma_flac_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac);
41514 MA_API ma_result ma_flac_init_file_w(const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac);
41515 MA_API ma_result ma_flac_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac);
41516 MA_API void ma_flac_uninit(ma_flac* pFlac, const ma_allocation_callbacks* pAllocationCallbacks);
41517 MA_API ma_result ma_flac_read_pcm_frames(ma_flac* pFlac, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
41519 MA_API ma_result ma_flac_get_data_format(ma_flac* pFlac, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
41522 
41523 
41524 static ma_result ma_flac_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
41525 {
41526  return ma_flac_read_pcm_frames((ma_flac*)pDataSource, pFramesOut, frameCount, pFramesRead);
41527 }
41528 
41529 static ma_result ma_flac_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
41530 {
41531  return ma_flac_seek_to_pcm_frame((ma_flac*)pDataSource, frameIndex);
41532 }
41533 
41534 static ma_result ma_flac_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
41535 {
41536  return ma_flac_get_data_format((ma_flac*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
41537 }
41538 
41540 {
41541  return ma_flac_get_cursor_in_pcm_frames((ma_flac*)pDataSource, pCursor);
41542 }
41543 
41545 {
41546  return ma_flac_get_length_in_pcm_frames((ma_flac*)pDataSource, pLength);
41547 }
41548 
41550 {
41553  NULL, /* onMap() */
41554  NULL, /* onUnmap() */
41558 };
41559 
41560 
41561 #if !defined(MA_NO_FLAC)
41563 {
41564  drflac_allocation_callbacks callbacks;
41565 
41566  if (pAllocationCallbacks != NULL) {
41567  callbacks.onMalloc = pAllocationCallbacks->onMalloc;
41568  callbacks.onRealloc = pAllocationCallbacks->onRealloc;
41569  callbacks.onFree = pAllocationCallbacks->onFree;
41570  callbacks.pUserData = pAllocationCallbacks->pUserData;
41571  } else {
41572  callbacks.onMalloc = ma__malloc_default;
41573  callbacks.onRealloc = ma__realloc_default;
41574  callbacks.onFree = ma__free_default;
41575  callbacks.pUserData = NULL;
41576  }
41577 
41578  return callbacks;
41579 }
41580 
41581 static size_t ma_flac_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
41582 {
41583  ma_flac* pFlac = (ma_flac*)pUserData;
41584  ma_result result;
41585  size_t bytesRead;
41586 
41587  MA_ASSERT(pFlac != NULL);
41588 
41589  result = pFlac->onRead(pFlac->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
41590  (void)result;
41591 
41592  return bytesRead;
41593 }
41594 
41595 static drflac_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, drflac_seek_origin origin)
41596 {
41597  ma_flac* pFlac = (ma_flac*)pUserData;
41598  ma_result result;
41599  ma_seek_origin maSeekOrigin;
41600 
41601  MA_ASSERT(pFlac != NULL);
41602 
41603  maSeekOrigin = ma_seek_origin_start;
41604  if (origin == drflac_seek_origin_current) {
41605  maSeekOrigin = ma_seek_origin_current;
41606  }
41607 
41608  result = pFlac->onSeek(pFlac->pReadSeekTellUserData, offset, maSeekOrigin);
41609  if (result != MA_SUCCESS) {
41610  return MA_FALSE;
41611  }
41612 
41613  return MA_TRUE;
41614 }
41615 #endif
41616 
41618 {
41619  ma_result result;
41620  ma_data_source_config dataSourceConfig;
41621 
41622  if (pFlac == NULL) {
41623  return MA_INVALID_ARGS;
41624  }
41625 
41626  MA_ZERO_OBJECT(pFlac);
41627  pFlac->format = ma_format_f32; /* f32 by default. */
41628 
41629  if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16 || pConfig->preferredFormat == ma_format_s32)) {
41630  pFlac->format = pConfig->preferredFormat;
41631  } else {
41632  /* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
41633  }
41634 
41635  dataSourceConfig = ma_data_source_config_init();
41636  dataSourceConfig.vtable = &g_ma_flac_ds_vtable;
41637 
41638  result = ma_data_source_init(&dataSourceConfig, &pFlac->ds);
41639  if (result != MA_SUCCESS) {
41640  return result; /* Failed to initialize the base data source. */
41641  }
41642 
41643  return MA_SUCCESS;
41644 }
41645 
41646 MA_API ma_result ma_flac_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac)
41647 {
41648  ma_result result;
41649 
41650  result = ma_flac_init_internal(pConfig, pFlac);
41651  if (result != MA_SUCCESS) {
41652  return result;
41653  }
41654 
41655  if (onRead == NULL || onSeek == NULL) {
41656  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
41657  }
41658 
41659  pFlac->onRead = onRead;
41660  pFlac->onSeek = onSeek;
41661  pFlac->onTell = onTell;
41662  pFlac->pReadSeekTellUserData = pReadSeekTellUserData;
41663 
41664  #if !defined(MA_NO_FLAC)
41665  {
41666  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41667 
41668  pFlac->dr = drflac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, pFlac, &flacAllocationCallbacks);
41669  if (pFlac->dr == NULL) {
41670  return MA_INVALID_FILE;
41671  }
41672 
41673  return MA_SUCCESS;
41674  }
41675  #else
41676  {
41677  /* flac is disabled. */
41678  (void)pAllocationCallbacks;
41679  return MA_NOT_IMPLEMENTED;
41680  }
41681  #endif
41682 }
41683 
41684 MA_API ma_result ma_flac_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac)
41685 {
41686  ma_result result;
41687 
41688  result = ma_flac_init_internal(pConfig, pFlac);
41689  if (result != MA_SUCCESS) {
41690  return result;
41691  }
41692 
41693  #if !defined(MA_NO_FLAC)
41694  {
41695  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41696 
41697  pFlac->dr = drflac_open_file(pFilePath, &flacAllocationCallbacks);
41698  if (pFlac->dr == NULL) {
41699  return MA_INVALID_FILE;
41700  }
41701 
41702  return MA_SUCCESS;
41703  }
41704  #else
41705  {
41706  /* flac is disabled. */
41707  (void)pFilePath;
41708  (void)pAllocationCallbacks;
41709  return MA_NOT_IMPLEMENTED;
41710  }
41711  #endif
41712 }
41713 
41714 MA_API ma_result ma_flac_init_file_w(const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac)
41715 {
41716  ma_result result;
41717 
41718  result = ma_flac_init_internal(pConfig, pFlac);
41719  if (result != MA_SUCCESS) {
41720  return result;
41721  }
41722 
41723  #if !defined(MA_NO_FLAC)
41724  {
41725  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41726 
41727  pFlac->dr = drflac_open_file_w(pFilePath, &flacAllocationCallbacks);
41728  if (pFlac->dr == NULL) {
41729  return MA_INVALID_FILE;
41730  }
41731 
41732  return MA_SUCCESS;
41733  }
41734  #else
41735  {
41736  /* flac is disabled. */
41737  (void)pFilePath;
41738  (void)pAllocationCallbacks;
41739  return MA_NOT_IMPLEMENTED;
41740  }
41741  #endif
41742 }
41743 
41744 MA_API ma_result ma_flac_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_flac* pFlac)
41745 {
41746  ma_result result;
41747 
41748  result = ma_flac_init_internal(pConfig, pFlac);
41749  if (result != MA_SUCCESS) {
41750  return result;
41751  }
41752 
41753  #if !defined(MA_NO_FLAC)
41754  {
41755  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
41756 
41757  pFlac->dr = drflac_open_memory(pData, dataSize, &flacAllocationCallbacks);
41758  if (pFlac->dr == NULL) {
41759  return MA_INVALID_FILE;
41760  }
41761 
41762  return MA_SUCCESS;
41763  }
41764  #else
41765  {
41766  /* flac is disabled. */
41767  (void)pData;
41768  (void)dataSize;
41769  (void)pAllocationCallbacks;
41770  return MA_NOT_IMPLEMENTED;
41771  }
41772  #endif
41773 }
41774 
41775 MA_API void ma_flac_uninit(ma_flac* pFlac, const ma_allocation_callbacks* pAllocationCallbacks)
41776 {
41777  if (pFlac == NULL) {
41778  return;
41779  }
41780 
41781  (void)pAllocationCallbacks;
41782 
41783  #if !defined(MA_NO_FLAC)
41784  {
41785  drflac_close(pFlac->dr);
41786  }
41787  #else
41788  {
41789  /* flac is disabled. Should never hit this since initialization would have failed. */
41791  }
41792  #endif
41793 
41794  ma_data_source_uninit(&pFlac->ds);
41795 }
41796 
41797 MA_API ma_result ma_flac_read_pcm_frames(ma_flac* pFlac, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
41798 {
41799  if (pFlac == NULL) {
41800  return MA_INVALID_ARGS;
41801  }
41802 
41803  #if !defined(MA_NO_FLAC)
41804  {
41805  /* We always use floating point format. */
41806  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
41807  ma_uint64 totalFramesRead = 0;
41808  ma_format format;
41809 
41810  ma_flac_get_data_format(pFlac, &format, NULL, NULL, NULL, 0);
41811 
41812  switch (format)
41813  {
41814  case ma_format_f32:
41815  {
41816  totalFramesRead = drflac_read_pcm_frames_f32(pFlac->dr, frameCount, (float*)pFramesOut);
41817  } break;
41818 
41819  case ma_format_s16:
41820  {
41821  totalFramesRead = drflac_read_pcm_frames_s16(pFlac->dr, frameCount, (drflac_int16*)pFramesOut);
41822  } break;
41823 
41824  case ma_format_s32:
41825  {
41826  totalFramesRead = drflac_read_pcm_frames_s32(pFlac->dr, frameCount, (drflac_int32*)pFramesOut);
41827  } break;
41828 
41829  case ma_format_u8:
41830  case ma_format_s24:
41831  case ma_format_unknown:
41832  default:
41833  {
41834  return MA_INVALID_OPERATION;
41835  };
41836  }
41837 
41838  /* In the future we'll update dr_flac to return MA_AT_END for us. */
41839  if (totalFramesRead == 0) {
41840  result = MA_AT_END;
41841  }
41842 
41843  if (pFramesRead != NULL) {
41844  *pFramesRead = totalFramesRead;
41845  }
41846 
41847  return result;
41848  }
41849  #else
41850  {
41851  /* flac is disabled. Should never hit this since initialization would have failed. */
41853 
41854  (void)pFramesOut;
41855  (void)frameCount;
41856  (void)pFramesRead;
41857 
41858  return MA_NOT_IMPLEMENTED;
41859  }
41860  #endif
41861 }
41862 
41864 {
41865  if (pFlac == NULL) {
41866  return MA_INVALID_ARGS;
41867  }
41868 
41869  #if !defined(MA_NO_FLAC)
41870  {
41871  drflac_bool32 flacResult;
41872 
41873  flacResult = drflac_seek_to_pcm_frame(pFlac->dr, frameIndex);
41874  if (flacResult != DRFLAC_TRUE) {
41875  return MA_ERROR;
41876  }
41877 
41878  return MA_SUCCESS;
41879  }
41880  #else
41881  {
41882  /* flac is disabled. Should never hit this since initialization would have failed. */
41884 
41885  (void)frameIndex;
41886 
41887  return MA_NOT_IMPLEMENTED;
41888  }
41889  #endif
41890 }
41891 
41892 MA_API ma_result ma_flac_get_data_format(ma_flac* pFlac, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
41893 {
41894  /* Defaults for safety. */
41895  if (pFormat != NULL) {
41896  *pFormat = ma_format_unknown;
41897  }
41898  if (pChannels != NULL) {
41899  *pChannels = 0;
41900  }
41901  if (pSampleRate != NULL) {
41902  *pSampleRate = 0;
41903  }
41904  if (pChannelMap != NULL) {
41905  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
41906  }
41907 
41908  if (pFlac == NULL) {
41909  return MA_INVALID_OPERATION;
41910  }
41911 
41912  if (pFormat != NULL) {
41913  *pFormat = pFlac->format;
41914  }
41915 
41916  #if !defined(MA_NO_FLAC)
41917  {
41918  if (pChannels != NULL) {
41919  *pChannels = pFlac->dr->channels;
41920  }
41921 
41922  if (pSampleRate != NULL) {
41923  *pSampleRate = pFlac->dr->sampleRate;
41924  }
41925 
41926  if (pChannelMap != NULL) {
41928  }
41929 
41930  return MA_SUCCESS;
41931  }
41932  #else
41933  {
41934  /* flac is disabled. Should never hit this since initialization would have failed. */
41936  return MA_NOT_IMPLEMENTED;
41937  }
41938  #endif
41939 }
41940 
41942 {
41943  if (pCursor == NULL) {
41944  return MA_INVALID_ARGS;
41945  }
41946 
41947  *pCursor = 0; /* Safety. */
41948 
41949  if (pFlac == NULL) {
41950  return MA_INVALID_ARGS;
41951  }
41952 
41953  #if !defined(MA_NO_FLAC)
41954  {
41955  *pCursor = pFlac->dr->currentPCMFrame;
41956 
41957  return MA_SUCCESS;
41958  }
41959  #else
41960  {
41961  /* flac is disabled. Should never hit this since initialization would have failed. */
41963  return MA_NOT_IMPLEMENTED;
41964  }
41965  #endif
41966 }
41967 
41969 {
41970  if (pLength == NULL) {
41971  return MA_INVALID_ARGS;
41972  }
41973 
41974  *pLength = 0; /* Safety. */
41975 
41976  if (pFlac == NULL) {
41977  return MA_INVALID_ARGS;
41978  }
41979 
41980  #if !defined(MA_NO_FLAC)
41981  {
41982  *pLength = pFlac->dr->totalPCMFrameCount;
41983 
41984  return MA_SUCCESS;
41985  }
41986  #else
41987  {
41988  /* flac is disabled. Should never hit this since initialization would have failed. */
41990  return MA_NOT_IMPLEMENTED;
41991  }
41992  #endif
41993 }
41994 
41995 
41996 static ma_result ma_decoding_backend_init__flac(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
41997 {
41998  ma_result result;
41999  ma_flac* pFlac;
42000 
42001  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42002 
42003  /* For now we're just allocating the decoder backend on the heap. */
42004  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
42005  if (pFlac == NULL) {
42006  return MA_OUT_OF_MEMORY;
42007  }
42008 
42009  result = ma_flac_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pFlac);
42010  if (result != MA_SUCCESS) {
42011  ma_free(pFlac, pAllocationCallbacks);
42012  return result;
42013  }
42014 
42015  *ppBackend = pFlac;
42016 
42017  return MA_SUCCESS;
42018 }
42019 
42020 static ma_result ma_decoding_backend_init_file__flac(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42021 {
42022  ma_result result;
42023  ma_flac* pFlac;
42024 
42025  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42026 
42027  /* For now we're just allocating the decoder backend on the heap. */
42028  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
42029  if (pFlac == NULL) {
42030  return MA_OUT_OF_MEMORY;
42031  }
42032 
42033  result = ma_flac_init_file(pFilePath, pConfig, pAllocationCallbacks, pFlac);
42034  if (result != MA_SUCCESS) {
42035  ma_free(pFlac, pAllocationCallbacks);
42036  return result;
42037  }
42038 
42039  *ppBackend = pFlac;
42040 
42041  return MA_SUCCESS;
42042 }
42043 
42044 static ma_result ma_decoding_backend_init_file_w__flac(void* pUserData, const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42045 {
42046  ma_result result;
42047  ma_flac* pFlac;
42048 
42049  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42050 
42051  /* For now we're just allocating the decoder backend on the heap. */
42052  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
42053  if (pFlac == NULL) {
42054  return MA_OUT_OF_MEMORY;
42055  }
42056 
42057  result = ma_flac_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pFlac);
42058  if (result != MA_SUCCESS) {
42059  ma_free(pFlac, pAllocationCallbacks);
42060  return result;
42061  }
42062 
42063  *ppBackend = pFlac;
42064 
42065  return MA_SUCCESS;
42066 }
42067 
42068 static ma_result ma_decoding_backend_init_memory__flac(void* pUserData, const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42069 {
42070  ma_result result;
42071  ma_flac* pFlac;
42072 
42073  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42074 
42075  /* For now we're just allocating the decoder backend on the heap. */
42076  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
42077  if (pFlac == NULL) {
42078  return MA_OUT_OF_MEMORY;
42079  }
42080 
42081  result = ma_flac_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pFlac);
42082  if (result != MA_SUCCESS) {
42083  ma_free(pFlac, pAllocationCallbacks);
42084  return result;
42085  }
42086 
42087  *ppBackend = pFlac;
42088 
42089  return MA_SUCCESS;
42090 }
42091 
42092 static void ma_decoding_backend_uninit__flac(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
42093 {
42094  ma_flac* pFlac = (ma_flac*)pBackend;
42095 
42096  (void)pUserData;
42097 
42098  ma_flac_uninit(pFlac, pAllocationCallbacks);
42099  ma_free(pFlac, pAllocationCallbacks);
42100 }
42101 
42102 static ma_result ma_decoding_backend_get_channel_map__flac(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
42103 {
42104  ma_flac* pFlac = (ma_flac*)pBackend;
42105 
42106  (void)pUserData;
42107 
42108  return ma_flac_get_data_format(pFlac, NULL, NULL, NULL, pChannelMap, channelMapCap);
42109 }
42110 
42112 {
42119 };
42120 
42122 {
42124 }
42125 #endif /* dr_flac_h */
42126 
42127 /* MP3 */
42128 #ifdef dr_mp3_h
42129 #define MA_HAS_MP3
42130 
42131 typedef struct
42132 {
42138  ma_format format; /* Can be f32 or s16. */
42139 #if !defined(MA_NO_MP3)
42141 #endif
42142 } ma_mp3;
42143 
42144 MA_API ma_result ma_mp3_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3);
42145 MA_API ma_result ma_mp3_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3);
42146 MA_API ma_result ma_mp3_init_file_w(const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3);
42147 MA_API ma_result ma_mp3_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3);
42148 MA_API void ma_mp3_uninit(ma_mp3* pMP3, const ma_allocation_callbacks* pAllocationCallbacks);
42149 MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3* pMP3, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
42151 MA_API ma_result ma_mp3_get_data_format(ma_mp3* pMP3, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
42154 
42155 
42156 static ma_result ma_mp3_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
42157 {
42158  return ma_mp3_read_pcm_frames((ma_mp3*)pDataSource, pFramesOut, frameCount, pFramesRead);
42159 }
42160 
42161 static ma_result ma_mp3_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
42162 {
42163  return ma_mp3_seek_to_pcm_frame((ma_mp3*)pDataSource, frameIndex);
42164 }
42165 
42166 static ma_result ma_mp3_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
42167 {
42168  return ma_mp3_get_data_format((ma_mp3*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
42169 }
42170 
42172 {
42173  return ma_mp3_get_cursor_in_pcm_frames((ma_mp3*)pDataSource, pCursor);
42174 }
42175 
42177 {
42178  return ma_mp3_get_length_in_pcm_frames((ma_mp3*)pDataSource, pLength);
42179 }
42180 
42182 {
42185  NULL, /* onMap() */
42186  NULL, /* onUnmap() */
42190 };
42191 
42192 
42193 #if !defined(MA_NO_MP3)
42195 {
42196  drmp3_allocation_callbacks callbacks;
42197 
42198  if (pAllocationCallbacks != NULL) {
42199  callbacks.onMalloc = pAllocationCallbacks->onMalloc;
42200  callbacks.onRealloc = pAllocationCallbacks->onRealloc;
42201  callbacks.onFree = pAllocationCallbacks->onFree;
42202  callbacks.pUserData = pAllocationCallbacks->pUserData;
42203  } else {
42204  callbacks.onMalloc = ma__malloc_default;
42205  callbacks.onRealloc = ma__realloc_default;
42206  callbacks.onFree = ma__free_default;
42207  callbacks.pUserData = NULL;
42208  }
42209 
42210  return callbacks;
42211 }
42212 
42213 static size_t ma_mp3_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
42214 {
42215  ma_mp3* pMP3 = (ma_mp3*)pUserData;
42216  ma_result result;
42217  size_t bytesRead;
42218 
42219  MA_ASSERT(pMP3 != NULL);
42220 
42221  result = pMP3->onRead(pMP3->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
42222  (void)result;
42223 
42224  return bytesRead;
42225 }
42226 
42227 static drmp3_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, drmp3_seek_origin origin)
42228 {
42229  ma_mp3* pMP3 = (ma_mp3*)pUserData;
42230  ma_result result;
42231  ma_seek_origin maSeekOrigin;
42232 
42233  MA_ASSERT(pMP3 != NULL);
42234 
42235  maSeekOrigin = ma_seek_origin_start;
42236  if (origin == drmp3_seek_origin_current) {
42237  maSeekOrigin = ma_seek_origin_current;
42238  }
42239 
42240  result = pMP3->onSeek(pMP3->pReadSeekTellUserData, offset, maSeekOrigin);
42241  if (result != MA_SUCCESS) {
42242  return MA_FALSE;
42243  }
42244 
42245  return MA_TRUE;
42246 }
42247 #endif
42248 
42250 {
42251  ma_result result;
42252  ma_data_source_config dataSourceConfig;
42253 
42254  if (pMP3 == NULL) {
42255  return MA_INVALID_ARGS;
42256  }
42257 
42258  MA_ZERO_OBJECT(pMP3);
42259  pMP3->format = ma_format_f32; /* f32 by default. */
42260 
42261  if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16)) {
42262  pMP3->format = pConfig->preferredFormat;
42263  } else {
42264  /* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
42265  }
42266 
42267  dataSourceConfig = ma_data_source_config_init();
42268  dataSourceConfig.vtable = &g_ma_mp3_ds_vtable;
42269 
42270  result = ma_data_source_init(&dataSourceConfig, &pMP3->ds);
42271  if (result != MA_SUCCESS) {
42272  return result; /* Failed to initialize the base data source. */
42273  }
42274 
42275  return MA_SUCCESS;
42276 }
42277 
42278 MA_API ma_result ma_mp3_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3)
42279 {
42280  ma_result result;
42281 
42282  result = ma_mp3_init_internal(pConfig, pMP3);
42283  if (result != MA_SUCCESS) {
42284  return result;
42285  }
42286 
42287  if (onRead == NULL || onSeek == NULL) {
42288  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
42289  }
42290 
42291  pMP3->onRead = onRead;
42292  pMP3->onSeek = onSeek;
42293  pMP3->onTell = onTell;
42294  pMP3->pReadSeekTellUserData = pReadSeekTellUserData;
42295 
42296  #if !defined(MA_NO_MP3)
42297  {
42298  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
42299  drmp3_bool32 mp3Result;
42300 
42301  mp3Result = drmp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, pMP3, &mp3AllocationCallbacks);
42302  if (mp3Result != MA_TRUE) {
42303  return MA_INVALID_FILE;
42304  }
42305 
42306  return MA_SUCCESS;
42307  }
42308  #else
42309  {
42310  /* mp3 is disabled. */
42311  (void)pAllocationCallbacks;
42312  return MA_NOT_IMPLEMENTED;
42313  }
42314  #endif
42315 }
42316 
42317 MA_API ma_result ma_mp3_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3)
42318 {
42319  ma_result result;
42320 
42321  result = ma_mp3_init_internal(pConfig, pMP3);
42322  if (result != MA_SUCCESS) {
42323  return result;
42324  }
42325 
42326  #if !defined(MA_NO_MP3)
42327  {
42328  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
42329  drmp3_bool32 mp3Result;
42330 
42331  mp3Result = drmp3_init_file(&pMP3->dr, pFilePath, &mp3AllocationCallbacks);
42332  if (mp3Result != MA_TRUE) {
42333  return MA_INVALID_FILE;
42334  }
42335 
42336  return MA_SUCCESS;
42337  }
42338  #else
42339  {
42340  /* mp3 is disabled. */
42341  (void)pFilePath;
42342  (void)pAllocationCallbacks;
42343  return MA_NOT_IMPLEMENTED;
42344  }
42345  #endif
42346 }
42347 
42348 MA_API ma_result ma_mp3_init_file_w(const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3)
42349 {
42350  ma_result result;
42351 
42352  result = ma_mp3_init_internal(pConfig, pMP3);
42353  if (result != MA_SUCCESS) {
42354  return result;
42355  }
42356 
42357  #if !defined(MA_NO_MP3)
42358  {
42359  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
42360  drmp3_bool32 mp3Result;
42361 
42362  mp3Result = drmp3_init_file_w(&pMP3->dr, pFilePath, &mp3AllocationCallbacks);
42363  if (mp3Result != MA_TRUE) {
42364  return MA_INVALID_FILE;
42365  }
42366 
42367  return MA_SUCCESS;
42368  }
42369  #else
42370  {
42371  /* mp3 is disabled. */
42372  (void)pFilePath;
42373  (void)pAllocationCallbacks;
42374  return MA_NOT_IMPLEMENTED;
42375  }
42376  #endif
42377 }
42378 
42379 MA_API ma_result ma_mp3_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_mp3* pMP3)
42380 {
42381  ma_result result;
42382 
42383  result = ma_mp3_init_internal(pConfig, pMP3);
42384  if (result != MA_SUCCESS) {
42385  return result;
42386  }
42387 
42388  #if !defined(MA_NO_MP3)
42389  {
42390  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
42391  drmp3_bool32 mp3Result;
42392 
42393  mp3Result = drmp3_init_memory(&pMP3->dr, pData, dataSize, &mp3AllocationCallbacks);
42394  if (mp3Result != MA_TRUE) {
42395  return MA_INVALID_FILE;
42396  }
42397 
42398  return MA_SUCCESS;
42399  }
42400  #else
42401  {
42402  /* mp3 is disabled. */
42403  (void)pData;
42404  (void)dataSize;
42405  (void)pAllocationCallbacks;
42406  return MA_NOT_IMPLEMENTED;
42407  }
42408  #endif
42409 }
42410 
42411 MA_API void ma_mp3_uninit(ma_mp3* pMP3, const ma_allocation_callbacks* pAllocationCallbacks)
42412 {
42413  if (pMP3 == NULL) {
42414  return;
42415  }
42416 
42417  (void)pAllocationCallbacks;
42418 
42419  #if !defined(MA_NO_MP3)
42420  {
42421  drmp3_uninit(&pMP3->dr);
42422  }
42423  #else
42424  {
42425  /* mp3 is disabled. Should never hit this since initialization would have failed. */
42427  }
42428  #endif
42429 
42430  ma_data_source_uninit(&pMP3->ds);
42431 }
42432 
42433 MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3* pMP3, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
42434 {
42435  if (pMP3 == NULL) {
42436  return MA_INVALID_ARGS;
42437  }
42438 
42439  #if !defined(MA_NO_MP3)
42440  {
42441  /* We always use floating point format. */
42442  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
42443  ma_uint64 totalFramesRead = 0;
42444  ma_format format;
42445 
42446  ma_mp3_get_data_format(pMP3, &format, NULL, NULL, NULL, 0);
42447 
42448  switch (format)
42449  {
42450  case ma_format_f32:
42451  {
42452  totalFramesRead = drmp3_read_pcm_frames_f32(&pMP3->dr, frameCount, (float*)pFramesOut);
42453  } break;
42454 
42455  case ma_format_s16:
42456  {
42457  totalFramesRead = drmp3_read_pcm_frames_s16(&pMP3->dr, frameCount, (drmp3_int16*)pFramesOut);
42458  } break;
42459 
42460  case ma_format_u8:
42461  case ma_format_s24:
42462  case ma_format_s32:
42463  case ma_format_unknown:
42464  default:
42465  {
42466  return MA_INVALID_OPERATION;
42467  };
42468  }
42469 
42470  /* In the future we'll update dr_mp3 to return MA_AT_END for us. */
42471  if (totalFramesRead == 0) {
42472  result = MA_AT_END;
42473  }
42474 
42475  if (pFramesRead != NULL) {
42476  *pFramesRead = totalFramesRead;
42477  }
42478 
42479  return result;
42480  }
42481  #else
42482  {
42483  /* mp3 is disabled. Should never hit this since initialization would have failed. */
42485 
42486  (void)pFramesOut;
42487  (void)frameCount;
42488  (void)pFramesRead;
42489 
42490  return MA_NOT_IMPLEMENTED;
42491  }
42492  #endif
42493 }
42494 
42496 {
42497  if (pMP3 == NULL) {
42498  return MA_INVALID_ARGS;
42499  }
42500 
42501  #if !defined(MA_NO_MP3)
42502  {
42503  drmp3_bool32 mp3Result;
42504 
42505  mp3Result = drmp3_seek_to_pcm_frame(&pMP3->dr, frameIndex);
42506  if (mp3Result != DRMP3_TRUE) {
42507  return MA_ERROR;
42508  }
42509 
42510  return MA_SUCCESS;
42511  }
42512  #else
42513  {
42514  /* mp3 is disabled. Should never hit this since initialization would have failed. */
42516 
42517  (void)frameIndex;
42518 
42519  return MA_NOT_IMPLEMENTED;
42520  }
42521  #endif
42522 }
42523 
42524 MA_API ma_result ma_mp3_get_data_format(ma_mp3* pMP3, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
42525 {
42526  /* Defaults for safety. */
42527  if (pFormat != NULL) {
42528  *pFormat = ma_format_unknown;
42529  }
42530  if (pChannels != NULL) {
42531  *pChannels = 0;
42532  }
42533  if (pSampleRate != NULL) {
42534  *pSampleRate = 0;
42535  }
42536  if (pChannelMap != NULL) {
42537  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
42538  }
42539 
42540  if (pMP3 == NULL) {
42541  return MA_INVALID_OPERATION;
42542  }
42543 
42544  if (pFormat != NULL) {
42545  *pFormat = pMP3->format;
42546  }
42547 
42548  #if !defined(MA_NO_MP3)
42549  {
42550  if (pChannels != NULL) {
42551  *pChannels = pMP3->dr.channels;
42552  }
42553 
42554  if (pSampleRate != NULL) {
42555  *pSampleRate = pMP3->dr.sampleRate;
42556  }
42557 
42558  if (pChannelMap != NULL) {
42560  }
42561 
42562  return MA_SUCCESS;
42563  }
42564  #else
42565  {
42566  /* mp3 is disabled. Should never hit this since initialization would have failed. */
42568  return MA_NOT_IMPLEMENTED;
42569  }
42570  #endif
42571 }
42572 
42574 {
42575  if (pCursor == NULL) {
42576  return MA_INVALID_ARGS;
42577  }
42578 
42579  *pCursor = 0; /* Safety. */
42580 
42581  if (pMP3 == NULL) {
42582  return MA_INVALID_ARGS;
42583  }
42584 
42585  #if !defined(MA_NO_MP3)
42586  {
42587  *pCursor = pMP3->dr.currentPCMFrame;
42588 
42589  return MA_SUCCESS;
42590  }
42591  #else
42592  {
42593  /* mp3 is disabled. Should never hit this since initialization would have failed. */
42595  return MA_NOT_IMPLEMENTED;
42596  }
42597  #endif
42598 }
42599 
42601 {
42602  if (pLength == NULL) {
42603  return MA_INVALID_ARGS;
42604  }
42605 
42606  *pLength = 0; /* Safety. */
42607 
42608  if (pMP3 == NULL) {
42609  return MA_INVALID_ARGS;
42610  }
42611 
42612  #if !defined(MA_NO_MP3)
42613  {
42614  *pLength = drmp3_get_pcm_frame_count(&pMP3->dr);
42615 
42616  return MA_SUCCESS;
42617  }
42618  #else
42619  {
42620  /* mp3 is disabled. Should never hit this since initialization would have failed. */
42622  return MA_NOT_IMPLEMENTED;
42623  }
42624  #endif
42625 }
42626 
42627 
42628 static ma_result ma_decoding_backend_init__mp3(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42629 {
42630  ma_result result;
42631  ma_mp3* pMP3;
42632 
42633  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42634 
42635  /* For now we're just allocating the decoder backend on the heap. */
42636  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
42637  if (pMP3 == NULL) {
42638  return MA_OUT_OF_MEMORY;
42639  }
42640 
42641  result = ma_mp3_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pMP3);
42642  if (result != MA_SUCCESS) {
42643  ma_free(pMP3, pAllocationCallbacks);
42644  return result;
42645  }
42646 
42647  *ppBackend = pMP3;
42648 
42649  return MA_SUCCESS;
42650 }
42651 
42652 static ma_result ma_decoding_backend_init_file__mp3(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42653 {
42654  ma_result result;
42655  ma_mp3* pMP3;
42656 
42657  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42658 
42659  /* For now we're just allocating the decoder backend on the heap. */
42660  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
42661  if (pMP3 == NULL) {
42662  return MA_OUT_OF_MEMORY;
42663  }
42664 
42665  result = ma_mp3_init_file(pFilePath, pConfig, pAllocationCallbacks, pMP3);
42666  if (result != MA_SUCCESS) {
42667  ma_free(pMP3, pAllocationCallbacks);
42668  return result;
42669  }
42670 
42671  *ppBackend = pMP3;
42672 
42673  return MA_SUCCESS;
42674 }
42675 
42676 static ma_result ma_decoding_backend_init_file_w__mp3(void* pUserData, const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42677 {
42678  ma_result result;
42679  ma_mp3* pMP3;
42680 
42681  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42682 
42683  /* For now we're just allocating the decoder backend on the heap. */
42684  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
42685  if (pMP3 == NULL) {
42686  return MA_OUT_OF_MEMORY;
42687  }
42688 
42689  result = ma_mp3_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pMP3);
42690  if (result != MA_SUCCESS) {
42691  ma_free(pMP3, pAllocationCallbacks);
42692  return result;
42693  }
42694 
42695  *ppBackend = pMP3;
42696 
42697  return MA_SUCCESS;
42698 }
42699 
42700 static ma_result ma_decoding_backend_init_memory__mp3(void* pUserData, const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
42701 {
42702  ma_result result;
42703  ma_mp3* pMP3;
42704 
42705  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
42706 
42707  /* For now we're just allocating the decoder backend on the heap. */
42708  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
42709  if (pMP3 == NULL) {
42710  return MA_OUT_OF_MEMORY;
42711  }
42712 
42713  result = ma_mp3_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pMP3);
42714  if (result != MA_SUCCESS) {
42715  ma_free(pMP3, pAllocationCallbacks);
42716  return result;
42717  }
42718 
42719  *ppBackend = pMP3;
42720 
42721  return MA_SUCCESS;
42722 }
42723 
42724 static void ma_decoding_backend_uninit__mp3(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
42725 {
42726  ma_mp3* pMP3 = (ma_mp3*)pBackend;
42727 
42728  (void)pUserData;
42729 
42730  ma_mp3_uninit(pMP3, pAllocationCallbacks);
42731  ma_free(pMP3, pAllocationCallbacks);
42732 }
42733 
42734 static ma_result ma_decoding_backend_get_channel_map__mp3(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
42735 {
42736  ma_mp3* pMP3 = (ma_mp3*)pBackend;
42737 
42738  (void)pUserData;
42739 
42740  return ma_mp3_get_data_format(pMP3, NULL, NULL, NULL, pChannelMap, channelMapCap);
42741 }
42742 
42744 {
42751 };
42752 
42754 {
42756 }
42757 #endif /* dr_mp3_h */
42758 
42759 /* Vorbis */
42760 #ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
42761 #define MA_HAS_VORBIS
42762 
42763 /* The size in bytes of each chunk of data to read from the Vorbis stream. */
42764 #define MA_VORBIS_DATA_CHUNK_SIZE 4096
42765 
42766 typedef struct
42767 {
42769  ma_read_proc onRead;
42770  ma_seek_proc onSeek;
42771  ma_tell_proc onTell;
42772  void* pReadSeekTellUserData;
42773  ma_allocation_callbacks allocationCallbacks; /* Store the allocation callbacks within the structure because we may need to dynamically expand a buffer in ma_stbvorbis_read_pcm_frames() when using push mode. */
42774  ma_format format; /* Only f32 is allowed with stb_vorbis. */
42775  ma_uint32 channels;
42776  ma_uint32 sampleRate;
42777  ma_uint64 cursor;
42778 #if !defined(MA_NO_VORBIS)
42779  stb_vorbis* stb;
42780  ma_bool32 usingPushMode;
42781  struct
42782  {
42783  ma_uint8* pData;
42784  size_t dataSize;
42785  size_t dataCapacity;
42786  ma_uint32 framesConsumed; /* The number of frames consumed in ppPacketData. */
42787  ma_uint32 framesRemaining; /* The number of frames remaining in ppPacketData. */
42788  float** ppPacketData;
42789  } push;
42790 #endif
42791 } ma_stbvorbis;
42792 
42793 MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis);
42794 MA_API ma_result ma_stbvorbis_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis);
42795 MA_API ma_result ma_stbvorbis_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis);
42796 MA_API void ma_stbvorbis_uninit(ma_stbvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks);
42797 MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
42798 MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64 frameIndex);
42799 MA_API ma_result ma_stbvorbis_get_data_format(ma_stbvorbis* pVorbis, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
42800 MA_API ma_result ma_stbvorbis_get_cursor_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pCursor);
42801 MA_API ma_result ma_stbvorbis_get_length_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pLength);
42802 
42803 
42804 static ma_result ma_stbvorbis_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
42805 {
42806  return ma_stbvorbis_read_pcm_frames((ma_stbvorbis*)pDataSource, pFramesOut, frameCount, pFramesRead);
42807 }
42808 
42809 static ma_result ma_stbvorbis_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
42810 {
42811  return ma_stbvorbis_seek_to_pcm_frame((ma_stbvorbis*)pDataSource, frameIndex);
42812 }
42813 
42814 static ma_result ma_stbvorbis_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
42815 {
42816  return ma_stbvorbis_get_data_format((ma_stbvorbis*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
42817 }
42818 
42819 static ma_result ma_stbvorbis_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
42820 {
42821  return ma_stbvorbis_get_cursor_in_pcm_frames((ma_stbvorbis*)pDataSource, pCursor);
42822 }
42823 
42824 static ma_result ma_stbvorbis_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
42825 {
42826  return ma_stbvorbis_get_length_in_pcm_frames((ma_stbvorbis*)pDataSource, pLength);
42827 }
42828 
42829 static ma_data_source_vtable g_ma_stbvorbis_ds_vtable =
42830 {
42831  ma_stbvorbis_ds_read,
42832  ma_stbvorbis_ds_seek,
42833  NULL, /* onMap() */
42834  NULL, /* onUnmap() */
42835  ma_stbvorbis_ds_get_data_format,
42836  ma_stbvorbis_ds_get_cursor,
42837  ma_stbvorbis_ds_get_length
42838 };
42839 
42840 
42841 static ma_result ma_stbvorbis_init_internal(const ma_decoding_backend_config* pConfig, ma_stbvorbis* pVorbis)
42842 {
42843  ma_result result;
42844  ma_data_source_config dataSourceConfig;
42845 
42846  (void)pConfig;
42847 
42848  if (pVorbis == NULL) {
42849  return MA_INVALID_ARGS;
42850  }
42851 
42852  MA_ZERO_OBJECT(pVorbis);
42853  pVorbis->format = ma_format_f32; /* Only supporting f32. */
42854 
42855  dataSourceConfig = ma_data_source_config_init();
42856  dataSourceConfig.vtable = &g_ma_stbvorbis_ds_vtable;
42857 
42858  result = ma_data_source_init(&dataSourceConfig, &pVorbis->ds);
42859  if (result != MA_SUCCESS) {
42860  return result; /* Failed to initialize the base data source. */
42861  }
42862 
42863  return MA_SUCCESS;
42864 }
42865 
42866 #if !defined(MA_NO_VORBIS)
42867 static ma_result ma_stbvorbis_post_init(ma_stbvorbis* pVorbis)
42868 {
42869  stb_vorbis_info info;
42870 
42871  MA_ASSERT(pVorbis != NULL);
42872 
42873  info = stb_vorbis_get_info(pVorbis->stb);
42874 
42875  pVorbis->channels = info.channels;
42876  pVorbis->sampleRate = info.sample_rate;
42877 
42878  return MA_SUCCESS;
42879 }
42880 #endif
42881 
42882 MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis)
42883 {
42884  ma_result result;
42885 
42886  result = ma_stbvorbis_init_internal(pConfig, pVorbis);
42887  if (result != MA_SUCCESS) {
42888  return result;
42889  }
42890 
42891  if (onRead == NULL || onSeek == NULL) {
42892  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
42893  }
42894 
42895  pVorbis->onRead = onRead;
42896  pVorbis->onSeek = onSeek;
42897  pVorbis->onTell = onTell;
42898  pVorbis->pReadSeekTellUserData = pReadSeekTellUserData;
42899  ma_allocation_callbacks_init_copy(&pVorbis->allocationCallbacks, pAllocationCallbacks);
42900 
42901  #if !defined(MA_NO_VORBIS)
42902  {
42903  /*
42904  stb_vorbis lacks a callback based API for it's pulling API which means we're stuck with the
42905  pushing API. In order for us to be able to successfully initialize the decoder we need to
42906  supply it with enough data. We need to keep loading data until we have enough.
42907  */
42908  stb_vorbis* stb;
42909  size_t dataSize = 0;
42910  size_t dataCapacity = 0;
42911  ma_uint8* pData = NULL; /* <-- Must be initialized to NULL. */
42912 
42913  for (;;) {
42914  int vorbisError;
42915  int consumedDataSize; /* <-- Fill by stb_vorbis_open_pushdata(). */
42916  size_t bytesRead;
42917  ma_uint8* pNewData;
42918 
42919  /* Allocate memory for the new chunk. */
42920  dataCapacity += MA_VORBIS_DATA_CHUNK_SIZE;
42921  pNewData = (ma_uint8*)ma_realloc(pData, dataCapacity, pAllocationCallbacks);
42922  if (pNewData == NULL) {
42923  ma_free(pData, pAllocationCallbacks);
42924  return MA_OUT_OF_MEMORY;
42925  }
42926 
42927  pData = pNewData;
42928 
42929  /* Read in the next chunk. */
42930  result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, ma_offset_ptr(pData, dataSize), (dataCapacity - dataSize), &bytesRead);
42931  dataSize += bytesRead;
42932 
42933  if (result != MA_SUCCESS) {
42934  ma_free(pData, pAllocationCallbacks);
42935  return result;
42936  }
42937 
42938  /* We have a maximum of 31 bits with stb_vorbis. */
42939  if (dataSize > INT_MAX) {
42940  ma_free(pData, pAllocationCallbacks);
42941  return MA_TOO_BIG;
42942  }
42943 
42944  stb = stb_vorbis_open_pushdata(pData, (int)dataSize, &consumedDataSize, &vorbisError, NULL);
42945  if (stb != NULL) {
42946  /*
42947  Successfully opened the Vorbis decoder. We might have some leftover unprocessed
42948  data so we'll need to move that down to the front.
42949  */
42950  dataSize -= (size_t)consumedDataSize; /* Consume the data. */
42951  MA_MOVE_MEMORY(pData, ma_offset_ptr(pData, consumedDataSize), dataSize);
42952  break;
42953  } else {
42954  /* Failed to open the decoder. */
42955  if (vorbisError == VORBIS_need_more_data) {
42956  continue;
42957  } else {
42958  ma_free(pData, pAllocationCallbacks);
42959  return MA_ERROR; /* Failed to open the stb_vorbis decoder. */
42960  }
42961  }
42962  }
42963 
42964  MA_ASSERT(stb != NULL);
42965  pVorbis->stb = stb;
42966  pVorbis->push.pData = pData;
42967  pVorbis->push.dataSize = dataSize;
42968  pVorbis->push.dataCapacity = dataCapacity;
42969 
42970  pVorbis->usingPushMode = MA_TRUE;
42971 
42972  result = ma_stbvorbis_post_init(pVorbis);
42973  if (result != MA_SUCCESS) {
42974  stb_vorbis_close(pVorbis->stb);
42975  ma_free(pData, pAllocationCallbacks);
42976  return result;
42977  }
42978 
42979  return MA_SUCCESS;
42980  }
42981  #else
42982  {
42983  /* vorbis is disabled. */
42984  (void)pAllocationCallbacks;
42985  return MA_NOT_IMPLEMENTED;
42986  }
42987  #endif
42988 }
42989 
42990 MA_API ma_result ma_stbvorbis_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis)
42991 {
42992  ma_result result;
42993 
42994  result = ma_stbvorbis_init_internal(pConfig, pVorbis);
42995  if (result != MA_SUCCESS) {
42996  return result;
42997  }
42998 
42999  #if !defined(MA_NO_VORBIS)
43000  {
43001  (void)pAllocationCallbacks; /* Don't know how to make use of this with stb_vorbis. */
43002 
43003  /* We can use stb_vorbis' pull mode for file based streams. */
43004  pVorbis->stb = stb_vorbis_open_filename(pFilePath, NULL, NULL);
43005  if (pVorbis->stb == NULL) {
43006  return MA_INVALID_FILE;
43007  }
43008 
43009  pVorbis->usingPushMode = MA_FALSE;
43010 
43011  result = ma_stbvorbis_post_init(pVorbis);
43012  if (result != MA_SUCCESS) {
43013  stb_vorbis_close(pVorbis->stb);
43014  return result;
43015  }
43016 
43017  return MA_SUCCESS;
43018  }
43019  #else
43020  {
43021  /* vorbis is disabled. */
43022  (void)pFilePath;
43023  (void)pAllocationCallbacks;
43024  return MA_NOT_IMPLEMENTED;
43025  }
43026  #endif
43027 }
43028 
43029 MA_API ma_result ma_stbvorbis_init_memory(const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_stbvorbis* pVorbis)
43030 {
43031  ma_result result;
43032 
43033  result = ma_stbvorbis_init_internal(pConfig, pVorbis);
43034  if (result != MA_SUCCESS) {
43035  return result;
43036  }
43037 
43038  #if !defined(MA_NO_VORBIS)
43039  {
43040  (void)pAllocationCallbacks;
43041 
43042  /* stb_vorbis uses an int as it's size specifier, restricting it to 32-bit even on 64-bit systems. *sigh*. */
43043  if (dataSize > INT_MAX) {
43044  return MA_TOO_BIG;
43045  }
43046 
43047  pVorbis->stb = stb_vorbis_open_memory((const unsigned char*)pData, (int)dataSize, NULL, NULL);
43048  if (pVorbis->stb == NULL) {
43049  return MA_INVALID_FILE;
43050  }
43051 
43052  pVorbis->usingPushMode = MA_FALSE;
43053 
43054  result = ma_stbvorbis_post_init(pVorbis);
43055  if (result != MA_SUCCESS) {
43056  stb_vorbis_close(pVorbis->stb);
43057  return result;
43058  }
43059 
43060  return MA_SUCCESS;
43061  }
43062  #else
43063  {
43064  /* vorbis is disabled. */
43065  (void)pData;
43066  (void)dataSize;
43067  (void)pAllocationCallbacks;
43068  return MA_NOT_IMPLEMENTED;
43069  }
43070  #endif
43071 }
43072 
43073 MA_API void ma_stbvorbis_uninit(ma_stbvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks)
43074 {
43075  if (pVorbis == NULL) {
43076  return;
43077  }
43078 
43079  #if !defined(MA_NO_VORBIS)
43080  {
43081  stb_vorbis_close(pVorbis->stb);
43082 
43083  /* We'll have to clear some memory if we're using push mode. */
43084  if (pVorbis->usingPushMode) {
43085  ma_free(pVorbis->push.pData, pAllocationCallbacks);
43086  }
43087  }
43088  #else
43089  {
43090  /* vorbis is disabled. Should never hit this since initialization would have failed. */
43092  }
43093  #endif
43094 
43095  ma_data_source_uninit(&pVorbis->ds);
43096 }
43097 
43098 MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
43099 {
43100  if (pVorbis == NULL) {
43101  return MA_INVALID_ARGS;
43102  }
43103 
43104  #if !defined(MA_NO_VORBIS)
43105  {
43106  /* We always use floating point format. */
43107  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
43108  ma_uint64 totalFramesRead = 0;
43109  ma_format format;
43110  ma_uint32 channels;
43111 
43112  ma_stbvorbis_get_data_format(pVorbis, &format, &channels, NULL, NULL, 0);
43113 
43114  if (format == ma_format_f32) {
43115  /* We read differently depending on whether or not we're using push mode. */
43116  if (pVorbis->usingPushMode) {
43117  /* Push mode. This is the complex case. */
43118  float* pFramesOutF32 = (float*)pFramesOut;
43119 
43120  while (totalFramesRead < frameCount) {
43121  /* The first thing to do is read from any already-cached frames. */
43122  ma_uint32 framesToReadFromCache = (ma_uint32)ma_min(pVorbis->push.framesRemaining, (frameCount - totalFramesRead)); /* Safe cast because pVorbis->framesRemaining is 32-bit. */
43123 
43124  /* The output pointer can be null in which case we just treate it as a seek. */
43125  if (pFramesOut != NULL) {
43126  ma_uint64 iFrame;
43127  for (iFrame = 0; iFrame < framesToReadFromCache; iFrame += 1) {
43128  ma_uint32 iChannel;
43129  for (iChannel = 0; iChannel < pVorbis->channels; iChannel += 1) {
43130  pFramesOutF32[iChannel] = pVorbis->push.ppPacketData[iChannel][pVorbis->push.framesConsumed + iFrame];
43131  }
43132 
43133  pFramesOutF32 += pVorbis->channels;
43134  }
43135  }
43136 
43137  /* Update pointers and counters. */
43138  pVorbis->push.framesConsumed += framesToReadFromCache;
43139  pVorbis->push.framesRemaining -= framesToReadFromCache;
43140  totalFramesRead += framesToReadFromCache;
43141 
43142  /* Don't bother reading any more frames right now if we've just finished loading. */
43143  if (totalFramesRead == frameCount) {
43144  break;
43145  }
43146 
43147  MA_ASSERT(pVorbis->push.framesRemaining == 0);
43148 
43149  /* Getting here means we've run out of cached frames. We'll need to load some more. */
43150  for (;;) {
43151  int samplesRead = 0;
43152  int consumedDataSize;
43153 
43154  /* We need to case dataSize to an int, so make sure we can do it safely. */
43155  if (pVorbis->push.dataSize > INT_MAX) {
43156  break; /* Too big. */
43157  }
43158 
43159  consumedDataSize = stb_vorbis_decode_frame_pushdata(pVorbis->stb, pVorbis->push.pData, (int)pVorbis->push.dataSize, NULL, &pVorbis->push.ppPacketData, &samplesRead);
43160  if (consumedDataSize != 0) {
43161  /* Successfully decoded a Vorbis frame. Consume the data. */
43162  pVorbis->push.dataSize -= (size_t)consumedDataSize;
43163  MA_MOVE_MEMORY(pVorbis->push.pData, ma_offset_ptr(pVorbis->push.pData, consumedDataSize), pVorbis->push.dataSize);
43164 
43165  pVorbis->push.framesConsumed = 0;
43166  pVorbis->push.framesRemaining = samplesRead;
43167 
43168  break;
43169  } else {
43170  /* Not enough data. Read more. */
43171  size_t bytesRead;
43172 
43173  /* Expand the data buffer if necessary. */
43174  if (pVorbis->push.dataCapacity == pVorbis->push.dataSize) {
43175  size_t newCap = pVorbis->push.dataCapacity + MA_VORBIS_DATA_CHUNK_SIZE;
43176  ma_uint8* pNewData;
43177 
43178  pNewData = (ma_uint8*)ma_realloc(pVorbis->push.pData, newCap, &pVorbis->allocationCallbacks);
43179  if (pNewData == NULL) {
43180  result = MA_OUT_OF_MEMORY;
43181  break;
43182  }
43183 
43184  pVorbis->push.pData = pNewData;
43185  pVorbis->push.dataCapacity = newCap;
43186  }
43187 
43188  /* We should have enough room to load some data. */
43189  result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, ma_offset_ptr(pVorbis->push.pData, pVorbis->push.dataSize), (pVorbis->push.dataCapacity - pVorbis->push.dataSize), &bytesRead);
43190  pVorbis->push.dataSize += bytesRead;
43191 
43192  if (result != MA_SUCCESS) {
43193  break; /* Failed to read any data. Get out. */
43194  }
43195  }
43196  }
43197 
43198  /* If we don't have a success code at this point it means we've encounted an error or the end of the file has been reached (probably the latter). */
43199  if (result != MA_SUCCESS) {
43200  break;
43201  }
43202  }
43203  } else {
43204  /* Pull mode. This is the simple case, but we still need to run in a loop because stb_vorbis loves using 32-bit instead of 64-bit. */
43205  while (totalFramesRead < frameCount) {
43206  ma_uint64 framesRemaining = (frameCount - totalFramesRead);
43207  int framesRead;
43208 
43209  if (framesRemaining > INT_MAX) {
43210  framesRemaining = INT_MAX;
43211  }
43212 
43213  framesRead = stb_vorbis_get_samples_float_interleaved(pVorbis->stb, channels, (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels), (int)framesRemaining * channels); /* Safe cast. */
43214  totalFramesRead += framesRead;
43215 
43216  if (framesRead < framesRemaining) {
43217  break; /* Nothing left to read. Get out. */
43218  }
43219  }
43220  }
43221  } else {
43222  result = MA_INVALID_ARGS;
43223  }
43224 
43225  pVorbis->cursor += totalFramesRead;
43226 
43227  if (totalFramesRead == 0) {
43228  result = MA_AT_END;
43229  }
43230 
43231  if (pFramesRead != NULL) {
43232  *pFramesRead = totalFramesRead;
43233  }
43234 
43235  return result;
43236  }
43237  #else
43238  {
43239  /* vorbis is disabled. Should never hit this since initialization would have failed. */
43241 
43242  (void)pFramesOut;
43243  (void)frameCount;
43244  (void)pFramesRead;
43245 
43246  return MA_NOT_IMPLEMENTED;
43247  }
43248  #endif
43249 }
43250 
43251 MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64 frameIndex)
43252 {
43253  if (pVorbis == NULL) {
43254  return MA_INVALID_ARGS;
43255  }
43256 
43257  #if !defined(MA_NO_VORBIS)
43258  {
43259  /* Different seeking methods depending on whether or not we're using push mode. */
43260  if (pVorbis->usingPushMode) {
43261  /* Push mode. This is the complex case. */
43262  ma_result result;
43263  float buffer[4096];
43264 
43265  /*
43266  This is terribly inefficient because stb_vorbis does not have a good seeking solution with it's push API. Currently this just performs
43267  a full decode right from the start of the stream. Later on I'll need to write a layer that goes through all of the Ogg pages until we
43268  find the one containing the sample we need. Then we know exactly where to seek for stb_vorbis.
43269 
43270  TODO: Use seeking logic documented for stb_vorbis_flush_pushdata().
43271  */
43272 
43273  /* Seek to the start of the file to begin with. */
43274  result = pVorbis->onSeek(pVorbis->pReadSeekTellUserData, 0, ma_seek_origin_start);
43275  if (result != MA_SUCCESS) {
43276  return result;
43277  }
43278 
43279  stb_vorbis_flush_pushdata(pVorbis->stb);
43280  pVorbis->push.framesRemaining = 0;
43281  pVorbis->push.dataSize = 0;
43282 
43283  /* Move the cursor back to the start. We'll increment this in the loop below. */
43284  pVorbis->cursor = 0;
43285 
43286  while (pVorbis->cursor < frameIndex) {
43287  ma_uint64 framesRead;
43288  ma_uint64 framesToRead = ma_countof(buffer)/pVorbis->channels;
43289  if (framesToRead > (frameIndex - pVorbis->cursor)) {
43290  framesToRead = (frameIndex - pVorbis->cursor);
43291  }
43292 
43293  result = ma_stbvorbis_read_pcm_frames(pVorbis, buffer, framesToRead, &framesRead);
43294  pVorbis->cursor += framesRead;
43295 
43296  if (result != MA_SUCCESS) {
43297  return result;
43298  }
43299  }
43300  } else {
43301  /* Pull mode. This is the simple case. */
43302  int vorbisResult;
43303 
43304  if (frameIndex > UINT_MAX) {
43305  return MA_INVALID_ARGS; /* Trying to seek beyond the 32-bit maximum of stb_vorbis. */
43306  }
43307 
43308  vorbisResult = stb_vorbis_seek(pVorbis->stb, (unsigned int)frameIndex); /* Safe cast. */
43309  if (vorbisResult == 0) {
43310  return MA_ERROR; /* See failed. */
43311  }
43312 
43313  pVorbis->cursor = frameIndex;
43314  }
43315 
43316  return MA_SUCCESS;
43317  }
43318  #else
43319  {
43320  /* vorbis is disabled. Should never hit this since initialization would have failed. */
43322 
43323  (void)frameIndex;
43324 
43325  return MA_NOT_IMPLEMENTED;
43326  }
43327  #endif
43328 }
43329 
43330 MA_API ma_result ma_stbvorbis_get_data_format(ma_stbvorbis* pVorbis, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
43331 {
43332  /* Defaults for safety. */
43333  if (pFormat != NULL) {
43334  *pFormat = ma_format_unknown;
43335  }
43336  if (pChannels != NULL) {
43337  *pChannels = 0;
43338  }
43339  if (pSampleRate != NULL) {
43340  *pSampleRate = 0;
43341  }
43342  if (pChannelMap != NULL) {
43343  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
43344  }
43345 
43346  if (pVorbis == NULL) {
43347  return MA_INVALID_OPERATION;
43348  }
43349 
43350  if (pFormat != NULL) {
43351  *pFormat = pVorbis->format;
43352  }
43353 
43354  #if !defined(MA_NO_VORBIS)
43355  {
43356  if (pChannels != NULL) {
43357  *pChannels = pVorbis->channels;
43358  }
43359 
43360  if (pSampleRate != NULL) {
43361  *pSampleRate = pVorbis->sampleRate;
43362  }
43363 
43364  if (pChannelMap != NULL) {
43365  ma_get_standard_channel_map(ma_standard_channel_map_vorbis, (ma_uint32)ma_min(pVorbis->channels, channelMapCap), pChannelMap);
43366  }
43367 
43368  return MA_SUCCESS;
43369  }
43370  #else
43371  {
43372  /* vorbis is disabled. Should never hit this since initialization would have failed. */
43374  return MA_NOT_IMPLEMENTED;
43375  }
43376  #endif
43377 }
43378 
43379 MA_API ma_result ma_stbvorbis_get_cursor_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pCursor)
43380 {
43381  if (pCursor == NULL) {
43382  return MA_INVALID_ARGS;
43383  }
43384 
43385  *pCursor = 0; /* Safety. */
43386 
43387  if (pVorbis == NULL) {
43388  return MA_INVALID_ARGS;
43389  }
43390 
43391  #if !defined(MA_NO_VORBIS)
43392  {
43393  *pCursor = pVorbis->cursor;
43394 
43395  return MA_SUCCESS;
43396  }
43397  #else
43398  {
43399  /* vorbis is disabled. Should never hit this since initialization would have failed. */
43401  return MA_NOT_IMPLEMENTED;
43402  }
43403  #endif
43404 }
43405 
43406 MA_API ma_result ma_stbvorbis_get_length_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pLength)
43407 {
43408  if (pLength == NULL) {
43409  return MA_INVALID_ARGS;
43410  }
43411 
43412  *pLength = 0; /* Safety. */
43413 
43414  if (pVorbis == NULL) {
43415  return MA_INVALID_ARGS;
43416  }
43417 
43418  #if !defined(MA_NO_VORBIS)
43419  {
43420  if (pVorbis->usingPushMode) {
43421  *pLength = 0; /* I don't know of a good way to determine this reliably with stb_vorbis and push mode. */
43422  } else {
43423  *pLength = stb_vorbis_stream_length_in_samples(pVorbis->stb);
43424  }
43425 
43426  return MA_SUCCESS;
43427  }
43428  #else
43429  {
43430  /* vorbis is disabled. Should never hit this since initialization would have failed. */
43432  return MA_NOT_IMPLEMENTED;
43433  }
43434  #endif
43435 }
43436 
43437 
43438 static ma_result ma_decoding_backend_init__stbvorbis(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
43439 {
43440  ma_result result;
43441  ma_stbvorbis* pVorbis;
43442 
43443  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
43444 
43445  /* For now we're just allocating the decoder backend on the heap. */
43446  pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
43447  if (pVorbis == NULL) {
43448  return MA_OUT_OF_MEMORY;
43449  }
43450 
43451  result = ma_stbvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
43452  if (result != MA_SUCCESS) {
43453  ma_free(pVorbis, pAllocationCallbacks);
43454  return result;
43455  }
43456 
43457  *ppBackend = pVorbis;
43458 
43459  return MA_SUCCESS;
43460 }
43461 
43462 static ma_result ma_decoding_backend_init_file__stbvorbis(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
43463 {
43464  ma_result result;
43465  ma_stbvorbis* pVorbis;
43466 
43467  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
43468 
43469  /* For now we're just allocating the decoder backend on the heap. */
43470  pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
43471  if (pVorbis == NULL) {
43472  return MA_OUT_OF_MEMORY;
43473  }
43474 
43475  result = ma_stbvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
43476  if (result != MA_SUCCESS) {
43477  ma_free(pVorbis, pAllocationCallbacks);
43478  return result;
43479  }
43480 
43481  *ppBackend = pVorbis;
43482 
43483  return MA_SUCCESS;
43484 }
43485 
43486 static ma_result ma_decoding_backend_init_memory__stbvorbis(void* pUserData, const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
43487 {
43488  ma_result result;
43489  ma_stbvorbis* pVorbis;
43490 
43491  (void)pUserData; /* For now not using pUserData, but once we start storing the vorbis decoder state within the ma_decoder structure this will be set to the decoder so we can avoid a malloc. */
43492 
43493  /* For now we're just allocating the decoder backend on the heap. */
43494  pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
43495  if (pVorbis == NULL) {
43496  return MA_OUT_OF_MEMORY;
43497  }
43498 
43499  result = ma_stbvorbis_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pVorbis);
43500  if (result != MA_SUCCESS) {
43501  ma_free(pVorbis, pAllocationCallbacks);
43502  return result;
43503  }
43504 
43505  *ppBackend = pVorbis;
43506 
43507  return MA_SUCCESS;
43508 }
43509 
43510 static void ma_decoding_backend_uninit__stbvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
43511 {
43512  ma_stbvorbis* pVorbis = (ma_stbvorbis*)pBackend;
43513 
43514  (void)pUserData;
43515 
43516  ma_stbvorbis_uninit(pVorbis, pAllocationCallbacks);
43517  ma_free(pVorbis, pAllocationCallbacks);
43518 }
43519 
43520 static ma_result ma_decoding_backend_get_channel_map__stbvorbis(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
43521 {
43522  ma_stbvorbis* pVorbis = (ma_stbvorbis*)pBackend;
43523 
43524  (void)pUserData;
43525 
43526  return ma_stbvorbis_get_data_format(pVorbis, NULL, NULL, NULL, pChannelMap, channelMapCap);
43527 }
43528 
43529 static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_stbvorbis =
43530 {
43531  ma_decoding_backend_init__stbvorbis,
43532  ma_decoding_backend_init_file__stbvorbis,
43533  NULL, /* onInitFileW() */
43534  ma_decoding_backend_init_memory__stbvorbis,
43535  ma_decoding_backend_uninit__stbvorbis,
43536  ma_decoding_backend_get_channel_map__stbvorbis
43537 };
43538 
43539 static ma_result ma_decoder_init_vorbis__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43540 {
43541  return ma_decoder_init_from_vtable(&g_ma_decoding_backend_vtable_stbvorbis, NULL, pConfig, pDecoder);
43542 }
43543 #endif /* STB_VORBIS_INCLUDE_STB_VORBIS_H */
43544 
43545 
43546 
43548 {
43549  MA_ASSERT(pDecoder != NULL);
43550 
43551  if (pConfig != NULL) {
43553  } else {
43555  return MA_SUCCESS;
43556  }
43557 }
43558 
43559 static ma_result ma_decoder__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
43560 {
43561  ma_uint64 framesRead = ma_decoder_read_pcm_frames((ma_decoder*)pDataSource, pFramesOut, frameCount);
43562 
43563  if (pFramesRead != NULL) {
43564  *pFramesRead = framesRead;
43565  }
43566 
43567  if (framesRead == 0) {
43568  return MA_AT_END;
43569  }
43570 
43571  return MA_SUCCESS;
43572 }
43573 
43575 {
43576  return ma_decoder_seek_to_pcm_frame((ma_decoder*)pDataSource, frameIndex);
43577 }
43578 
43580 {
43581  ma_decoder* pDecoder = (ma_decoder*)pDataSource;
43582 
43583  *pFormat = pDecoder->outputFormat;
43584  *pChannels = pDecoder->outputChannels;
43585  *pSampleRate = pDecoder->outputSampleRate;
43586 
43587  return MA_SUCCESS;
43588 }
43589 
43591 {
43592  ma_decoder* pDecoder = (ma_decoder*)pDataSource;
43593 
43594  return ma_decoder_get_cursor_in_pcm_frames(pDecoder, pCursor);
43595 }
43596 
43598 {
43599  ma_decoder* pDecoder = (ma_decoder*)pDataSource;
43600 
43601  *pLength = ma_decoder_get_length_in_pcm_frames(pDecoder);
43602  if (*pLength == 0) {
43603  return MA_NOT_IMPLEMENTED;
43604  }
43605 
43606  return MA_SUCCESS;
43607 }
43608 
43610 {
43613  NULL, /* onMap */
43614  NULL, /* onUnmap */
43618 };
43619 
43620 static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, ma_decoder_tell_proc onTell, void* pUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43621 {
43622  ma_result result;
43623  ma_data_source_config dataSourceConfig;
43624 
43625  MA_ASSERT(pConfig != NULL);
43626 
43627  if (pDecoder == NULL) {
43628  return MA_INVALID_ARGS;
43629  }
43630 
43631  MA_ZERO_OBJECT(pDecoder);
43632 
43633  if (onRead == NULL || onSeek == NULL) {
43634  return MA_INVALID_ARGS;
43635  }
43636 
43637  dataSourceConfig = ma_data_source_config_init();
43638  dataSourceConfig.vtable = &g_ma_decoder_data_source_vtable;
43639 
43640  result = ma_data_source_init(&dataSourceConfig, &pDecoder->ds);
43641  if (result != MA_SUCCESS) {
43642  return result;
43643  }
43644 
43645  pDecoder->onRead = onRead;
43646  pDecoder->onSeek = onSeek;
43647  pDecoder->onTell = onTell;
43648  pDecoder->pUserData = pUserData;
43649 
43650  result = ma_decoder__init_allocation_callbacks(pConfig, pDecoder);
43651  if (result != MA_SUCCESS) {
43652  ma_data_source_uninit(&pDecoder->ds);
43653  return result;
43654  }
43655 
43656  return MA_SUCCESS;
43657 }
43658 
43660 {
43661  ma_result result = MA_SUCCESS;
43662 
43663  /* Basic validation in case the internal decoder supports different limits to miniaudio. */
43664  {
43665  /* TODO: Remove this block once we remove MA_MIN_CHANNELS and MA_MAX_CHANNELS. */
43666  ma_uint32 internalChannels;
43667  ma_data_source_get_data_format(pDecoder->pBackend, NULL, &internalChannels, NULL);
43668 
43669  if (internalChannels < MA_MIN_CHANNELS || internalChannels > MA_MAX_CHANNELS) {
43670  result = MA_INVALID_DATA;
43671  }
43672  }
43673 
43674  if (result == MA_SUCCESS) {
43675  result = ma_decoder__init_data_converter(pDecoder, pConfig);
43676  }
43677 
43678  /* If we failed post initialization we need to uninitialize the decoder before returning to prevent a memory leak. */
43679  if (result != MA_SUCCESS) {
43680  ma_decoder_uninit(pDecoder);
43681  return result;
43682  }
43683 
43684  return result;
43685 }
43686 
43688 {
43689 #ifdef MA_HAS_WAV
43691 
43693  config.encodingFormat = ma_encoding_format_wav;
43694 
43695  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
43696 #else
43697  (void)onRead;
43698  (void)onSeek;
43699  (void)pUserData;
43700  (void)pConfig;
43701  (void)pDecoder;
43702  return MA_NO_BACKEND;
43703 #endif
43704 }
43705 
43707 {
43708 #ifdef MA_HAS_FLAC
43710 
43712  config.encodingFormat = ma_encoding_format_flac;
43713 
43714  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
43715 #else
43716  (void)onRead;
43717  (void)onSeek;
43718  (void)pUserData;
43719  (void)pConfig;
43720  (void)pDecoder;
43721  return MA_NO_BACKEND;
43722 #endif
43723 }
43724 
43726 {
43727 #ifdef MA_HAS_MP3
43729 
43731  config.encodingFormat = ma_encoding_format_mp3;
43732 
43733  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
43734 #else
43735  (void)onRead;
43736  (void)onSeek;
43737  (void)pUserData;
43738  (void)pConfig;
43739  (void)pDecoder;
43740  return MA_NO_BACKEND;
43741 #endif
43742 }
43743 
43745 {
43746 #ifdef MA_HAS_VORBIS
43748 
43750  config.encodingFormat = ma_encoding_format_vorbis;
43751 
43752  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
43753 #else
43754  (void)onRead;
43755  (void)onSeek;
43756  (void)pUserData;
43757  (void)pConfig;
43758  (void)pDecoder;
43759  return MA_NO_BACKEND;
43760 #endif
43761 }
43762 
43763 
43764 
43765 static ma_result ma_decoder_init__internal(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void* pUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43766 {
43767  ma_result result = MA_NO_BACKEND;
43768 
43769  MA_ASSERT(pConfig != NULL);
43770  MA_ASSERT(pDecoder != NULL);
43771 
43772  /* Silence some warnings in the case that we don't have any decoder backends enabled. */
43773  (void)onRead;
43774  (void)onSeek;
43775  (void)pUserData;
43776 
43777 
43778  /* If we've specified a specific encoding type, try that first. */
43779  if (pConfig->encodingFormat != ma_encoding_format_unknown) {
43780  #ifdef MA_HAS_WAV
43781  if (pConfig->encodingFormat == ma_encoding_format_wav) {
43782  result = ma_decoder_init_wav__internal(pConfig, pDecoder);
43783  }
43784  #endif
43785  #ifdef MA_HAS_FLAC
43786  if (pConfig->encodingFormat == ma_encoding_format_flac) {
43787  result = ma_decoder_init_flac__internal(pConfig, pDecoder);
43788  }
43789  #endif
43790  #ifdef MA_HAS_MP3
43791  if (pConfig->encodingFormat == ma_encoding_format_mp3) {
43792  result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
43793  }
43794  #endif
43795  #ifdef MA_HAS_VORBIS
43796  if (pConfig->encodingFormat == ma_encoding_format_vorbis) {
43797  result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
43798  }
43799  #endif
43800 
43801  /* If we weren't able to initialize the decoder, seek back to the start to give the next attempts a clean start. */
43802  if (result != MA_SUCCESS) {
43803  onSeek(pDecoder, 0, ma_seek_origin_start);
43804  }
43805  }
43806 
43807  if (result != MA_SUCCESS) {
43808  /* Getting here means we couldn't load a specific decoding backend based on the encoding format. */
43809 
43810  /*
43811  We use trial and error to open a decoder. We prioritize custom decoders so that if they
43812  implement the same encoding format they take priority over the built-in decoders.
43813  */
43814  if (result != MA_SUCCESS) {
43815  result = ma_decoder_init_custom__internal(pConfig, pDecoder);
43816  if (result != MA_SUCCESS) {
43817  onSeek(pDecoder, 0, ma_seek_origin_start);
43818  }
43819  }
43820 
43821  /*
43822  If we get to this point and we still haven't found a decoder, and the caller has requested a
43823  specific encoding format, there's no hope for it. Abort.
43824  */
43825  if (pConfig->encodingFormat != ma_encoding_format_unknown) {
43826  return MA_NO_BACKEND;
43827  }
43828 
43829  #ifdef MA_HAS_WAV
43830  if (result != MA_SUCCESS) {
43831  result = ma_decoder_init_wav__internal(pConfig, pDecoder);
43832  if (result != MA_SUCCESS) {
43833  onSeek(pDecoder, 0, ma_seek_origin_start);
43834  }
43835  }
43836  #endif
43837  #ifdef MA_HAS_FLAC
43838  if (result != MA_SUCCESS) {
43839  result = ma_decoder_init_flac__internal(pConfig, pDecoder);
43840  if (result != MA_SUCCESS) {
43841  onSeek(pDecoder, 0, ma_seek_origin_start);
43842  }
43843  }
43844  #endif
43845  #ifdef MA_HAS_MP3
43846  if (result != MA_SUCCESS) {
43847  result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
43848  if (result != MA_SUCCESS) {
43849  onSeek(pDecoder, 0, ma_seek_origin_start);
43850  }
43851  }
43852  #endif
43853  #ifdef MA_HAS_VORBIS
43854  if (result != MA_SUCCESS) {
43855  result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
43856  if (result != MA_SUCCESS) {
43857  onSeek(pDecoder, 0, ma_seek_origin_start);
43858  }
43859  }
43860  #endif
43861  }
43862 
43863  if (result != MA_SUCCESS) {
43864  return result;
43865  }
43866 
43867  return ma_decoder__postinit(pConfig, pDecoder);
43868 }
43869 
43870 MA_API ma_result ma_decoder_init(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void* pUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43871 {
43873  ma_result result;
43874 
43876 
43877  result = ma_decoder__preinit(onRead, onSeek, NULL, pUserData, &config, pDecoder);
43878  if (result != MA_SUCCESS) {
43879  return result;
43880  }
43881 
43882  return ma_decoder_init__internal(onRead, onSeek, pUserData, &config, pDecoder);
43883 }
43884 
43885 
43886 static size_t ma_decoder__on_read_memory(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead)
43887 {
43888  size_t bytesRemaining;
43889 
43890  MA_ASSERT(pDecoder->data.memory.dataSize >= pDecoder->data.memory.currentReadPos);
43891 
43892  bytesRemaining = pDecoder->data.memory.dataSize - pDecoder->data.memory.currentReadPos;
43893  if (bytesToRead > bytesRemaining) {
43894  bytesToRead = bytesRemaining;
43895  }
43896 
43897  if (bytesToRead > 0) {
43898  MA_COPY_MEMORY(pBufferOut, pDecoder->data.memory.pData + pDecoder->data.memory.currentReadPos, bytesToRead);
43899  pDecoder->data.memory.currentReadPos += bytesToRead;
43900  }
43901 
43902  return bytesToRead;
43903 }
43904 
43906 {
43907  if (byteOffset > 0 && (ma_uint64)byteOffset > MA_SIZE_MAX) {
43908  return MA_FALSE; /* Too far. */
43909  }
43910 
43911  if (origin == ma_seek_origin_current) {
43912  if (byteOffset > 0) {
43913  if (pDecoder->data.memory.currentReadPos + byteOffset > pDecoder->data.memory.dataSize) {
43914  byteOffset = (ma_int64)(pDecoder->data.memory.dataSize - pDecoder->data.memory.currentReadPos); /* Trying to seek too far forward. */
43915  }
43916 
43917  pDecoder->data.memory.currentReadPos += (size_t)byteOffset;
43918  } else {
43919  if (pDecoder->data.memory.currentReadPos < (size_t)-byteOffset) {
43920  byteOffset = -(ma_int64)pDecoder->data.memory.currentReadPos; /* Trying to seek too far backwards. */
43921  }
43922 
43923  pDecoder->data.memory.currentReadPos -= (size_t)-byteOffset;
43924  }
43925  } else {
43926  if (origin == ma_seek_origin_end) {
43927  if (byteOffset < 0) {
43928  byteOffset = -byteOffset;
43929  }
43930 
43931  if (byteOffset > (ma_int64)pDecoder->data.memory.dataSize) {
43932  pDecoder->data.memory.currentReadPos = 0; /* Trying to seek too far back. */
43933  } else {
43934  pDecoder->data.memory.currentReadPos = pDecoder->data.memory.dataSize - (size_t)byteOffset;
43935  }
43936  } else {
43937  if ((size_t)byteOffset <= pDecoder->data.memory.dataSize) {
43938  pDecoder->data.memory.currentReadPos = (size_t)byteOffset;
43939  } else {
43940  pDecoder->data.memory.currentReadPos = pDecoder->data.memory.dataSize; /* Trying to seek too far forward. */
43941  }
43942  }
43943  }
43944 
43945  return MA_TRUE;
43946 }
43947 
43949 {
43950  MA_ASSERT(pDecoder != NULL);
43951  MA_ASSERT(pCursor != NULL);
43952 
43953  *pCursor = (ma_int64)pDecoder->data.memory.currentReadPos;
43954 
43955  return MA_SUCCESS;
43956 }
43957 
43958 static ma_result ma_decoder__preinit_memory(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43959 {
43961  if (result != MA_SUCCESS) {
43962  return result;
43963  }
43964 
43965  if (pData == NULL || dataSize == 0) {
43966  return MA_INVALID_ARGS;
43967  }
43968 
43969  pDecoder->data.memory.pData = (const ma_uint8*)pData;
43970  pDecoder->data.memory.dataSize = dataSize;
43971  pDecoder->data.memory.currentReadPos = 0;
43972 
43973  (void)pConfig;
43974  return MA_SUCCESS;
43975 }
43976 
43977 MA_API ma_result ma_decoder_init_memory(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43978 {
43980  ma_result result;
43981 
43982  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
43983 
43984  result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
43985  if (result != MA_SUCCESS) {
43986  return result;
43987  }
43988 
43990 }
43991 
43992 MA_API ma_result ma_decoder_init_memory_wav(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
43993 {
43994 #ifdef MA_HAS_WAV
43996 
43997  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
43998  config.encodingFormat = ma_encoding_format_wav;
43999 
44000  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
44001 #else
44002  (void)pData;
44003  (void)dataSize;
44004  (void)pConfig;
44005  (void)pDecoder;
44006  return MA_NO_BACKEND;
44007 #endif
44008 }
44009 
44010 MA_API ma_result ma_decoder_init_memory_flac(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44011 {
44012 #ifdef MA_HAS_FLAC
44014 
44015  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
44016  config.encodingFormat = ma_encoding_format_flac;
44017 
44018  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
44019 #else
44020  (void)pData;
44021  (void)dataSize;
44022  (void)pConfig;
44023  (void)pDecoder;
44024  return MA_NO_BACKEND;
44025 #endif
44026 }
44027 
44028 MA_API ma_result ma_decoder_init_memory_mp3(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44029 {
44030 #ifdef MA_HAS_MP3
44032 
44033  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
44034  config.encodingFormat = ma_encoding_format_mp3;
44035 
44036  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
44037 #else
44038  (void)pData;
44039  (void)dataSize;
44040  (void)pConfig;
44041  (void)pDecoder;
44042  return MA_NO_BACKEND;
44043 #endif
44044 }
44045 
44046 MA_API ma_result ma_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44047 {
44048 #ifdef MA_HAS_VORBIS
44050 
44051  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
44052  config.encodingFormat = ma_encoding_format_vorbis;
44053 
44054  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
44055 #else
44056  (void)pData;
44057  (void)dataSize;
44058  (void)pConfig;
44059  (void)pDecoder;
44060  return MA_NO_BACKEND;
44061 #endif
44062 }
44063 
44064 
44065 
44066 #if defined(MA_HAS_WAV) || \
44067  defined(MA_HAS_MP3) || \
44068  defined(MA_HAS_FLAC) || \
44069  defined(MA_HAS_VORBIS) || \
44070  defined(MA_HAS_OPUS)
44071 #define MA_HAS_PATH_API
44072 #endif
44073 
44074 #if defined(MA_HAS_PATH_API)
44075 static const char* ma_path_file_name(const char* path)
44076 {
44077  const char* fileName;
44078 
44079  if (path == NULL) {
44080  return NULL;
44081  }
44082 
44083  fileName = path;
44084 
44085  /* We just loop through the path until we find the last slash. */
44086  while (path[0] != '\0') {
44087  if (path[0] == '/' || path[0] == '\\') {
44088  fileName = path;
44089  }
44090 
44091  path += 1;
44092  }
44093 
44094  /* At this point the file name is sitting on a slash, so just move forward. */
44095  while (fileName[0] != '\0' && (fileName[0] == '/' || fileName[0] == '\\')) {
44096  fileName += 1;
44097  }
44098 
44099  return fileName;
44100 }
44101 
44102 static const wchar_t* ma_path_file_name_w(const wchar_t* path)
44103 {
44104  const wchar_t* fileName;
44105 
44106  if (path == NULL) {
44107  return NULL;
44108  }
44109 
44110  fileName = path;
44111 
44112  /* We just loop through the path until we find the last slash. */
44113  while (path[0] != '\0') {
44114  if (path[0] == '/' || path[0] == '\\') {
44115  fileName = path;
44116  }
44117 
44118  path += 1;
44119  }
44120 
44121  /* At this point the file name is sitting on a slash, so just move forward. */
44122  while (fileName[0] != '\0' && (fileName[0] == '/' || fileName[0] == '\\')) {
44123  fileName += 1;
44124  }
44125 
44126  return fileName;
44127 }
44128 
44129 
44130 static const char* ma_path_extension(const char* path)
44131 {
44132  const char* extension;
44133  const char* lastOccurance;
44134 
44135  if (path == NULL) {
44136  path = "";
44137  }
44138 
44139  extension = ma_path_file_name(path);
44140  lastOccurance = NULL;
44141 
44142  /* Just find the last '.' and return. */
44143  while (extension[0] != '\0') {
44144  if (extension[0] == '.') {
44145  extension += 1;
44146  lastOccurance = extension;
44147  }
44148 
44149  extension += 1;
44150  }
44151 
44152  return (lastOccurance != NULL) ? lastOccurance : extension;
44153 }
44154 
44155 static const wchar_t* ma_path_extension_w(const wchar_t* path)
44156 {
44157  const wchar_t* extension;
44158  const wchar_t* lastOccurance;
44159 
44160  if (path == NULL) {
44161  path = L"";
44162  }
44163 
44164  extension = ma_path_file_name_w(path);
44165  lastOccurance = NULL;
44166 
44167  /* Just find the last '.' and return. */
44168  while (extension[0] != '\0') {
44169  if (extension[0] == '.') {
44170  extension += 1;
44171  lastOccurance = extension;
44172  }
44173 
44174  extension += 1;
44175  }
44176 
44177  return (lastOccurance != NULL) ? lastOccurance : extension;
44178 }
44179 
44180 
44181 static ma_bool32 ma_path_extension_equal(const char* path, const char* extension)
44182 {
44183  const char* ext1;
44184  const char* ext2;
44185 
44186  if (path == NULL || extension == NULL) {
44187  return MA_FALSE;
44188  }
44189 
44190  ext1 = extension;
44191  ext2 = ma_path_extension(path);
44192 
44193 #if defined(_MSC_VER) || defined(__DMC__)
44194  return _stricmp(ext1, ext2) == 0;
44195 #else
44196  return strcasecmp(ext1, ext2) == 0;
44197 #endif
44198 }
44199 
44200 static ma_bool32 ma_path_extension_equal_w(const wchar_t* path, const wchar_t* extension)
44201 {
44202  const wchar_t* ext1;
44203  const wchar_t* ext2;
44204 
44205  if (path == NULL || extension == NULL) {
44206  return MA_FALSE;
44207  }
44208 
44209  ext1 = extension;
44210  ext2 = ma_path_extension_w(path);
44211 
44212 #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)
44213  return _wcsicmp(ext1, ext2) == 0;
44214 #else
44215  /*
44216  I'm not aware of a wide character version of strcasecmp(). I'm therefore converting the extensions to multibyte strings and comparing those. This
44217  isn't the most efficient way to do it, but it should work OK.
44218  */
44219  {
44220  char ext1MB[4096];
44221  char ext2MB[4096];
44222  const wchar_t* pext1 = ext1;
44223  const wchar_t* pext2 = ext2;
44224  mbstate_t mbs1;
44225  mbstate_t mbs2;
44226 
44227  MA_ZERO_OBJECT(&mbs1);
44228  MA_ZERO_OBJECT(&mbs2);
44229 
44230  if (wcsrtombs(ext1MB, &pext1, sizeof(ext1MB), &mbs1) == (size_t)-1) {
44231  return MA_FALSE;
44232  }
44233  if (wcsrtombs(ext2MB, &pext2, sizeof(ext2MB), &mbs2) == (size_t)-1) {
44234  return MA_FALSE;
44235  }
44236 
44237  return strcasecmp(ext1MB, ext2MB) == 0;
44238  }
44239 #endif
44240 }
44241 #endif /* MA_HAS_PATH_API */
44242 
44243 
44244 
44245 static size_t ma_decoder__on_read_vfs(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead)
44246 {
44247  size_t bytesRead;
44248 
44249  MA_ASSERT(pDecoder != NULL);
44250  MA_ASSERT(pBufferOut != NULL);
44251 
44252  ma_vfs_or_default_read(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file, pBufferOut, bytesToRead, &bytesRead);
44253 
44254  return bytesRead;
44255 }
44256 
44258 {
44259  ma_result result;
44260 
44261  MA_ASSERT(pDecoder != NULL);
44262 
44263  result = ma_vfs_or_default_seek(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file, offset, origin);
44264  if (result != MA_SUCCESS) {
44265  return MA_FALSE;
44266  }
44267 
44268  return MA_TRUE;
44269 }
44270 
44272 {
44273  MA_ASSERT(pDecoder != NULL);
44274 
44275  return ma_vfs_or_default_tell(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file, pCursor);
44276 }
44277 
44278 static ma_result ma_decoder__preinit_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44279 {
44280  ma_result result;
44281  ma_vfs_file file;
44282 
44284  if (result != MA_SUCCESS) {
44285  return result;
44286  }
44287 
44288  if (pFilePath == NULL || pFilePath[0] == '\0') {
44289  return MA_INVALID_ARGS;
44290  }
44291 
44292  result = ma_vfs_or_default_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
44293  if (result != MA_SUCCESS) {
44294  return result;
44295  }
44296 
44297  pDecoder->data.vfs.pVFS = pVFS;
44298  pDecoder->data.vfs.file = file;
44299 
44300  return MA_SUCCESS;
44301 }
44302 
44303 MA_API ma_result ma_decoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44304 {
44305  ma_result result;
44307 
44309  result = ma_decoder__preinit_vfs(pVFS, pFilePath, &config, pDecoder);
44310  if (result != MA_SUCCESS) {
44311  return result;
44312  }
44313 
44314  result = MA_NO_BACKEND;
44315 
44316  if (config.encodingFormat != ma_encoding_format_unknown) {
44317  #ifdef MA_HAS_WAV
44318  if (config.encodingFormat == ma_encoding_format_wav) {
44319  result = ma_decoder_init_wav__internal(&config, pDecoder);
44320  }
44321  #endif
44322  #ifdef MA_HAS_FLAC
44323  if (config.encodingFormat == ma_encoding_format_flac) {
44324  result = ma_decoder_init_flac__internal(&config, pDecoder);
44325  }
44326  #endif
44327  #ifdef MA_HAS_MP3
44328  if (config.encodingFormat == ma_encoding_format_mp3) {
44329  result = ma_decoder_init_mp3__internal(&config, pDecoder);
44330  }
44331  #endif
44332  #ifdef MA_HAS_VORBIS
44333  if (config.encodingFormat == ma_encoding_format_vorbis) {
44334  result = ma_decoder_init_vorbis__internal(&config, pDecoder);
44335  }
44336  #endif
44337 
44338  /* Make sure we seek back to the start if we didn't initialize a decoder successfully so the next attempts have a fresh start. */
44339  if (result != MA_SUCCESS) {
44341  }
44342  }
44343 
44344  if (result != MA_SUCCESS) {
44345  /* Getting here means we weren't able to initialize a decoder of a specific encoding format. */
44346 
44347  /*
44348  We use trial and error to open a decoder. We prioritize custom decoders so that if they
44349  implement the same encoding format they take priority over the built-in decoders.
44350  */
44351  if (result != MA_SUCCESS) {
44352  result = ma_decoder_init_custom__internal(&config, pDecoder);
44353  if (result != MA_SUCCESS) {
44355  }
44356  }
44357 
44358  /*
44359  If we get to this point and we still haven't found a decoder, and the caller has requested a
44360  specific encoding format, there's no hope for it. Abort.
44361  */
44362  if (config.encodingFormat != ma_encoding_format_unknown) {
44363  return MA_NO_BACKEND;
44364  }
44365 
44366  #ifdef MA_HAS_WAV
44367  if (result != MA_SUCCESS && ma_path_extension_equal(pFilePath, "wav")) {
44368  result = ma_decoder_init_wav__internal(&config, pDecoder);
44369  if (result != MA_SUCCESS) {
44371  }
44372  }
44373  #endif
44374  #ifdef MA_HAS_FLAC
44375  if (result != MA_SUCCESS && ma_path_extension_equal(pFilePath, "flac")) {
44376  result = ma_decoder_init_flac__internal(&config, pDecoder);
44377  if (result != MA_SUCCESS) {
44379  }
44380  }
44381  #endif
44382  #ifdef MA_HAS_MP3
44383  if (result != MA_SUCCESS && ma_path_extension_equal(pFilePath, "mp3")) {
44384  result = ma_decoder_init_mp3__internal(&config, pDecoder);
44385  if (result != MA_SUCCESS) {
44387  }
44388  }
44389  #endif
44390  }
44391 
44392  /* If we still haven't got a result just use trial and error. Otherwise we can finish up. */
44393  if (result != MA_SUCCESS) {
44395  } else {
44396  result = ma_decoder__postinit(&config, pDecoder);
44397  }
44398 
44399  if (result != MA_SUCCESS) {
44400  if (pDecoder->data.vfs.file != NULL) { /* <-- Will be reset to NULL if ma_decoder_uninit() is called in one of the steps above which allows us to avoid a double close of the file. */
44401  ma_vfs_or_default_close(pVFS, pDecoder->data.vfs.file);
44402  }
44403 
44404  return result;
44405  }
44406 
44407  return MA_SUCCESS;
44408 }
44409 
44410 MA_API ma_result ma_decoder_init_vfs_wav(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44411 {
44412 #ifdef MA_HAS_WAV
44414 
44416  config.encodingFormat = ma_encoding_format_wav;
44417 
44418  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
44419 #else
44420  (void)pVFS;
44421  (void)pFilePath;
44422  (void)pConfig;
44423  (void)pDecoder;
44424  return MA_NO_BACKEND;
44425 #endif
44426 }
44427 
44428 MA_API ma_result ma_decoder_init_vfs_flac(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44429 {
44430 #ifdef MA_HAS_FLAC
44432 
44434  config.encodingFormat = ma_encoding_format_flac;
44435 
44436  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
44437 #else
44438  (void)pVFS;
44439  (void)pFilePath;
44440  (void)pConfig;
44441  (void)pDecoder;
44442  return MA_NO_BACKEND;
44443 #endif
44444 }
44445 
44446 MA_API ma_result ma_decoder_init_vfs_mp3(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44447 {
44448 #ifdef MA_HAS_MP3
44450 
44452  config.encodingFormat = ma_encoding_format_mp3;
44453 
44454  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
44455 #else
44456  (void)pVFS;
44457  (void)pFilePath;
44458  (void)pConfig;
44459  (void)pDecoder;
44460  return MA_NO_BACKEND;
44461 #endif
44462 }
44463 
44464 MA_API ma_result ma_decoder_init_vfs_vorbis(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44465 {
44466 #ifdef MA_HAS_VORBIS
44468 
44470  config.encodingFormat = ma_encoding_format_vorbis;
44471 
44472  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
44473 #else
44474  (void)pVFS;
44475  (void)pFilePath;
44476  (void)pConfig;
44477  (void)pDecoder;
44478  return MA_NO_BACKEND;
44479 #endif
44480 }
44481 
44482 
44483 
44484 static ma_result ma_decoder__preinit_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44485 {
44486  ma_result result;
44487  ma_vfs_file file;
44488 
44490  if (result != MA_SUCCESS) {
44491  return result;
44492  }
44493 
44494  if (pFilePath == NULL || pFilePath[0] == '\0') {
44495  return MA_INVALID_ARGS;
44496  }
44497 
44498  result = ma_vfs_or_default_open_w(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
44499  if (result != MA_SUCCESS) {
44500  return result;
44501  }
44502 
44503  pDecoder->data.vfs.pVFS = pVFS;
44504  pDecoder->data.vfs.file = file;
44505 
44506  return MA_SUCCESS;
44507 }
44508 
44509 MA_API ma_result ma_decoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44510 {
44511  ma_result result;
44513 
44515  result = ma_decoder__preinit_vfs_w(pVFS, pFilePath, &config, pDecoder);
44516  if (result != MA_SUCCESS) {
44517  return result;
44518  }
44519 
44520  result = MA_NO_BACKEND;
44521 
44522  if (config.encodingFormat != ma_encoding_format_unknown) {
44523  #ifdef MA_HAS_WAV
44524  if (config.encodingFormat == ma_encoding_format_wav) {
44525  result = ma_decoder_init_wav__internal(&config, pDecoder);
44526  }
44527  #endif
44528  #ifdef MA_HAS_FLAC
44529  if (config.encodingFormat == ma_encoding_format_flac) {
44530  result = ma_decoder_init_flac__internal(&config, pDecoder);
44531  }
44532  #endif
44533  #ifdef MA_HAS_MP3
44534  if (config.encodingFormat == ma_encoding_format_mp3) {
44535  result = ma_decoder_init_mp3__internal(&config, pDecoder);
44536  }
44537  #endif
44538  #ifdef MA_HAS_VORBIS
44539  if (config.encodingFormat == ma_encoding_format_vorbis) {
44540  result = ma_decoder_init_vorbis__internal(&config, pDecoder);
44541  }
44542  #endif
44543 
44544  /* Make sure we seek back to the start if we didn't initialize a decoder successfully so the next attempts have a fresh start. */
44545  if (result != MA_SUCCESS) {
44547  }
44548  }
44549 
44550  if (result != MA_SUCCESS) {
44551  /* Getting here means we weren't able to initialize a decoder of a specific encoding format. */
44552 
44553  /*
44554  We use trial and error to open a decoder. We prioritize custom decoders so that if they
44555  implement the same encoding format they take priority over the built-in decoders.
44556  */
44557  if (result != MA_SUCCESS) {
44558  result = ma_decoder_init_custom__internal(&config, pDecoder);
44559  if (result != MA_SUCCESS) {
44561  }
44562  }
44563 
44564  /*
44565  If we get to this point and we still haven't found a decoder, and the caller has requested a
44566  specific encoding format, there's no hope for it. Abort.
44567  */
44568  if (config.encodingFormat != ma_encoding_format_unknown) {
44569  return MA_NO_BACKEND;
44570  }
44571 
44572  #ifdef MA_HAS_WAV
44573  if (result != MA_SUCCESS && ma_path_extension_equal_w(pFilePath, L"wav")) {
44574  result = ma_decoder_init_wav__internal(&config, pDecoder);
44575  if (result != MA_SUCCESS) {
44577  }
44578  }
44579  #endif
44580  #ifdef MA_HAS_FLAC
44581  if (result != MA_SUCCESS && ma_path_extension_equal_w(pFilePath, L"flac")) {
44582  result = ma_decoder_init_flac__internal(&config, pDecoder);
44583  if (result != MA_SUCCESS) {
44585  }
44586  }
44587  #endif
44588  #ifdef MA_HAS_MP3
44589  if (result != MA_SUCCESS && ma_path_extension_equal_w(pFilePath, L"mp3")) {
44590  result = ma_decoder_init_mp3__internal(&config, pDecoder);
44591  if (result != MA_SUCCESS) {
44593  }
44594  }
44595  #endif
44596  }
44597 
44598  /* If we still haven't got a result just use trial and error. Otherwise we can finish up. */
44599  if (result != MA_SUCCESS) {
44601  } else {
44602  result = ma_decoder__postinit(&config, pDecoder);
44603  }
44604 
44605  if (result != MA_SUCCESS) {
44606  ma_vfs_or_default_close(pVFS, pDecoder->data.vfs.file);
44607  return result;
44608  }
44609 
44610  return MA_SUCCESS;
44611 }
44612 
44613 MA_API ma_result ma_decoder_init_vfs_wav_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44614 {
44615 #ifdef MA_HAS_WAV
44617 
44619  config.encodingFormat = ma_encoding_format_wav;
44620 
44621  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
44622 #else
44623  (void)pVFS;
44624  (void)pFilePath;
44625  (void)pConfig;
44626  (void)pDecoder;
44627  return MA_NO_BACKEND;
44628 #endif
44629 }
44630 
44631 MA_API ma_result ma_decoder_init_vfs_flac_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44632 {
44633 #ifdef MA_HAS_FLAC
44635 
44637  config.encodingFormat = ma_encoding_format_flac;
44638 
44639  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
44640 #else
44641  (void)pVFS;
44642  (void)pFilePath;
44643  (void)pConfig;
44644  (void)pDecoder;
44645  return MA_NO_BACKEND;
44646 #endif
44647 }
44648 
44649 MA_API ma_result ma_decoder_init_vfs_mp3_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44650 {
44651 #ifdef MA_HAS_MP3
44653 
44655  config.encodingFormat = ma_encoding_format_mp3;
44656 
44657  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
44658 #else
44659  (void)pVFS;
44660  (void)pFilePath;
44661  (void)pConfig;
44662  (void)pDecoder;
44663  return MA_NO_BACKEND;
44664 #endif
44665 }
44666 
44667 MA_API ma_result ma_decoder_init_vfs_vorbis_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44668 {
44669 #ifdef MA_HAS_VORBIS
44671 
44673  config.encodingFormat = ma_encoding_format_vorbis;
44674 
44675  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
44676 #else
44677  (void)pVFS;
44678  (void)pFilePath;
44679  (void)pConfig;
44680  (void)pDecoder;
44681  return MA_NO_BACKEND;
44682 #endif
44683 }
44684 
44685 
44686 
44687 MA_API ma_result ma_decoder_init_file(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44688 {
44689  return ma_decoder_init_vfs(NULL, pFilePath, pConfig, pDecoder);
44690 }
44691 
44692 MA_API ma_result ma_decoder_init_file_wav(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44693 {
44694  return ma_decoder_init_vfs_wav(NULL, pFilePath, pConfig, pDecoder);
44695 }
44696 
44697 MA_API ma_result ma_decoder_init_file_flac(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44698 {
44699  return ma_decoder_init_vfs_flac(NULL, pFilePath, pConfig, pDecoder);
44700 }
44701 
44702 MA_API ma_result ma_decoder_init_file_mp3(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44703 {
44704  return ma_decoder_init_vfs_mp3(NULL, pFilePath, pConfig, pDecoder);
44705 }
44706 
44707 MA_API ma_result ma_decoder_init_file_vorbis(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44708 {
44709  return ma_decoder_init_vfs_vorbis(NULL, pFilePath, pConfig, pDecoder);
44710 }
44711 
44712 
44713 
44714 MA_API ma_result ma_decoder_init_file_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44715 {
44716  return ma_decoder_init_vfs_w(NULL, pFilePath, pConfig, pDecoder);
44717 }
44718 
44719 MA_API ma_result ma_decoder_init_file_wav_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44720 {
44721  return ma_decoder_init_vfs_wav_w(NULL, pFilePath, pConfig, pDecoder);
44722 }
44723 
44724 MA_API ma_result ma_decoder_init_file_flac_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44725 {
44726  return ma_decoder_init_vfs_flac_w(NULL, pFilePath, pConfig, pDecoder);
44727 }
44728 
44729 MA_API ma_result ma_decoder_init_file_mp3_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44730 {
44731  return ma_decoder_init_vfs_mp3_w(NULL, pFilePath, pConfig, pDecoder);
44732 }
44733 
44734 MA_API ma_result ma_decoder_init_file_vorbis_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
44735 {
44736  return ma_decoder_init_vfs_vorbis_w(NULL, pFilePath, pConfig, pDecoder);
44737 }
44738 
44740 {
44741  if (pDecoder == NULL) {
44742  return MA_INVALID_ARGS;
44743  }
44744 
44745  if (pDecoder->pBackend != NULL) {
44746  if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onUninit != NULL) {
44747  pDecoder->pBackendVTable->onUninit(pDecoder->pBackendUserData, pDecoder->pBackend, &pDecoder->allocationCallbacks);
44748  }
44749  }
44750 
44751  /* Legacy. */
44752  if (pDecoder->onRead == ma_decoder__on_read_vfs) {
44753  ma_vfs_or_default_close(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file);
44754  pDecoder->data.vfs.file = NULL;
44755  }
44756 
44757  ma_data_converter_uninit(&pDecoder->converter);
44758  ma_data_source_uninit(&pDecoder->ds);
44759 
44760  return MA_SUCCESS;
44761 }
44762 
44764 {
44765  if (pCursor == NULL) {
44766  return MA_INVALID_ARGS;
44767  }
44768 
44769  *pCursor = 0;
44770 
44771  if (pDecoder == NULL) {
44772  return MA_INVALID_ARGS;
44773  }
44774 
44775  *pCursor = pDecoder->readPointerInPCMFrames;
44776 
44777  return MA_SUCCESS;
44778 }
44779 
44781 {
44782  if (pDecoder == NULL) {
44783  return 0;
44784  }
44785 
44786  if (pDecoder->pBackend != NULL) {
44787  ma_result result;
44788  ma_uint64 nativeLengthInPCMFrames;
44789  ma_uint32 internalSampleRate;
44790 
44791  ma_data_source_get_length_in_pcm_frames(pDecoder->pBackend, &nativeLengthInPCMFrames);
44792 
44793  result = ma_data_source_get_data_format(pDecoder->pBackend, NULL, NULL, &internalSampleRate);
44794  if (result != MA_SUCCESS) {
44795  return 0; /* Failed to retrieve the internal sample rate. */
44796  }
44797 
44798  if (internalSampleRate == pDecoder->outputSampleRate) {
44799  return nativeLengthInPCMFrames;
44800  } else {
44801  return ma_calculate_frame_count_after_resampling(pDecoder->outputSampleRate, internalSampleRate, nativeLengthInPCMFrames);
44802  }
44803  }
44804 
44805  return 0;
44806 }
44807 
44808 MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount)
44809 {
44810  ma_result result;
44811  ma_uint64 totalFramesReadOut;
44812  ma_uint64 totalFramesReadIn;
44813  void* pRunningFramesOut;
44814 
44815  if (pDecoder == NULL) {
44816  return 0;
44817  }
44818 
44819  if (pDecoder->pBackend == NULL) {
44820  return 0;
44821  }
44822 
44823  /* Fast path. */
44824  if (pDecoder->converter.isPassthrough) {
44825  result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pFramesOut, frameCount, &totalFramesReadOut, MA_FALSE);
44826  } else {
44827  /*
44828  Getting here means we need to do data conversion. If we're seeking forward and are _not_ doing resampling we can run this in a fast path. If we're doing resampling we
44829  need to run through each sample because we need to ensure it's internal cache is updated.
44830  */
44831  if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) {
44832  result = ma_data_source_read_pcm_frames(pDecoder->pBackend, NULL, frameCount, &totalFramesReadOut, MA_FALSE);
44833  } else {
44834  /* Slow path. Need to run everything through the data converter. */
44835  ma_format internalFormat;
44836  ma_uint32 internalChannels;
44837 
44838  totalFramesReadOut = 0;
44839  totalFramesReadIn = 0;
44840  pRunningFramesOut = pFramesOut;
44841 
44842  result = ma_data_source_get_data_format(pDecoder->pBackend, &internalFormat, &internalChannels, NULL);
44843  if (result != MA_SUCCESS) {
44844  return 0; /* Failed to retrieve the internal format and channel count. */
44845  }
44846 
44847  while (totalFramesReadOut < frameCount) {
44848  ma_uint8 pIntermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In internal format. */
44849  ma_uint64 intermediaryBufferCap = sizeof(pIntermediaryBuffer) / ma_get_bytes_per_frame(internalFormat, internalChannels);
44850  ma_uint64 framesToReadThisIterationIn;
44851  ma_uint64 framesReadThisIterationIn;
44852  ma_uint64 framesToReadThisIterationOut;
44853  ma_uint64 framesReadThisIterationOut;
44854  ma_uint64 requiredInputFrameCount;
44855 
44856  framesToReadThisIterationOut = (frameCount - totalFramesReadOut);
44857  framesToReadThisIterationIn = framesToReadThisIterationOut;
44858  if (framesToReadThisIterationIn > intermediaryBufferCap) {
44859  framesToReadThisIterationIn = intermediaryBufferCap;
44860  }
44861 
44862  requiredInputFrameCount = ma_data_converter_get_required_input_frame_count(&pDecoder->converter, framesToReadThisIterationOut);
44863  if (framesToReadThisIterationIn > requiredInputFrameCount) {
44864  framesToReadThisIterationIn = requiredInputFrameCount;
44865  }
44866 
44867  if (requiredInputFrameCount > 0) {
44868  result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn, MA_FALSE);
44869  totalFramesReadIn += framesReadThisIterationIn;
44870  } else {
44871  framesReadThisIterationIn = 0;
44872  }
44873 
44874  /*
44875  At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any
44876  input frames, we still want to try processing frames because there may some output frames generated from cached input data.
44877  */
44878  framesReadThisIterationOut = framesToReadThisIterationOut;
44879  result = ma_data_converter_process_pcm_frames(&pDecoder->converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
44880  if (result != MA_SUCCESS) {
44881  break;
44882  }
44883 
44884  totalFramesReadOut += framesReadThisIterationOut;
44885 
44886  if (pRunningFramesOut != NULL) {
44887  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels));
44888  }
44889 
44890  if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
44891  break; /* We're done. */
44892  }
44893  }
44894  }
44895  }
44896 
44897  pDecoder->readPointerInPCMFrames += totalFramesReadOut;
44898 
44899  return totalFramesReadOut;
44900 }
44901 
44903 {
44904  if (pDecoder == NULL) {
44905  return MA_INVALID_ARGS;
44906  }
44907 
44908  if (pDecoder->pBackend != NULL) {
44909  ma_result result;
44910  ma_uint64 internalFrameIndex;
44911  ma_uint32 internalSampleRate;
44912 
44913  result = ma_data_source_get_data_format(pDecoder->pBackend, NULL, NULL, &internalSampleRate);
44914  if (result != MA_SUCCESS) {
44915  return result; /* Failed to retrieve the internal sample rate. */
44916  }
44917 
44918  if (internalSampleRate == pDecoder->outputSampleRate) {
44919  internalFrameIndex = frameIndex;
44920  } else {
44921  internalFrameIndex = ma_calculate_frame_count_after_resampling(internalSampleRate, pDecoder->outputSampleRate, frameIndex);
44922  }
44923 
44924  result = ma_data_source_seek_to_pcm_frame(pDecoder->pBackend, internalFrameIndex);
44925  if (result == MA_SUCCESS) {
44926  pDecoder->readPointerInPCMFrames = frameIndex;
44927  }
44928 
44929  return result;
44930  }
44931 
44932  /* Should never get here, but if we do it means onSeekToPCMFrame was not set by the backend. */
44933  return MA_INVALID_ARGS;
44934 }
44935 
44937 {
44938  ma_uint64 totalFrameCount;
44939 
44940  if (pAvailableFrames == NULL) {
44941  return MA_INVALID_ARGS;
44942  }
44943 
44944  *pAvailableFrames = 0;
44945 
44946  if (pDecoder == NULL) {
44947  return MA_INVALID_ARGS;
44948  }
44949 
44950  totalFrameCount = ma_decoder_get_length_in_pcm_frames(pDecoder);
44951  if (totalFrameCount == 0) {
44952  return MA_NOT_IMPLEMENTED;
44953  }
44954 
44955  if (totalFrameCount <= pDecoder->readPointerInPCMFrames) {
44956  *pAvailableFrames = 0;
44957  } else {
44958  *pAvailableFrames = totalFrameCount - pDecoder->readPointerInPCMFrames;
44959  }
44960 
44961  return MA_SUCCESS; /* No frames available. */
44962 }
44963 
44964 
44965 static ma_result ma_decoder__full_decode_and_uninit(ma_decoder* pDecoder, ma_decoder_config* pConfigOut, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
44966 {
44967  ma_uint64 totalFrameCount;
44968  ma_uint64 bpf;
44969  ma_uint64 dataCapInFrames;
44970  void* pPCMFramesOut;
44971 
44972  MA_ASSERT(pDecoder != NULL);
44973 
44974  totalFrameCount = 0;
44975  bpf = ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels);
44976 
44977  /* The frame count is unknown until we try reading. Thus, we just run in a loop. */
44978  dataCapInFrames = 0;
44979  pPCMFramesOut = NULL;
44980  for (;;) {
44981  ma_uint64 frameCountToTryReading;
44982  ma_uint64 framesJustRead;
44983 
44984  /* Make room if there's not enough. */
44985  if (totalFrameCount == dataCapInFrames) {
44986  void* pNewPCMFramesOut;
44987  ma_uint64 oldDataCapInFrames = dataCapInFrames;
44988  ma_uint64 newDataCapInFrames = dataCapInFrames*2;
44989  if (newDataCapInFrames == 0) {
44990  newDataCapInFrames = 4096;
44991  }
44992 
44993  if ((newDataCapInFrames * bpf) > MA_SIZE_MAX) {
44994  ma__free_from_callbacks(pPCMFramesOut, &pDecoder->allocationCallbacks);
44995  return MA_TOO_BIG;
44996  }
44997 
44998 
44999  pNewPCMFramesOut = (void*)ma__realloc_from_callbacks(pPCMFramesOut, (size_t)(newDataCapInFrames * bpf), (size_t)(oldDataCapInFrames * bpf), &pDecoder->allocationCallbacks);
45000  if (pNewPCMFramesOut == NULL) {
45001  ma__free_from_callbacks(pPCMFramesOut, &pDecoder->allocationCallbacks);
45002  return MA_OUT_OF_MEMORY;
45003  }
45004 
45005  dataCapInFrames = newDataCapInFrames;
45006  pPCMFramesOut = pNewPCMFramesOut;
45007  }
45008 
45009  frameCountToTryReading = dataCapInFrames - totalFrameCount;
45010  MA_ASSERT(frameCountToTryReading > 0);
45011 
45012  framesJustRead = ma_decoder_read_pcm_frames(pDecoder, (ma_uint8*)pPCMFramesOut + (totalFrameCount * bpf), frameCountToTryReading);
45013  totalFrameCount += framesJustRead;
45014 
45015  if (framesJustRead < frameCountToTryReading) {
45016  break;
45017  }
45018  }
45019 
45020 
45021  if (pConfigOut != NULL) {
45022  pConfigOut->format = pDecoder->outputFormat;
45023  pConfigOut->channels = pDecoder->outputChannels;
45024  pConfigOut->sampleRate = pDecoder->outputSampleRate;
45025  ma_channel_map_copy(pConfigOut->channelMap, pDecoder->outputChannelMap, pDecoder->outputChannels);
45026  }
45027 
45028  if (ppPCMFramesOut != NULL) {
45029  *ppPCMFramesOut = pPCMFramesOut;
45030  } else {
45031  ma__free_from_callbacks(pPCMFramesOut, &pDecoder->allocationCallbacks);
45032  }
45033 
45034  if (pFrameCountOut != NULL) {
45035  *pFrameCountOut = totalFrameCount;
45036  }
45037 
45038  ma_decoder_uninit(pDecoder);
45039  return MA_SUCCESS;
45040 }
45041 
45042 MA_API ma_result ma_decode_from_vfs(ma_vfs* pVFS, const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
45043 {
45044  ma_result result;
45047 
45048  if (pFrameCountOut != NULL) {
45049  *pFrameCountOut = 0;
45050  }
45051  if (ppPCMFramesOut != NULL) {
45052  *ppPCMFramesOut = NULL;
45053  }
45054 
45056 
45057  result = ma_decoder_init_vfs(pVFS, pFilePath, &config, &decoder);
45058  if (result != MA_SUCCESS) {
45059  return result;
45060  }
45061 
45062  result = ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
45063 
45064  return result;
45065 }
45066 
45067 MA_API ma_result ma_decode_file(const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
45068 {
45069  return ma_decode_from_vfs(NULL, pFilePath, pConfig, pFrameCountOut, ppPCMFramesOut);
45070 }
45071 
45072 MA_API ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
45073 {
45076  ma_result result;
45077 
45078  if (pFrameCountOut != NULL) {
45079  *pFrameCountOut = 0;
45080  }
45081  if (ppPCMFramesOut != NULL) {
45082  *ppPCMFramesOut = NULL;
45083  }
45084 
45085  if (pData == NULL || dataSize == 0) {
45086  return MA_INVALID_ARGS;
45087  }
45088 
45090 
45091  result = ma_decoder_init_memory(pData, dataSize, &config, &decoder);
45092  if (result != MA_SUCCESS) {
45093  return result;
45094  }
45095 
45096  return ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
45097 }
45098 #endif /* MA_NO_DECODING */
45099 
45100 
45101 #ifndef MA_NO_ENCODING
45102 
45103 #if defined(MA_HAS_WAV)
45104 static size_t ma_encoder__internal_on_write_wav(void* pUserData, const void* pData, size_t bytesToWrite)
45105 {
45106  ma_encoder* pEncoder = (ma_encoder*)pUserData;
45107  MA_ASSERT(pEncoder != NULL);
45108 
45109  return pEncoder->onWrite(pEncoder, pData, bytesToWrite);
45110 }
45111 
45112 static drwav_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, drwav_seek_origin origin)
45113 {
45114  ma_encoder* pEncoder = (ma_encoder*)pUserData;
45115  MA_ASSERT(pEncoder != NULL);
45116 
45117  return pEncoder->onSeek(pEncoder, offset, (origin == drwav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current);
45118 }
45119 
45121 {
45122  drwav_data_format wavFormat;
45123  drwav_allocation_callbacks allocationCallbacks;
45124  drwav* pWav;
45125 
45126  MA_ASSERT(pEncoder != NULL);
45127 
45128  pWav = (drwav*)ma__malloc_from_callbacks(sizeof(*pWav), &pEncoder->config.allocationCallbacks);
45129  if (pWav == NULL) {
45130  return MA_OUT_OF_MEMORY;
45131  }
45132 
45133  wavFormat.container = drwav_container_riff;
45134  wavFormat.channels = pEncoder->config.channels;
45135  wavFormat.sampleRate = pEncoder->config.sampleRate;
45136  wavFormat.bitsPerSample = ma_get_bytes_per_sample(pEncoder->config.format) * 8;
45137  if (pEncoder->config.format == ma_format_f32) {
45138  wavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT;
45139  } else {
45140  wavFormat.format = DR_WAVE_FORMAT_PCM;
45141  }
45142 
45143  allocationCallbacks.pUserData = pEncoder->config.allocationCallbacks.pUserData;
45144  allocationCallbacks.onMalloc = pEncoder->config.allocationCallbacks.onMalloc;
45145  allocationCallbacks.onRealloc = pEncoder->config.allocationCallbacks.onRealloc;
45146  allocationCallbacks.onFree = pEncoder->config.allocationCallbacks.onFree;
45147 
45148  if (!drwav_init_write(pWav, &wavFormat, ma_encoder__internal_on_write_wav, ma_encoder__internal_on_seek_wav, pEncoder, &allocationCallbacks)) {
45149  return MA_ERROR;
45150  }
45151 
45152  pEncoder->pInternalEncoder = pWav;
45153 
45154  return MA_SUCCESS;
45155 }
45156 
45158 {
45159  drwav* pWav;
45160 
45161  MA_ASSERT(pEncoder != NULL);
45162 
45163  pWav = (drwav*)pEncoder->pInternalEncoder;
45164  MA_ASSERT(pWav != NULL);
45165 
45166  drwav_uninit(pWav);
45168 }
45169 
45170 static ma_uint64 ma_encoder__on_write_pcm_frames_wav(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount)
45171 {
45172  drwav* pWav;
45173 
45174  MA_ASSERT(pEncoder != NULL);
45175 
45176  pWav = (drwav*)pEncoder->pInternalEncoder;
45177  MA_ASSERT(pWav != NULL);
45178 
45179  return drwav_write_pcm_frames(pWav, frameCount, pFramesIn);
45180 }
45181 #endif
45182 
45184 {
45186 
45188  config.resourceFormat = resourceFormat;
45189  config.format = format;
45190  config.channels = channels;
45191  config.sampleRate = sampleRate;
45192 
45193  return config;
45194 }
45195 
45197 {
45198  ma_result result;
45199 
45200  if (pEncoder == NULL) {
45201  return MA_INVALID_ARGS;
45202  }
45203 
45204  MA_ZERO_OBJECT(pEncoder);
45205 
45206  if (pConfig == NULL) {
45207  return MA_INVALID_ARGS;
45208  }
45209 
45210  if (pConfig->format == ma_format_unknown || pConfig->channels == 0 || pConfig->sampleRate == 0) {
45211  return MA_INVALID_ARGS;
45212  }
45213 
45214  pEncoder->config = *pConfig;
45215 
45217  if (result != MA_SUCCESS) {
45218  return result;
45219  }
45220 
45221  return MA_SUCCESS;
45222 }
45223 
45225 {
45226  ma_result result = MA_SUCCESS;
45227 
45228  /* This assumes ma_encoder_preinit() has been called prior. */
45229  MA_ASSERT(pEncoder != NULL);
45230 
45231  if (onWrite == NULL || onSeek == NULL) {
45232  return MA_INVALID_ARGS;
45233  }
45234 
45235  pEncoder->onWrite = onWrite;
45236  pEncoder->onSeek = onSeek;
45237  pEncoder->pUserData = pUserData;
45238 
45239  switch (pEncoder->config.resourceFormat)
45240  {
45242  {
45243  #if defined(MA_HAS_WAV)
45244  pEncoder->onInit = ma_encoder__on_init_wav;
45245  pEncoder->onUninit = ma_encoder__on_uninit_wav;
45247  #else
45248  result = MA_NO_BACKEND;
45249  #endif
45250  } break;
45251 
45252  default:
45253  {
45254  result = MA_INVALID_ARGS;
45255  } break;
45256  }
45257 
45258  /* Getting here means we should have our backend callbacks set up. */
45259  if (result == MA_SUCCESS) {
45260  result = pEncoder->onInit(pEncoder);
45261  if (result != MA_SUCCESS) {
45262  return result;
45263  }
45264  }
45265 
45266  return MA_SUCCESS;
45267 }
45268 
45269 MA_API size_t ma_encoder__on_write_stdio(ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite)
45270 {
45271  return fwrite(pBufferIn, 1, bytesToWrite, (FILE*)pEncoder->pFile);
45272 }
45273 
45275 {
45276  return fseek((FILE*)pEncoder->pFile, byteOffset, (origin == ma_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
45277 }
45278 
45279 MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
45280 {
45281  ma_result result;
45282  FILE* pFile;
45283 
45284  result = ma_encoder_preinit(pConfig, pEncoder);
45285  if (result != MA_SUCCESS) {
45286  return result;
45287  }
45288 
45289  /* Now open the file. If this fails we don't need to uninitialize the encoder. */
45290  result = ma_fopen(&pFile, pFilePath, "wb");
45291  if (pFile == NULL) {
45292  return result;
45293  }
45294 
45295  pEncoder->pFile = pFile;
45296 
45298 }
45299 
45300 MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
45301 {
45302  ma_result result;
45303  FILE* pFile;
45304 
45305  result = ma_encoder_preinit(pConfig, pEncoder);
45306  if (result != MA_SUCCESS) {
45307  return result;
45308  }
45309 
45310  /* Now open the file. If this fails we don't need to uninitialize the encoder. */
45311  result = ma_wfopen(&pFile, pFilePath, L"wb", &pEncoder->config.allocationCallbacks);
45312  if (pFile == NULL) {
45313  return result;
45314  }
45315 
45316  pEncoder->pFile = pFile;
45317 
45319 }
45320 
45321 MA_API ma_result ma_encoder_init(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void* pUserData, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
45322 {
45323  ma_result result;
45324 
45325  result = ma_encoder_preinit(pConfig, pEncoder);
45326  if (result != MA_SUCCESS) {
45327  return result;
45328  }
45329 
45330  return ma_encoder_init__internal(onWrite, onSeek, pUserData, pEncoder);
45331 }
45332 
45333 
45335 {
45336  if (pEncoder == NULL) {
45337  return;
45338  }
45339 
45340  if (pEncoder->onUninit) {
45341  pEncoder->onUninit(pEncoder);
45342  }
45343 
45344  /* If we have a file handle, close it. */
45345  if (pEncoder->onWrite == ma_encoder__on_write_stdio) {
45346  fclose((FILE*)pEncoder->pFile);
45347  }
45348 }
45349 
45350 
45351 MA_API ma_uint64 ma_encoder_write_pcm_frames(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount)
45352 {
45353  if (pEncoder == NULL || pFramesIn == NULL) {
45354  return 0;
45355  }
45356 
45357  return pEncoder->onWritePCMFrames(pEncoder, pFramesIn, frameCount);
45358 }
45359 #endif /* MA_NO_ENCODING */
45360 
45361 
45362 
45363 /**************************************************************************************************************************************************************
45364 
45365 Generation
45366 
45367 **************************************************************************************************************************************************************/
45368 #ifndef MA_NO_GENERATION
45369 MA_API ma_waveform_config ma_waveform_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_waveform_type type, double amplitude, double frequency)
45370 {
45372 
45374  config.format = format;
45375  config.channels = channels;
45376  config.sampleRate = sampleRate;
45377  config.type = type;
45378  config.amplitude = amplitude;
45379  config.frequency = frequency;
45380 
45381  return config;
45382 }
45383 
45384 static ma_result ma_waveform__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
45385 {
45386  ma_uint64 framesRead = ma_waveform_read_pcm_frames((ma_waveform*)pDataSource, pFramesOut, frameCount);
45387 
45388  if (pFramesRead != NULL) {
45389  *pFramesRead = framesRead;
45390  }
45391 
45392  if (framesRead == 0) {
45393  return MA_AT_END;
45394  }
45395 
45396  return MA_SUCCESS;
45397 }
45398 
45400 {
45401  return ma_waveform_seek_to_pcm_frame((ma_waveform*)pDataSource, frameIndex);
45402 }
45403 
45405 {
45406  ma_waveform* pWaveform = (ma_waveform*)pDataSource;
45407 
45408  *pFormat = pWaveform->config.format;
45409  *pChannels = pWaveform->config.channels;
45410  *pSampleRate = pWaveform->config.sampleRate;
45411 
45412  return MA_SUCCESS;
45413 }
45414 
45416 {
45417  ma_waveform* pWaveform = (ma_waveform*)pDataSource;
45418 
45419  *pCursor = (ma_uint64)(pWaveform->time / pWaveform->advance);
45420 
45421  return MA_SUCCESS;
45422 }
45423 
45424 static double ma_waveform__calculate_advance(ma_uint32 sampleRate, double frequency)
45425 {
45426  return (1.0 / (sampleRate / frequency));
45427 }
45428 
45430 {
45431  pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
45432 }
45433 
45435 {
45438  NULL, /* onMap */
45439  NULL, /* onUnmap */
45442  NULL /* onGetLength. There's no notion of a length in waveforms. */
45443 };
45444 
45446 {
45447  ma_result result;
45448  ma_data_source_config dataSourceConfig;
45449 
45450  if (pWaveform == NULL) {
45451  return MA_INVALID_ARGS;
45452  }
45453 
45454  MA_ZERO_OBJECT(pWaveform);
45455 
45456  dataSourceConfig = ma_data_source_config_init();
45457  dataSourceConfig.vtable = &g_ma_waveform_data_source_vtable;
45458 
45459  result = ma_data_source_init(&dataSourceConfig, &pWaveform->ds);
45460  if (result != MA_SUCCESS) {
45461  return result;
45462  }
45463 
45464  pWaveform->config = *pConfig;
45465  pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
45466  pWaveform->time = 0;
45467 
45468  return MA_SUCCESS;
45469 }
45470 
45472 {
45473  if (pWaveform == NULL) {
45474  return;
45475  }
45476 
45477  ma_data_source_uninit(&pWaveform->ds);
45478 }
45479 
45481 {
45482  if (pWaveform == NULL) {
45483  return MA_INVALID_ARGS;
45484  }
45485 
45486  pWaveform->config.amplitude = amplitude;
45487  return MA_SUCCESS;
45488 }
45489 
45491 {
45492  if (pWaveform == NULL) {
45493  return MA_INVALID_ARGS;
45494  }
45495 
45496  pWaveform->config.frequency = frequency;
45497  ma_waveform__update_advance(pWaveform);
45498 
45499  return MA_SUCCESS;
45500 }
45501 
45503 {
45504  if (pWaveform == NULL) {
45505  return MA_INVALID_ARGS;
45506  }
45507 
45508  pWaveform->config.type = type;
45509  return MA_SUCCESS;
45510 }
45511 
45513 {
45514  if (pWaveform == NULL) {
45515  return MA_INVALID_ARGS;
45516  }
45517 
45518  pWaveform->config.sampleRate = sampleRate;
45519  ma_waveform__update_advance(pWaveform);
45520 
45521  return MA_SUCCESS;
45522 }
45523 
45524 static float ma_waveform_sine_f32(double time, double amplitude)
45525 {
45526  return (float)(ma_sind(MA_TAU_D * time) * amplitude);
45527 }
45528 
45529 static ma_int16 ma_waveform_sine_s16(double time, double amplitude)
45530 {
45531  return ma_pcm_sample_f32_to_s16(ma_waveform_sine_f32(time, amplitude));
45532 }
45533 
45534 static float ma_waveform_square_f32(double time, double amplitude)
45535 {
45536  double f = time - (ma_int64)time;
45537  double r;
45538 
45539  if (f < 0.5) {
45540  r = amplitude;
45541  } else {
45542  r = -amplitude;
45543  }
45544 
45545  return (float)r;
45546 }
45547 
45548 static ma_int16 ma_waveform_square_s16(double time, double amplitude)
45549 {
45550  return ma_pcm_sample_f32_to_s16(ma_waveform_square_f32(time, amplitude));
45551 }
45552 
45553 static float ma_waveform_triangle_f32(double time, double amplitude)
45554 {
45555  double f = time - (ma_int64)time;
45556  double r;
45557 
45558  r = 2 * ma_abs(2 * (f - 0.5)) - 1;
45559 
45560  return (float)(r * amplitude);
45561 }
45562 
45563 static ma_int16 ma_waveform_triangle_s16(double time, double amplitude)
45564 {
45565  return ma_pcm_sample_f32_to_s16(ma_waveform_triangle_f32(time, amplitude));
45566 }
45567 
45568 static float ma_waveform_sawtooth_f32(double time, double amplitude)
45569 {
45570  double f = time - (ma_int64)time;
45571  double r;
45572 
45573  r = 2 * (f - 0.5);
45574 
45575  return (float)(r * amplitude);
45576 }
45577 
45578 static ma_int16 ma_waveform_sawtooth_s16(double time, double amplitude)
45579 {
45580  return ma_pcm_sample_f32_to_s16(ma_waveform_sawtooth_f32(time, amplitude));
45581 }
45582 
45583 static void ma_waveform_read_pcm_frames__sine(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
45584 {
45585  ma_uint64 iFrame;
45586  ma_uint64 iChannel;
45587  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
45588  ma_uint32 bpf = bps * pWaveform->config.channels;
45589 
45590  MA_ASSERT(pWaveform != NULL);
45591  MA_ASSERT(pFramesOut != NULL);
45592 
45593  if (pWaveform->config.format == ma_format_f32) {
45594  float* pFramesOutF32 = (float*)pFramesOut;
45595  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45596  float s = ma_waveform_sine_f32(pWaveform->time, pWaveform->config.amplitude);
45597  pWaveform->time += pWaveform->advance;
45598 
45599  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45600  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
45601  }
45602  }
45603  } else if (pWaveform->config.format == ma_format_s16) {
45604  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
45605  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45606  ma_int16 s = ma_waveform_sine_s16(pWaveform->time, pWaveform->config.amplitude);
45607  pWaveform->time += pWaveform->advance;
45608 
45609  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45610  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
45611  }
45612  }
45613  } else {
45614  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45615  float s = ma_waveform_sine_f32(pWaveform->time, pWaveform->config.amplitude);
45616  pWaveform->time += pWaveform->advance;
45617 
45618  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45619  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
45620  }
45621  }
45622  }
45623 }
45624 
45625 static void ma_waveform_read_pcm_frames__square(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
45626 {
45627  ma_uint64 iFrame;
45628  ma_uint64 iChannel;
45629  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
45630  ma_uint32 bpf = bps * pWaveform->config.channels;
45631 
45632  MA_ASSERT(pWaveform != NULL);
45633  MA_ASSERT(pFramesOut != NULL);
45634 
45635  if (pWaveform->config.format == ma_format_f32) {
45636  float* pFramesOutF32 = (float*)pFramesOut;
45637  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45638  float s = ma_waveform_square_f32(pWaveform->time, pWaveform->config.amplitude);
45639  pWaveform->time += pWaveform->advance;
45640 
45641  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45642  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
45643  }
45644  }
45645  } else if (pWaveform->config.format == ma_format_s16) {
45646  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
45647  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45648  ma_int16 s = ma_waveform_square_s16(pWaveform->time, pWaveform->config.amplitude);
45649  pWaveform->time += pWaveform->advance;
45650 
45651  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45652  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
45653  }
45654  }
45655  } else {
45656  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45657  float s = ma_waveform_square_f32(pWaveform->time, pWaveform->config.amplitude);
45658  pWaveform->time += pWaveform->advance;
45659 
45660  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45661  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
45662  }
45663  }
45664  }
45665 }
45666 
45667 static void ma_waveform_read_pcm_frames__triangle(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
45668 {
45669  ma_uint64 iFrame;
45670  ma_uint64 iChannel;
45671  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
45672  ma_uint32 bpf = bps * pWaveform->config.channels;
45673 
45674  MA_ASSERT(pWaveform != NULL);
45675  MA_ASSERT(pFramesOut != NULL);
45676 
45677  if (pWaveform->config.format == ma_format_f32) {
45678  float* pFramesOutF32 = (float*)pFramesOut;
45679  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45680  float s = ma_waveform_triangle_f32(pWaveform->time, pWaveform->config.amplitude);
45681  pWaveform->time += pWaveform->advance;
45682 
45683  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45684  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
45685  }
45686  }
45687  } else if (pWaveform->config.format == ma_format_s16) {
45688  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
45689  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45690  ma_int16 s = ma_waveform_triangle_s16(pWaveform->time, pWaveform->config.amplitude);
45691  pWaveform->time += pWaveform->advance;
45692 
45693  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45694  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
45695  }
45696  }
45697  } else {
45698  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45699  float s = ma_waveform_triangle_f32(pWaveform->time, pWaveform->config.amplitude);
45700  pWaveform->time += pWaveform->advance;
45701 
45702  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45703  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
45704  }
45705  }
45706  }
45707 }
45708 
45709 static void ma_waveform_read_pcm_frames__sawtooth(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
45710 {
45711  ma_uint64 iFrame;
45712  ma_uint64 iChannel;
45713  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
45714  ma_uint32 bpf = bps * pWaveform->config.channels;
45715 
45716  MA_ASSERT(pWaveform != NULL);
45717  MA_ASSERT(pFramesOut != NULL);
45718 
45719  if (pWaveform->config.format == ma_format_f32) {
45720  float* pFramesOutF32 = (float*)pFramesOut;
45721  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45722  float s = ma_waveform_sawtooth_f32(pWaveform->time, pWaveform->config.amplitude);
45723  pWaveform->time += pWaveform->advance;
45724 
45725  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45726  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
45727  }
45728  }
45729  } else if (pWaveform->config.format == ma_format_s16) {
45730  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
45731  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45732  ma_int16 s = ma_waveform_sawtooth_s16(pWaveform->time, pWaveform->config.amplitude);
45733  pWaveform->time += pWaveform->advance;
45734 
45735  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45736  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
45737  }
45738  }
45739  } else {
45740  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45741  float s = ma_waveform_sawtooth_f32(pWaveform->time, pWaveform->config.amplitude);
45742  pWaveform->time += pWaveform->advance;
45743 
45744  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
45745  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
45746  }
45747  }
45748  }
45749 }
45750 
45751 MA_API ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
45752 {
45753  if (pWaveform == NULL) {
45754  return 0;
45755  }
45756 
45757  if (pFramesOut != NULL) {
45758  switch (pWaveform->config.type)
45759  {
45760  case ma_waveform_type_sine:
45761  {
45762  ma_waveform_read_pcm_frames__sine(pWaveform, pFramesOut, frameCount);
45763  } break;
45764 
45766  {
45767  ma_waveform_read_pcm_frames__square(pWaveform, pFramesOut, frameCount);
45768  } break;
45769 
45771  {
45772  ma_waveform_read_pcm_frames__triangle(pWaveform, pFramesOut, frameCount);
45773  } break;
45774 
45776  {
45777  ma_waveform_read_pcm_frames__sawtooth(pWaveform, pFramesOut, frameCount);
45778  } break;
45779 
45780  default: return 0;
45781  }
45782  } else {
45783  pWaveform->time += pWaveform->advance * (ma_int64)frameCount; /* Cast to int64 required for VC6. Won't affect anything in practice. */
45784  }
45785 
45786  return frameCount;
45787 }
45788 
45790 {
45791  if (pWaveform == NULL) {
45792  return MA_INVALID_ARGS;
45793  }
45794 
45795  pWaveform->time = pWaveform->advance * (ma_int64)frameIndex; /* Casting for VC6. Won't be an issue in practice. */
45796 
45797  return MA_SUCCESS;
45798 }
45799 
45800 
45802 {
45805 
45806  config.format = format;
45807  config.channels = channels;
45808  config.type = type;
45809  config.seed = seed;
45810  config.amplitude = amplitude;
45811 
45812  if (config.seed == 0) {
45813  config.seed = MA_DEFAULT_LCG_SEED;
45814  }
45815 
45816  return config;
45817 }
45818 
45819 
45820 static ma_result ma_noise__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
45821 {
45822  ma_uint64 framesRead = ma_noise_read_pcm_frames((ma_noise*)pDataSource, pFramesOut, frameCount);
45823 
45824  if (pFramesRead != NULL) {
45825  *pFramesRead = framesRead;
45826  }
45827 
45828  if (framesRead == 0) {
45829  return MA_AT_END;
45830  }
45831 
45832  return MA_SUCCESS;
45833 }
45834 
45836 {
45837  /* No-op. Just pretend to be successful. */
45838  (void)pDataSource;
45839  (void)frameIndex;
45840  return MA_SUCCESS;
45841 }
45842 
45843 static ma_result ma_noise__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
45844 {
45845  ma_noise* pNoise = (ma_noise*)pDataSource;
45846 
45847  *pFormat = pNoise->config.format;
45848  *pChannels = pNoise->config.channels;
45849  *pSampleRate = 0; /* There is no notion of sample rate with noise generation. */
45850 
45851  return MA_SUCCESS;
45852 }
45853 
45855 {
45857  ma_noise__data_source_on_seek, /* No-op for noise. */
45858  NULL, /* onMap */
45859  NULL, /* onUnmap */
45861  NULL, /* onGetCursor. No notion of a cursor for noise. */
45862  NULL /* onGetLength. No notion of a length for noise. */
45863 };
45864 
45866 {
45867  ma_result result;
45868  ma_data_source_config dataSourceConfig;
45869 
45870  if (pNoise == NULL) {
45871  return MA_INVALID_ARGS;
45872  }
45873 
45874  MA_ZERO_OBJECT(pNoise);
45875 
45876  if (pConfig == NULL) {
45877  return MA_INVALID_ARGS;
45878  }
45879 
45880  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
45881  return MA_INVALID_ARGS;
45882  }
45883 
45884  dataSourceConfig = ma_data_source_config_init();
45885  dataSourceConfig.vtable = &g_ma_noise_data_source_vtable;
45886 
45887  result = ma_data_source_init(&dataSourceConfig, &pNoise->ds);
45888  if (result != MA_SUCCESS) {
45889  return result;
45890  }
45891 
45892  pNoise->config = *pConfig;
45893  ma_lcg_seed(&pNoise->lcg, pConfig->seed);
45894 
45895  if (pNoise->config.type == ma_noise_type_pink) {
45896  ma_uint32 iChannel;
45897  for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
45898  pNoise->state.pink.accumulation[iChannel] = 0;
45899  pNoise->state.pink.counter[iChannel] = 1;
45900  }
45901  }
45902 
45903  if (pNoise->config.type == ma_noise_type_brownian) {
45904  ma_uint32 iChannel;
45905  for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
45906  pNoise->state.brownian.accumulation[iChannel] = 0;
45907  }
45908  }
45909 
45910  return MA_SUCCESS;
45911 }
45912 
45914 {
45915  if (pNoise == NULL) {
45916  return;
45917  }
45918 
45919  ma_data_source_uninit(&pNoise->ds);
45920 }
45921 
45923 {
45924  if (pNoise == NULL) {
45925  return MA_INVALID_ARGS;
45926  }
45927 
45928  pNoise->config.amplitude = amplitude;
45929  return MA_SUCCESS;
45930 }
45931 
45933 {
45934  if (pNoise == NULL) {
45935  return MA_INVALID_ARGS;
45936  }
45937 
45938  pNoise->lcg.state = seed;
45939  return MA_SUCCESS;
45940 }
45941 
45942 
45944 {
45945  if (pNoise == NULL) {
45946  return MA_INVALID_ARGS;
45947  }
45948 
45949  pNoise->config.type = type;
45950  return MA_SUCCESS;
45951 }
45952 
45954 {
45955  return (float)(ma_lcg_rand_f64(&pNoise->lcg) * pNoise->config.amplitude);
45956 }
45957 
45959 {
45961 }
45962 
45963 static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__white(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
45964 {
45965  ma_uint64 iFrame;
45966  ma_uint32 iChannel;
45967  const ma_uint32 channels = pNoise->config.channels;
45968  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
45969 
45970  if (pNoise->config.format == ma_format_f32) {
45971  float* pFramesOutF32 = (float*)pFramesOut;
45972  if (pNoise->config.duplicateChannels) {
45973  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45974  float s = ma_noise_f32_white(pNoise);
45975  for (iChannel = 0; iChannel < channels; iChannel += 1) {
45976  pFramesOutF32[iFrame*channels + iChannel] = s;
45977  }
45978  }
45979  } else {
45980  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45981  for (iChannel = 0; iChannel < channels; iChannel += 1) {
45982  pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_white(pNoise);
45983  }
45984  }
45985  }
45986  } else if (pNoise->config.format == ma_format_s16) {
45987  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
45988  if (pNoise->config.duplicateChannels) {
45989  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45990  ma_int16 s = ma_noise_s16_white(pNoise);
45991  for (iChannel = 0; iChannel < channels; iChannel += 1) {
45992  pFramesOutS16[iFrame*channels + iChannel] = s;
45993  }
45994  }
45995  } else {
45996  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
45997  for (iChannel = 0; iChannel < channels; iChannel += 1) {
45998  pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_white(pNoise);
45999  }
46000  }
46001  }
46002  } else {
46003  const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
46004  const ma_uint32 bpf = bps * channels;
46005 
46006  if (pNoise->config.duplicateChannels) {
46007  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46008  float s = ma_noise_f32_white(pNoise);
46009  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46010  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
46011  }
46012  }
46013  } else {
46014  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46015  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46016  float s = ma_noise_f32_white(pNoise);
46017  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
46018  }
46019  }
46020  }
46021  }
46022 
46023  return frameCount;
46024 }
46025 
46026 
46027 static MA_INLINE unsigned int ma_tzcnt32(unsigned int x)
46028 {
46029  unsigned int n;
46030 
46031  /* Special case for odd numbers since they should happen about half the time. */
46032  if (x & 0x1) {
46033  return 0;
46034  }
46035 
46036  if (x == 0) {
46037  return sizeof(x) << 3;
46038  }
46039 
46040  n = 1;
46041  if ((x & 0x0000FFFF) == 0) { x >>= 16; n += 16; }
46042  if ((x & 0x000000FF) == 0) { x >>= 8; n += 8; }
46043  if ((x & 0x0000000F) == 0) { x >>= 4; n += 4; }
46044  if ((x & 0x00000003) == 0) { x >>= 2; n += 2; }
46045  n -= x & 0x00000001;
46046 
46047  return n;
46048 }
46049 
46050 /*
46051 Pink noise generation based on Tonic (public domain) with modifications. https://github.com/TonicAudio/Tonic/blob/master/src/Tonic/Noise.h
46052 
46053 This is basically _the_ reference for pink noise from what I've found: http://www.firstpr.com.au/dsp/pink-noise/
46054 */
46055 static MA_INLINE float ma_noise_f32_pink(ma_noise* pNoise, ma_uint32 iChannel)
46056 {
46057  double result;
46058  double binPrev;
46059  double binNext;
46060  unsigned int ibin;
46061 
46062  ibin = ma_tzcnt32(pNoise->state.pink.counter[iChannel]) & (ma_countof(pNoise->state.pink.bin[0]) - 1);
46063 
46064  binPrev = pNoise->state.pink.bin[iChannel][ibin];
46065  binNext = ma_lcg_rand_f64(&pNoise->lcg);
46066  pNoise->state.pink.bin[iChannel][ibin] = binNext;
46067 
46068  pNoise->state.pink.accumulation[iChannel] += (binNext - binPrev);
46069  pNoise->state.pink.counter[iChannel] += 1;
46070 
46071  result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.pink.accumulation[iChannel]);
46072  result /= 10;
46073 
46074  return (float)(result * pNoise->config.amplitude);
46075 }
46076 
46078 {
46079  return ma_pcm_sample_f32_to_s16(ma_noise_f32_pink(pNoise, iChannel));
46080 }
46081 
46082 static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__pink(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
46083 {
46084  ma_uint64 iFrame;
46085  ma_uint32 iChannel;
46086  const ma_uint32 channels = pNoise->config.channels;
46087  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
46088 
46089  if (pNoise->config.format == ma_format_f32) {
46090  float* pFramesOutF32 = (float*)pFramesOut;
46091  if (pNoise->config.duplicateChannels) {
46092  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46093  float s = ma_noise_f32_pink(pNoise, 0);
46094  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46095  pFramesOutF32[iFrame*channels + iChannel] = s;
46096  }
46097  }
46098  } else {
46099  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46100  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46101  pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_pink(pNoise, iChannel);
46102  }
46103  }
46104  }
46105  } else if (pNoise->config.format == ma_format_s16) {
46106  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
46107  if (pNoise->config.duplicateChannels) {
46108  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46109  ma_int16 s = ma_noise_s16_pink(pNoise, 0);
46110  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46111  pFramesOutS16[iFrame*channels + iChannel] = s;
46112  }
46113  }
46114  } else {
46115  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46116  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46117  pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_pink(pNoise, iChannel);
46118  }
46119  }
46120  }
46121  } else {
46122  const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
46123  const ma_uint32 bpf = bps * channels;
46124 
46125  if (pNoise->config.duplicateChannels) {
46126  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46127  float s = ma_noise_f32_pink(pNoise, 0);
46128  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46129  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
46130  }
46131  }
46132  } else {
46133  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46134  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46135  float s = ma_noise_f32_pink(pNoise, iChannel);
46136  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
46137  }
46138  }
46139  }
46140  }
46141 
46142  return frameCount;
46143 }
46144 
46145 
46146 static MA_INLINE float ma_noise_f32_brownian(ma_noise* pNoise, ma_uint32 iChannel)
46147 {
46148  double result;
46149 
46150  result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.brownian.accumulation[iChannel]);
46151  result /= 1.005; /* Don't escape the -1..1 range on average. */
46152 
46153  pNoise->state.brownian.accumulation[iChannel] = result;
46154  result /= 20;
46155 
46156  return (float)(result * pNoise->config.amplitude);
46157 }
46158 
46160 {
46161  return ma_pcm_sample_f32_to_s16(ma_noise_f32_brownian(pNoise, iChannel));
46162 }
46163 
46164 static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__brownian(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
46165 {
46166  ma_uint64 iFrame;
46167  ma_uint32 iChannel;
46168  const ma_uint32 channels = pNoise->config.channels;
46169  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
46170 
46171  if (pNoise->config.format == ma_format_f32) {
46172  float* pFramesOutF32 = (float*)pFramesOut;
46173  if (pNoise->config.duplicateChannels) {
46174  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46175  float s = ma_noise_f32_brownian(pNoise, 0);
46176  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46177  pFramesOutF32[iFrame*channels + iChannel] = s;
46178  }
46179  }
46180  } else {
46181  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46182  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46183  pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_brownian(pNoise, iChannel);
46184  }
46185  }
46186  }
46187  } else if (pNoise->config.format == ma_format_s16) {
46188  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
46189  if (pNoise->config.duplicateChannels) {
46190  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46191  ma_int16 s = ma_noise_s16_brownian(pNoise, 0);
46192  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46193  pFramesOutS16[iFrame*channels + iChannel] = s;
46194  }
46195  }
46196  } else {
46197  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46198  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46199  pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_brownian(pNoise, iChannel);
46200  }
46201  }
46202  }
46203  } else {
46204  const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
46205  const ma_uint32 bpf = bps * channels;
46206 
46207  if (pNoise->config.duplicateChannels) {
46208  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46209  float s = ma_noise_f32_brownian(pNoise, 0);
46210  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46211  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
46212  }
46213  }
46214  } else {
46215  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
46216  for (iChannel = 0; iChannel < channels; iChannel += 1) {
46217  float s = ma_noise_f32_brownian(pNoise, iChannel);
46218  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
46219  }
46220  }
46221  }
46222  }
46223 
46224  return frameCount;
46225 }
46226 
46227 MA_API ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
46228 {
46229  if (pNoise == NULL) {
46230  return 0;
46231  }
46232 
46233  /* The output buffer is allowed to be NULL. Since we aren't tracking cursors or anything we can just do nothing and pretend to be successful. */
46234  if (pFramesOut == NULL) {
46235  return frameCount;
46236  }
46237 
46238  if (pNoise->config.type == ma_noise_type_white) {
46239  return ma_noise_read_pcm_frames__white(pNoise, pFramesOut, frameCount);
46240  }
46241 
46242  if (pNoise->config.type == ma_noise_type_pink) {
46243  return ma_noise_read_pcm_frames__pink(pNoise, pFramesOut, frameCount);
46244  }
46245 
46246  if (pNoise->config.type == ma_noise_type_brownian) {
46247  return ma_noise_read_pcm_frames__brownian(pNoise, pFramesOut, frameCount);
46248  }
46249 
46250  /* Should never get here. */
46252  return 0;
46253 }
46254 #endif /* MA_NO_GENERATION */
46255 
46256 
46257 
46258 /**************************************************************************************************************************************************************
46259 ***************************************************************************************************************************************************************
46260 
46261 Auto Generated
46262 ==============
46263 All code below is auto-generated from a tool. This mostly consists of decoding backend implementations such as dr_wav, dr_flac, etc. If you find a bug in the
46264 code below please report the bug to the respective repository for the relevant project (probably dr_libs).
46265 
46266 ***************************************************************************************************************************************************************
46267 **************************************************************************************************************************************************************/
46268 #if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING))
46269 #if !defined(DR_WAV_IMPLEMENTATION) && !defined(DRWAV_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
46270 /* dr_wav_c begin */
46271 #ifndef dr_wav_c
46272 #define dr_wav_c
46273 #include <stdlib.h>
46274 #include <string.h>
46275 #include <limits.h>
46276 #ifndef DR_WAV_NO_STDIO
46277 #include <stdio.h>
46278 #include <wchar.h>
46279 #endif
46280 #ifndef DRWAV_ASSERT
46281 #include <assert.h>
46282 #define DRWAV_ASSERT(expression) assert(expression)
46283 #endif
46284 #ifndef DRWAV_MALLOC
46285 #define DRWAV_MALLOC(sz) malloc((sz))
46286 #endif
46287 #ifndef DRWAV_REALLOC
46288 #define DRWAV_REALLOC(p, sz) realloc((p), (sz))
46289 #endif
46290 #ifndef DRWAV_FREE
46291 #define DRWAV_FREE(p) free((p))
46292 #endif
46293 #ifndef DRWAV_COPY_MEMORY
46294 #define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
46295 #endif
46296 #ifndef DRWAV_ZERO_MEMORY
46297 #define DRWAV_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
46298 #endif
46299 #ifndef DRWAV_ZERO_OBJECT
46300 #define DRWAV_ZERO_OBJECT(p) DRWAV_ZERO_MEMORY((p), sizeof(*p))
46301 #endif
46302 #define drwav_countof(x) (sizeof(x) / sizeof(x[0]))
46303 #define drwav_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
46304 #define drwav_min(a, b) (((a) < (b)) ? (a) : (b))
46305 #define drwav_max(a, b) (((a) > (b)) ? (a) : (b))
46306 #define drwav_clamp(x, lo, hi) (drwav_max((lo), drwav_min((hi), (x))))
46307 #define DRWAV_MAX_SIMD_VECTOR_SIZE 64
46308 #if defined(__x86_64__) || defined(_M_X64)
46309  #define DRWAV_X64
46310 #elif defined(__i386) || defined(_M_IX86)
46311  #define DRWAV_X86
46312 #elif defined(__arm__) || defined(_M_ARM)
46313  #define DRWAV_ARM
46314 #endif
46315 #ifdef _MSC_VER
46316  #define DRWAV_INLINE __forceinline
46317 #elif defined(__GNUC__)
46318  #if defined(__STRICT_ANSI__)
46319  #define DRWAV_INLINE __inline__ __attribute__((always_inline))
46320  #else
46321  #define DRWAV_INLINE inline __attribute__((always_inline))
46322  #endif
46323 #elif defined(__WATCOMC__)
46324  #define DRWAV_INLINE __inline
46325 #else
46326  #define DRWAV_INLINE
46327 #endif
46328 #if defined(SIZE_MAX)
46329  #define DRWAV_SIZE_MAX SIZE_MAX
46330 #else
46331  #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
46332  #define DRWAV_SIZE_MAX ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
46333  #else
46334  #define DRWAV_SIZE_MAX 0xFFFFFFFF
46335  #endif
46336 #endif
46337 #if defined(_MSC_VER) && _MSC_VER >= 1400
46338  #define DRWAV_HAS_BYTESWAP16_INTRINSIC
46339  #define DRWAV_HAS_BYTESWAP32_INTRINSIC
46340  #define DRWAV_HAS_BYTESWAP64_INTRINSIC
46341 #elif defined(__clang__)
46342  #if defined(__has_builtin)
46343  #if __has_builtin(__builtin_bswap16)
46344  #define DRWAV_HAS_BYTESWAP16_INTRINSIC
46345  #endif
46346  #if __has_builtin(__builtin_bswap32)
46347  #define DRWAV_HAS_BYTESWAP32_INTRINSIC
46348  #endif
46349  #if __has_builtin(__builtin_bswap64)
46350  #define DRWAV_HAS_BYTESWAP64_INTRINSIC
46351  #endif
46352  #endif
46353 #elif defined(__GNUC__)
46354  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
46355  #define DRWAV_HAS_BYTESWAP32_INTRINSIC
46356  #define DRWAV_HAS_BYTESWAP64_INTRINSIC
46357  #endif
46358  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
46359  #define DRWAV_HAS_BYTESWAP16_INTRINSIC
46360  #endif
46361 #endif
46363 {
46364  if (pMajor) {
46365  *pMajor = DRWAV_VERSION_MAJOR;
46366  }
46367  if (pMinor) {
46368  *pMinor = DRWAV_VERSION_MINOR;
46369  }
46370  if (pRevision) {
46371  *pRevision = DRWAV_VERSION_REVISION;
46372  }
46373 }
46375 {
46376  return DRWAV_VERSION_STRING;
46377 }
46378 #ifndef DRWAV_MAX_SAMPLE_RATE
46379 #define DRWAV_MAX_SAMPLE_RATE 384000
46380 #endif
46381 #ifndef DRWAV_MAX_CHANNELS
46382 #define DRWAV_MAX_CHANNELS 256
46383 #endif
46384 #ifndef DRWAV_MAX_BITS_PER_SAMPLE
46385 #define DRWAV_MAX_BITS_PER_SAMPLE 64
46386 #endif
46387 static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00};
46388 static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
46389 static const drwav_uint8 drwavGUID_W64_FMT [16] = {0x66,0x6D,0x74,0x20, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
46390 static const drwav_uint8 drwavGUID_W64_FACT[16] = {0x66,0x61,0x63,0x74, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
46391 static const drwav_uint8 drwavGUID_W64_DATA[16] = {0x64,0x61,0x74,0x61, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
46393 {
46394 #if defined(DRWAV_X86) || defined(DRWAV_X64)
46395  return DRWAV_TRUE;
46396 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
46397  return DRWAV_TRUE;
46398 #else
46399  int n = 1;
46400  return (*(char*)&n) == 1;
46401 #endif
46402 }
46404 {
46405  int i;
46406  for (i = 0; i < 16; ++i) {
46407  guid[i] = data[i];
46408  }
46409 }
46411 {
46412 #ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
46413  #if defined(_MSC_VER)
46414  return _byteswap_ushort(n);
46415  #elif defined(__GNUC__) || defined(__clang__)
46416  return __builtin_bswap16(n);
46417  #else
46418  #error "This compiler does not support the byte swap intrinsic."
46419  #endif
46420 #else
46421  return ((n & 0xFF00) >> 8) |
46422  ((n & 0x00FF) << 8);
46423 #endif
46424 }
46426 {
46427 #ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
46428  #if defined(_MSC_VER)
46429  return _byteswap_ulong(n);
46430  #elif defined(__GNUC__) || defined(__clang__)
46431  #if defined(DRWAV_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRWAV_64BIT)
46432  drwav_uint32 r;
46433  __asm__ __volatile__ (
46434  #if defined(DRWAV_64BIT)
46435  "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n)
46436  #else
46437  "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
46438  #endif
46439  );
46440  return r;
46441  #else
46442  return __builtin_bswap32(n);
46443  #endif
46444  #else
46445  #error "This compiler does not support the byte swap intrinsic."
46446  #endif
46447 #else
46448  return ((n & 0xFF000000) >> 24) |
46449  ((n & 0x00FF0000) >> 8) |
46450  ((n & 0x0000FF00) << 8) |
46451  ((n & 0x000000FF) << 24);
46452 #endif
46453 }
46455 {
46456 #ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
46457  #if defined(_MSC_VER)
46458  return _byteswap_uint64(n);
46459  #elif defined(__GNUC__) || defined(__clang__)
46460  return __builtin_bswap64(n);
46461  #else
46462  #error "This compiler does not support the byte swap intrinsic."
46463  #endif
46464 #else
46465  return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
46466  ((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
46467  ((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
46468  ((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
46469  ((n & ((drwav_uint64)0xFF000000 )) << 8) |
46470  ((n & ((drwav_uint64)0x00FF0000 )) << 24) |
46471  ((n & ((drwav_uint64)0x0000FF00 )) << 40) |
46472  ((n & ((drwav_uint64)0x000000FF )) << 56);
46473 #endif
46474 }
46476 {
46478 }
46480 {
46481  drwav_uint64 iSample;
46482  for (iSample = 0; iSample < sampleCount; iSample += 1) {
46483  pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
46484  }
46485 }
46487 {
46488  drwav_uint8 t;
46489  t = p[0];
46490  p[0] = p[2];
46491  p[2] = t;
46492 }
46494 {
46495  drwav_uint64 iSample;
46496  for (iSample = 0; iSample < sampleCount; iSample += 1) {
46497  drwav_uint8* pSample = pSamples + (iSample*3);
46498  drwav__bswap_s24(pSample);
46499  }
46500 }
46502 {
46504 }
46506 {
46507  drwav_uint64 iSample;
46508  for (iSample = 0; iSample < sampleCount; iSample += 1) {
46509  pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
46510  }
46511 }
46512 static DRWAV_INLINE float drwav__bswap_f32(float n)
46513 {
46514  union {
46515  drwav_uint32 i;
46516  float f;
46517  } x;
46518  x.f = n;
46519  x.i = drwav__bswap32(x.i);
46520  return x.f;
46521 }
46522 static DRWAV_INLINE void drwav__bswap_samples_f32(float* pSamples, drwav_uint64 sampleCount)
46523 {
46524  drwav_uint64 iSample;
46525  for (iSample = 0; iSample < sampleCount; iSample += 1) {
46526  pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
46527  }
46528 }
46529 static DRWAV_INLINE double drwav__bswap_f64(double n)
46530 {
46531  union {
46532  drwav_uint64 i;
46533  double f;
46534  } x;
46535  x.f = n;
46536  x.i = drwav__bswap64(x.i);
46537  return x.f;
46538 }
46539 static DRWAV_INLINE void drwav__bswap_samples_f64(double* pSamples, drwav_uint64 sampleCount)
46540 {
46541  drwav_uint64 iSample;
46542  for (iSample = 0; iSample < sampleCount; iSample += 1) {
46543  pSamples[iSample] = drwav__bswap_f64(pSamples[iSample]);
46544  }
46545 }
46546 static DRWAV_INLINE void drwav__bswap_samples_pcm(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
46547 {
46548  switch (bytesPerSample)
46549  {
46550  case 2:
46551  {
46552  drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
46553  } break;
46554  case 3:
46555  {
46556  drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
46557  } break;
46558  case 4:
46559  {
46560  drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
46561  } break;
46562  default:
46563  {
46565  } break;
46566  }
46567 }
46568 static DRWAV_INLINE void drwav__bswap_samples_ieee(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
46569 {
46570  switch (bytesPerSample)
46571  {
46572  #if 0
46573  case 2:
46574  {
46575  drwav__bswap_samples_f16((drwav_float16*)pSamples, sampleCount);
46576  } break;
46577  #endif
46578  case 4:
46579  {
46580  drwav__bswap_samples_f32((float*)pSamples, sampleCount);
46581  } break;
46582  case 8:
46583  {
46584  drwav__bswap_samples_f64((double*)pSamples, sampleCount);
46585  } break;
46586  default:
46587  {
46589  } break;
46590  }
46591 }
46592 static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample, drwav_uint16 format)
46593 {
46594  switch (format)
46595  {
46596  case DR_WAVE_FORMAT_PCM:
46597  {
46598  drwav__bswap_samples_pcm(pSamples, sampleCount, bytesPerSample);
46599  } break;
46601  {
46602  drwav__bswap_samples_ieee(pSamples, sampleCount, bytesPerSample);
46603  } break;
46604  case DR_WAVE_FORMAT_ALAW:
46605  case DR_WAVE_FORMAT_MULAW:
46606  {
46607  drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
46608  } break;
46609  case DR_WAVE_FORMAT_ADPCM:
46611  default:
46612  {
46614  } break;
46615  }
46616 }
46617 DRWAV_PRIVATE void* drwav__malloc_default(size_t sz, void* pUserData)
46618 {
46619  (void)pUserData;
46620  return DRWAV_MALLOC(sz);
46621 }
46622 DRWAV_PRIVATE void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
46623 {
46624  (void)pUserData;
46625  return DRWAV_REALLOC(p, sz);
46626 }
46627 DRWAV_PRIVATE void drwav__free_default(void* p, void* pUserData)
46628 {
46629  (void)pUserData;
46630  DRWAV_FREE(p);
46631 }
46632 DRWAV_PRIVATE void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
46633 {
46634  if (pAllocationCallbacks == NULL) {
46635  return NULL;
46636  }
46637  if (pAllocationCallbacks->onMalloc != NULL) {
46638  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
46639  }
46640  if (pAllocationCallbacks->onRealloc != NULL) {
46641  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
46642  }
46643  return NULL;
46644 }
46645 DRWAV_PRIVATE void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
46646 {
46647  if (pAllocationCallbacks == NULL) {
46648  return NULL;
46649  }
46650  if (pAllocationCallbacks->onRealloc != NULL) {
46651  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
46652  }
46653  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
46654  void* p2;
46655  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
46656  if (p2 == NULL) {
46657  return NULL;
46658  }
46659  if (p != NULL) {
46660  DRWAV_COPY_MEMORY(p2, p, szOld);
46661  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
46662  }
46663  return p2;
46664  }
46665  return NULL;
46666 }
46667 DRWAV_PRIVATE void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
46668 {
46669  if (p == NULL || pAllocationCallbacks == NULL) {
46670  return;
46671  }
46672  if (pAllocationCallbacks->onFree != NULL) {
46673  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
46674  }
46675 }
46677 {
46678  if (pAllocationCallbacks != NULL) {
46679  return *pAllocationCallbacks;
46680  } else {
46681  drwav_allocation_callbacks allocationCallbacks;
46682  allocationCallbacks.pUserData = NULL;
46683  allocationCallbacks.onMalloc = drwav__malloc_default;
46684  allocationCallbacks.onRealloc = drwav__realloc_default;
46685  allocationCallbacks.onFree = drwav__free_default;
46686  return allocationCallbacks;
46687  }
46688 }
46690 {
46691  return
46692  formatTag == DR_WAVE_FORMAT_ADPCM ||
46693  formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
46694 }
46696 {
46697  return (unsigned int)(chunkSize % 2);
46698 }
46700 {
46701  return (unsigned int)(chunkSize % 8);
46702 }
46706 DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
46707 {
46708  if (container == drwav_container_riff || container == drwav_container_rf64) {
46709  drwav_uint8 sizeInBytes[4];
46710  if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
46711  return DRWAV_AT_END;
46712  }
46713  if (onRead(pUserData, sizeInBytes, 4) != 4) {
46714  return DRWAV_INVALID_FILE;
46715  }
46716  pHeaderOut->sizeInBytes = drwav_bytes_to_u32(sizeInBytes);
46717  pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
46718  *pRunningBytesReadOut += 8;
46719  } else {
46720  drwav_uint8 sizeInBytes[8];
46721  if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
46722  return DRWAV_AT_END;
46723  }
46724  if (onRead(pUserData, sizeInBytes, 8) != 8) {
46725  return DRWAV_INVALID_FILE;
46726  }
46727  pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24;
46728  pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
46729  *pRunningBytesReadOut += 24;
46730  }
46731  return DRWAV_SUCCESS;
46732 }
46734 {
46735  drwav_uint64 bytesRemainingToSeek = offset;
46736  while (bytesRemainingToSeek > 0) {
46737  if (bytesRemainingToSeek > 0x7FFFFFFF) {
46738  if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
46739  return DRWAV_FALSE;
46740  }
46741  bytesRemainingToSeek -= 0x7FFFFFFF;
46742  } else {
46743  if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
46744  return DRWAV_FALSE;
46745  }
46746  bytesRemainingToSeek = 0;
46747  }
46748  }
46749  return DRWAV_TRUE;
46750 }
46752 {
46753  if (offset <= 0x7FFFFFFF) {
46754  return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
46755  }
46756  if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
46757  return DRWAV_FALSE;
46758  }
46759  offset -= 0x7FFFFFFF;
46760  for (;;) {
46761  if (offset <= 0x7FFFFFFF) {
46762  return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
46763  }
46764  if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
46765  return DRWAV_FALSE;
46766  }
46767  offset -= 0x7FFFFFFF;
46768  }
46769 }
46770 DRWAV_PRIVATE drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_fmt* fmtOut)
46771 {
46773  drwav_uint8 fmt[16];
46774  if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
46775  return DRWAV_FALSE;
46776  }
46777  while (((container == drwav_container_riff || container == drwav_container_rf64) && !drwav_fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
46778  if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
46779  return DRWAV_FALSE;
46780  }
46781  *pRunningBytesReadOut += header.sizeInBytes + header.paddingSize;
46782  if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
46783  return DRWAV_FALSE;
46784  }
46785  }
46786  if (container == drwav_container_riff || container == drwav_container_rf64) {
46787  if (!drwav_fourcc_equal(header.id.fourcc, "fmt ")) {
46788  return DRWAV_FALSE;
46789  }
46790  } else {
46791  if (!drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT)) {
46792  return DRWAV_FALSE;
46793  }
46794  }
46795  if (onRead(pUserData, fmt, sizeof(fmt)) != sizeof(fmt)) {
46796  return DRWAV_FALSE;
46797  }
46798  *pRunningBytesReadOut += sizeof(fmt);
46799  fmtOut->formatTag = drwav_bytes_to_u16(fmt + 0);
46800  fmtOut->channels = drwav_bytes_to_u16(fmt + 2);
46801  fmtOut->sampleRate = drwav_bytes_to_u32(fmt + 4);
46802  fmtOut->avgBytesPerSec = drwav_bytes_to_u32(fmt + 8);
46803  fmtOut->blockAlign = drwav_bytes_to_u16(fmt + 12);
46804  fmtOut->bitsPerSample = drwav_bytes_to_u16(fmt + 14);
46805  fmtOut->extendedSize = 0;
46806  fmtOut->validBitsPerSample = 0;
46807  fmtOut->channelMask = 0;
46808  memset(fmtOut->subFormat, 0, sizeof(fmtOut->subFormat));
46809  if (header.sizeInBytes > 16) {
46810  drwav_uint8 fmt_cbSize[2];
46811  int bytesReadSoFar = 0;
46812  if (onRead(pUserData, fmt_cbSize, sizeof(fmt_cbSize)) != sizeof(fmt_cbSize)) {
46813  return DRWAV_FALSE;
46814  }
46815  *pRunningBytesReadOut += sizeof(fmt_cbSize);
46816  bytesReadSoFar = 18;
46817  fmtOut->extendedSize = drwav_bytes_to_u16(fmt_cbSize);
46818  if (fmtOut->extendedSize > 0) {
46819  if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
46820  if (fmtOut->extendedSize != 22) {
46821  return DRWAV_FALSE;
46822  }
46823  }
46824  if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
46825  drwav_uint8 fmtext[22];
46826  if (onRead(pUserData, fmtext, fmtOut->extendedSize) != fmtOut->extendedSize) {
46827  return DRWAV_FALSE;
46828  }
46829  fmtOut->validBitsPerSample = drwav_bytes_to_u16(fmtext + 0);
46830  fmtOut->channelMask = drwav_bytes_to_u32(fmtext + 2);
46831  drwav_bytes_to_guid(fmtext + 6, fmtOut->subFormat);
46832  } else {
46833  if (!onSeek(pUserData, fmtOut->extendedSize, drwav_seek_origin_current)) {
46834  return DRWAV_FALSE;
46835  }
46836  }
46837  *pRunningBytesReadOut += fmtOut->extendedSize;
46838  bytesReadSoFar += fmtOut->extendedSize;
46839  }
46840  if (!onSeek(pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current)) {
46841  return DRWAV_FALSE;
46842  }
46843  *pRunningBytesReadOut += (header.sizeInBytes - bytesReadSoFar);
46844  }
46845  if (header.paddingSize > 0) {
46846  if (!onSeek(pUserData, header.paddingSize, drwav_seek_origin_current)) {
46847  return DRWAV_FALSE;
46848  }
46849  *pRunningBytesReadOut += header.paddingSize;
46850  }
46851  return DRWAV_TRUE;
46852 }
46853 DRWAV_PRIVATE size_t drwav__on_read(drwav_read_proc onRead, void* pUserData, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
46854 {
46855  size_t bytesRead;
46856  DRWAV_ASSERT(onRead != NULL);
46857  DRWAV_ASSERT(pCursor != NULL);
46858  bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
46859  *pCursor += bytesRead;
46860  return bytesRead;
46861 }
46862 #if 0
46863 DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserData, int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
46864 {
46865  DRWAV_ASSERT(onSeek != NULL);
46866  DRWAV_ASSERT(pCursor != NULL);
46867  if (!onSeek(pUserData, offset, origin)) {
46868  return DRWAV_FALSE;
46869  }
46870  if (origin == drwav_seek_origin_start) {
46871  *pCursor = offset;
46872  } else {
46873  *pCursor += offset;
46874  }
46875  return DRWAV_TRUE;
46876 }
46877 #endif
46878 #define DRWAV_SMPL_BYTES 36
46879 #define DRWAV_SMPL_LOOP_BYTES 24
46880 #define DRWAV_INST_BYTES 7
46881 #define DRWAV_ACID_BYTES 24
46882 #define DRWAV_CUE_BYTES 4
46883 #define DRWAV_BEXT_BYTES 602
46884 #define DRWAV_BEXT_DESCRIPTION_BYTES 256
46885 #define DRWAV_BEXT_ORIGINATOR_NAME_BYTES 32
46886 #define DRWAV_BEXT_ORIGINATOR_REF_BYTES 32
46887 #define DRWAV_BEXT_RESERVED_BYTES 180
46888 #define DRWAV_BEXT_UMID_BYTES 64
46889 #define DRWAV_CUE_POINT_BYTES 24
46890 #define DRWAV_LIST_LABEL_OR_NOTE_BYTES 4
46891 #define DRWAV_LIST_LABELLED_TEXT_BYTES 20
46892 #define DRWAV_METADATA_ALIGNMENT 8
46893 typedef enum
46894 {
46898 typedef struct
46899 {
46912 {
46913  drwav_uint64 cap = sizeof(drwav_metadata) * (drwav_uint64)pParser->metadataCount + pParser->extraCapacity;
46914  if (cap > DRWAV_SIZE_MAX) {
46915  return 0;
46916  }
46917  return (size_t)cap;
46918 }
46920 {
46921  drwav_uint8* pResult;
46922  if (align) {
46923  drwav_uintptr modulo = (drwav_uintptr)pParser->pDataCursor % align;
46924  if (modulo != 0) {
46925  pParser->pDataCursor += align - modulo;
46926  }
46927  }
46928  pResult = pParser->pDataCursor;
46929  DRWAV_ASSERT((pResult + size) <= (pParser->pData + drwav__metadata_memory_capacity(pParser)));
46930  pParser->pDataCursor += size;
46931  return pResult;
46932 }
46934 {
46935  size_t extra = bytes + (align ? (align - 1) : 0);
46936  pParser->extraCapacity += extra;
46937 }
46939 {
46940  if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
46941  free(pParser->pData);
46942  pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
46943  pParser->pDataCursor = pParser->pData;
46944  if (pParser->pData == NULL) {
46945  return DRWAV_OUT_OF_MEMORY;
46946  }
46947  pParser->pMetadata = (drwav_metadata*)drwav__metadata_get_memory(pParser, sizeof(drwav_metadata) * pParser->metadataCount, 1);
46948  pParser->metadataCursor = 0;
46949  }
46950  return DRWAV_SUCCESS;
46951 }
46952 DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
46953 {
46954  if (pCursor != NULL) {
46955  return drwav__on_read(pParser->onRead, pParser->pReadSeekUserData, pBufferOut, bytesToRead, pCursor);
46956  } else {
46957  return pParser->onRead(pParser->pReadSeekUserData, pBufferOut, bytesToRead);
46958  }
46959 }
46961 {
46962  drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
46963  drwav_uint64 totalBytesRead = 0;
46964  size_t bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
46966  if (bytesJustRead == sizeof(smplHeaderData)) {
46967  drwav_uint32 iSampleLoop;
46968  pMetadata->type = drwav_metadata_type_smpl;
46969  pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
46970  pMetadata->data.smpl.productId = drwav_bytes_to_u32(smplHeaderData + 4);
46971  pMetadata->data.smpl.samplePeriodNanoseconds = drwav_bytes_to_u32(smplHeaderData + 8);
46972  pMetadata->data.smpl.midiUnityNote = drwav_bytes_to_u32(smplHeaderData + 12);
46973  pMetadata->data.smpl.midiPitchFraction = drwav_bytes_to_u32(smplHeaderData + 16);
46974  pMetadata->data.smpl.smpteFormat = drwav_bytes_to_u32(smplHeaderData + 20);
46975  pMetadata->data.smpl.smpteOffset = drwav_bytes_to_u32(smplHeaderData + 24);
46976  pMetadata->data.smpl.sampleLoopCount = drwav_bytes_to_u32(smplHeaderData + 28);
46977  pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
46979  for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
46980  drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
46981  bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
46982  if (bytesJustRead == sizeof(smplLoopData)) {
46983  pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
46984  pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
46985  pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
46986  pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
46987  pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
46988  pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
46989  } else {
46990  break;
46991  }
46992  }
46993  if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
46996  bytesJustRead = drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
46997  }
46998  }
46999  return totalBytesRead;
47000 }
47002 {
47003  drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
47004  drwav_uint64 totalBytesRead = 0;
47005  size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData, sizeof(cueHeaderSectionData), &totalBytesRead);
47007  if (bytesJustRead == sizeof(cueHeaderSectionData)) {
47008  pMetadata->type = drwav_metadata_type_cue;
47009  pMetadata->data.cue.cuePointCount = drwav_bytes_to_u32(cueHeaderSectionData);
47011  DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
47012  if (pMetadata->data.cue.cuePointCount > 0) {
47013  drwav_uint32 iCuePoint;
47014  for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
47015  drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
47016  bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData, sizeof(cuePointData), &totalBytesRead);
47017  if (bytesJustRead == sizeof(cuePointData)) {
47018  pMetadata->data.cue.pCuePoints[iCuePoint].id = drwav_bytes_to_u32(cuePointData + 0);
47019  pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
47020  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0] = cuePointData[8];
47021  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1] = cuePointData[9];
47022  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2] = cuePointData[10];
47023  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
47024  pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
47025  pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
47026  pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
47027  } else {
47028  break;
47029  }
47030  }
47031  }
47032  }
47033  return totalBytesRead;
47034 }
47036 {
47037  drwav_uint8 instData[DRWAV_INST_BYTES];
47038  drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, instData, sizeof(instData), NULL);
47040  if (bytesRead == sizeof(instData)) {
47041  pMetadata->type = drwav_metadata_type_inst;
47042  pMetadata->data.inst.midiUnityNote = (drwav_int8)instData[0];
47043  pMetadata->data.inst.fineTuneCents = (drwav_int8)instData[1];
47044  pMetadata->data.inst.gainDecibels = (drwav_int8)instData[2];
47045  pMetadata->data.inst.lowNote = (drwav_int8)instData[3];
47046  pMetadata->data.inst.highNote = (drwav_int8)instData[4];
47047  pMetadata->data.inst.lowVelocity = (drwav_int8)instData[5];
47048  pMetadata->data.inst.highVelocity = (drwav_int8)instData[6];
47049  }
47050  return bytesRead;
47051 }
47053 {
47054  drwav_uint8 acidData[DRWAV_ACID_BYTES];
47055  drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
47057  if (bytesRead == sizeof(acidData)) {
47058  pMetadata->type = drwav_metadata_type_acid;
47059  pMetadata->data.acid.flags = drwav_bytes_to_u32(acidData + 0);
47060  pMetadata->data.acid.midiUnityNote = drwav_bytes_to_u16(acidData + 4);
47061  pMetadata->data.acid.reserved1 = drwav_bytes_to_u16(acidData + 6);
47062  pMetadata->data.acid.reserved2 = drwav_bytes_to_f32(acidData + 8);
47063  pMetadata->data.acid.numBeats = drwav_bytes_to_u32(acidData + 12);
47064  pMetadata->data.acid.meterDenominator = drwav_bytes_to_u16(acidData + 16);
47065  pMetadata->data.acid.meterNumerator = drwav_bytes_to_u16(acidData + 18);
47066  pMetadata->data.acid.tempo = drwav_bytes_to_f32(acidData + 20);
47067  }
47068  return bytesRead;
47069 }
47070 DRWAV_PRIVATE size_t drwav__strlen_clamped(char* str, size_t maxToRead)
47071 {
47072  size_t result = 0;
47073  while (*str++ && result < maxToRead) {
47074  result += 1;
47075  }
47076  return result;
47077 }
47078 DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, char* str, size_t maxToRead)
47079 {
47080  size_t len = drwav__strlen_clamped(str, maxToRead);
47081  if (len) {
47082  char* result = (char*)drwav__metadata_get_memory(pParser, len + 1, 1);
47083  DRWAV_ASSERT(result != NULL);
47084  memcpy(result, str, len);
47085  result[len] = '\0';
47086  return result;
47087  } else {
47088  return NULL;
47089  }
47090 }
47092 {
47093  drwav_uint8 bextData[DRWAV_BEXT_BYTES];
47094  drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
47096  if (bytesRead == sizeof(bextData)) {
47097  drwav_uint8* pReadPointer;
47098  drwav_uint32 timeReferenceLow;
47099  drwav_uint32 timeReferenceHigh;
47100  size_t extraBytes;
47101  pMetadata->type = drwav_metadata_type_bext;
47102  pReadPointer = bextData;
47103  pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_DESCRIPTION_BYTES);
47104  pReadPointer += DRWAV_BEXT_DESCRIPTION_BYTES;
47105  pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
47106  pReadPointer += DRWAV_BEXT_ORIGINATOR_NAME_BYTES;
47107  pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
47108  pReadPointer += DRWAV_BEXT_ORIGINATOR_REF_BYTES;
47109  memcpy(pReadPointer, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate));
47110  pReadPointer += sizeof(pMetadata->data.bext.pOriginationDate);
47111  memcpy(pReadPointer, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime));
47112  pReadPointer += sizeof(pMetadata->data.bext.pOriginationTime);
47113  timeReferenceLow = drwav_bytes_to_u32(pReadPointer);
47114  pReadPointer += sizeof(drwav_uint32);
47115  timeReferenceHigh = drwav_bytes_to_u32(pReadPointer);
47116  pReadPointer += sizeof(drwav_uint32);
47117  pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
47118  pMetadata->data.bext.version = drwav_bytes_to_u16(pReadPointer);
47119  pReadPointer += sizeof(drwav_uint16);
47121  memcpy(pMetadata->data.bext.pUMID, pReadPointer, DRWAV_BEXT_UMID_BYTES);
47122  pReadPointer += DRWAV_BEXT_UMID_BYTES;
47123  pMetadata->data.bext.loudnessValue = drwav_bytes_to_u16(pReadPointer);
47124  pReadPointer += sizeof(drwav_uint16);
47125  pMetadata->data.bext.loudnessRange = drwav_bytes_to_u16(pReadPointer);
47126  pReadPointer += sizeof(drwav_uint16);
47127  pMetadata->data.bext.maxTruePeakLevel = drwav_bytes_to_u16(pReadPointer);
47128  pReadPointer += sizeof(drwav_uint16);
47129  pMetadata->data.bext.maxMomentaryLoudness = drwav_bytes_to_u16(pReadPointer);
47130  pReadPointer += sizeof(drwav_uint16);
47131  pMetadata->data.bext.maxShortTermLoudness = drwav_bytes_to_u16(pReadPointer);
47132  pReadPointer += sizeof(drwav_uint16);
47133  DRWAV_ASSERT((pReadPointer + DRWAV_BEXT_RESERVED_BYTES) == (bextData + DRWAV_BEXT_BYTES));
47134  extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
47135  if (extraBytes > 0) {
47136  pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
47137  DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
47138  bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
47139  pMetadata->data.bext.codingHistorySize = (drwav_uint32)strlen(pMetadata->data.bext.pCodingHistory);
47140  } else {
47141  pMetadata->data.bext.pCodingHistory = NULL;
47142  pMetadata->data.bext.codingHistorySize = 0;
47143  }
47144  }
47145  return bytesRead;
47146 }
47148 {
47149  drwav_uint8 cueIDBuffer[DRWAV_LIST_LABEL_OR_NOTE_BYTES];
47150  drwav_uint64 totalBytesRead = 0;
47151  size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueIDBuffer, sizeof(cueIDBuffer), &totalBytesRead);
47153  if (bytesJustRead == sizeof(cueIDBuffer)) {
47154  drwav_uint32 sizeIncludingNullTerminator;
47155  pMetadata->type = type;
47156  pMetadata->data.labelOrNote.cuePointId = drwav_bytes_to_u32(cueIDBuffer);
47157  sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
47158  if (sizeIncludingNullTerminator > 0) {
47159  pMetadata->data.labelOrNote.stringLength = sizeIncludingNullTerminator - 1;
47160  pMetadata->data.labelOrNote.pString = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
47161  DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
47162  bytesJustRead = drwav__metadata_parser_read(pParser, pMetadata->data.labelOrNote.pString, sizeIncludingNullTerminator, &totalBytesRead);
47163  } else {
47164  pMetadata->data.labelOrNote.stringLength = 0;
47165  pMetadata->data.labelOrNote.pString = NULL;
47166  }
47167  }
47168  return totalBytesRead;
47169 }
47171 {
47172  drwav_uint8 buffer[DRWAV_LIST_LABELLED_TEXT_BYTES];
47173  drwav_uint64 totalBytesRead = 0;
47174  size_t bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &totalBytesRead);
47176  if (bytesJustRead == sizeof(buffer)) {
47177  drwav_uint32 sizeIncludingNullTerminator;
47179  pMetadata->data.labelledCueRegion.cuePointId = drwav_bytes_to_u32(buffer + 0);
47180  pMetadata->data.labelledCueRegion.sampleLength = drwav_bytes_to_u32(buffer + 4);
47181  pMetadata->data.labelledCueRegion.purposeId[0] = buffer[8];
47182  pMetadata->data.labelledCueRegion.purposeId[1] = buffer[9];
47183  pMetadata->data.labelledCueRegion.purposeId[2] = buffer[10];
47184  pMetadata->data.labelledCueRegion.purposeId[3] = buffer[11];
47185  pMetadata->data.labelledCueRegion.country = drwav_bytes_to_u16(buffer + 12);
47186  pMetadata->data.labelledCueRegion.language = drwav_bytes_to_u16(buffer + 14);
47187  pMetadata->data.labelledCueRegion.dialect = drwav_bytes_to_u16(buffer + 16);
47188  pMetadata->data.labelledCueRegion.codePage = drwav_bytes_to_u16(buffer + 18);
47189  sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
47190  if (sizeIncludingNullTerminator > 0) {
47191  pMetadata->data.labelledCueRegion.stringLength = sizeIncludingNullTerminator - 1;
47192  pMetadata->data.labelledCueRegion.pString = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
47194  bytesJustRead = drwav__metadata_parser_read(pParser, pMetadata->data.labelledCueRegion.pString, sizeIncludingNullTerminator, &totalBytesRead);
47195  } else {
47196  pMetadata->data.labelledCueRegion.stringLength = 0;
47197  pMetadata->data.labelledCueRegion.pString = NULL;
47198  }
47199  }
47200  return totalBytesRead;
47201 }
47203 {
47204  drwav_uint64 bytesRead = 0;
47205  drwav_uint32 stringSizeWithNullTerminator = (drwav_uint32)chunkSize;
47206  if (pParser->stage == drwav__metadata_parser_stage_count) {
47207  pParser->metadataCount += 1;
47208  drwav__metadata_request_extra_memory_for_stage_2(pParser, stringSizeWithNullTerminator, 1);
47209  } else {
47210  drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
47211  pMetadata->type = type;
47212  if (stringSizeWithNullTerminator > 0) {
47213  pMetadata->data.infoText.stringLength = stringSizeWithNullTerminator - 1;
47214  pMetadata->data.infoText.pString = (char*)drwav__metadata_get_memory(pParser, stringSizeWithNullTerminator, 1);
47215  DRWAV_ASSERT(pMetadata->data.infoText.pString != NULL);
47216  bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.infoText.pString, (size_t)stringSizeWithNullTerminator, NULL);
47217  if (bytesRead == chunkSize) {
47218  pParser->metadataCursor += 1;
47219  } else {
47220  }
47221  } else {
47222  pMetadata->data.infoText.stringLength = 0;
47223  pMetadata->data.infoText.pString = NULL;
47224  pParser->metadataCursor += 1;
47225  }
47226  }
47227  return bytesRead;
47228 }
47230 {
47231  drwav_uint64 bytesRead = 0;
47232  if (location == drwav_metadata_location_invalid) {
47233  return 0;
47234  }
47235  if (drwav_fourcc_equal(pChunkId, "data") || drwav_fourcc_equal(pChunkId, "fmt") || drwav_fourcc_equal(pChunkId, "fact")) {
47236  return 0;
47237  }
47238  if (pParser->stage == drwav__metadata_parser_stage_count) {
47239  pParser->metadataCount += 1;
47240  drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)chunkSize, 1);
47241  } else {
47242  drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
47243  pMetadata->type = drwav_metadata_type_unknown;
47244  pMetadata->data.unknown.chunkLocation = location;
47245  pMetadata->data.unknown.id[0] = pChunkId[0];
47246  pMetadata->data.unknown.id[1] = pChunkId[1];
47247  pMetadata->data.unknown.id[2] = pChunkId[2];
47248  pMetadata->data.unknown.id[3] = pChunkId[3];
47249  pMetadata->data.unknown.dataSizeInBytes = (drwav_uint32)chunkSize;
47250  pMetadata->data.unknown.pData = (drwav_uint8 *)drwav__metadata_get_memory(pParser, (size_t)chunkSize, 1);
47251  DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
47252  bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes, NULL);
47253  if (bytesRead == pMetadata->data.unknown.dataSizeInBytes) {
47254  pParser->metadataCursor += 1;
47255  } else {
47256  }
47257  }
47258  return bytesRead;
47259 }
47260 DRWAV_PRIVATE drwav_bool32 drwav__chunk_matches(drwav_uint64 allowedMetadataTypes, const drwav_uint8* pChunkID, drwav_metadata_type type, const char* pID)
47261 {
47262  return (allowedMetadataTypes & type) && drwav_fourcc_equal(pChunkID, pID);
47263 }
47265 {
47266  const drwav_uint8 *pChunkID = pChunkHeader->id.fourcc;
47267  drwav_uint64 bytesRead = 0;
47268  if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_smpl, "smpl")) {
47269  if (pChunkHeader->sizeInBytes >= DRWAV_SMPL_BYTES) {
47270  if (pParser->stage == drwav__metadata_parser_stage_count) {
47271  drwav_uint8 buffer[4];
47272  size_t bytesJustRead;
47273  if (!pParser->onSeek(pParser->pReadSeekUserData, 28, drwav_seek_origin_current)) {
47274  return bytesRead;
47275  }
47276  bytesRead += 28;
47277  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
47278  if (bytesJustRead == sizeof(buffer)) {
47279  drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
47280  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
47281  if (bytesJustRead == sizeof(buffer)) {
47282  drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
47283  pParser->metadataCount += 1;
47285  drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
47286  }
47287  }
47288  } else {
47289  bytesRead = drwav__read_smpl_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
47290  if (bytesRead == pChunkHeader->sizeInBytes) {
47291  pParser->metadataCursor += 1;
47292  } else {
47293  }
47294  }
47295  } else {
47296  }
47297  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_inst, "inst")) {
47298  if (pChunkHeader->sizeInBytes == DRWAV_INST_BYTES) {
47299  if (pParser->stage == drwav__metadata_parser_stage_count) {
47300  pParser->metadataCount += 1;
47301  } else {
47302  bytesRead = drwav__read_inst_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
47303  if (bytesRead == pChunkHeader->sizeInBytes) {
47304  pParser->metadataCursor += 1;
47305  } else {
47306  }
47307  }
47308  } else {
47309  }
47310  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_acid, "acid")) {
47311  if (pChunkHeader->sizeInBytes == DRWAV_ACID_BYTES) {
47312  if (pParser->stage == drwav__metadata_parser_stage_count) {
47313  pParser->metadataCount += 1;
47314  } else {
47315  bytesRead = drwav__read_acid_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
47316  if (bytesRead == pChunkHeader->sizeInBytes) {
47317  pParser->metadataCursor += 1;
47318  } else {
47319  }
47320  }
47321  } else {
47322  }
47323  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_cue, "cue ")) {
47324  if (pChunkHeader->sizeInBytes >= DRWAV_CUE_BYTES) {
47325  if (pParser->stage == drwav__metadata_parser_stage_count) {
47326  size_t cueCount;
47327  pParser->metadataCount += 1;
47328  cueCount = (size_t)(pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES;
47330  } else {
47331  bytesRead = drwav__read_cue_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
47332  if (bytesRead == pChunkHeader->sizeInBytes) {
47333  pParser->metadataCursor += 1;
47334  } else {
47335  }
47336  }
47337  } else {
47338  }
47339  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_bext, "bext")) {
47340  if (pChunkHeader->sizeInBytes >= DRWAV_BEXT_BYTES) {
47341  if (pParser->stage == drwav__metadata_parser_stage_count) {
47342  char buffer[DRWAV_BEXT_DESCRIPTION_BYTES + 1];
47343  size_t allocSizeNeeded = DRWAV_BEXT_UMID_BYTES;
47344  size_t bytesJustRead;
47345  buffer[DRWAV_BEXT_DESCRIPTION_BYTES] = '\0';
47346  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_DESCRIPTION_BYTES, &bytesRead);
47347  if (bytesJustRead != DRWAV_BEXT_DESCRIPTION_BYTES) {
47348  return bytesRead;
47349  }
47350  allocSizeNeeded += strlen(buffer) + 1;
47351  buffer[DRWAV_BEXT_ORIGINATOR_NAME_BYTES] = '\0';
47352  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_NAME_BYTES, &bytesRead);
47353  if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_NAME_BYTES) {
47354  return bytesRead;
47355  }
47356  allocSizeNeeded += strlen(buffer) + 1;
47357  buffer[DRWAV_BEXT_ORIGINATOR_REF_BYTES] = '\0';
47358  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_REF_BYTES, &bytesRead);
47359  if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_REF_BYTES) {
47360  return bytesRead;
47361  }
47362  allocSizeNeeded += strlen(buffer) + 1;
47363  allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES;
47364  drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
47365  pParser->metadataCount += 1;
47366  } else {
47367  bytesRead = drwav__read_bext_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], pChunkHeader->sizeInBytes);
47368  if (bytesRead == pChunkHeader->sizeInBytes) {
47369  pParser->metadataCursor += 1;
47370  } else {
47371  }
47372  }
47373  } else {
47374  }
47375  } else if (drwav_fourcc_equal(pChunkID, "LIST") || drwav_fourcc_equal(pChunkID, "list")) {
47377  while (bytesRead < pChunkHeader->sizeInBytes) {
47378  drwav_uint8 subchunkId[4];
47379  drwav_uint8 subchunkSizeBuffer[4];
47380  drwav_uint64 subchunkDataSize;
47381  drwav_uint64 subchunkBytesRead = 0;
47382  drwav_uint64 bytesJustRead = drwav__metadata_parser_read(pParser, subchunkId, sizeof(subchunkId), &bytesRead);
47383  if (bytesJustRead != sizeof(subchunkId)) {
47384  break;
47385  }
47386  if (drwav_fourcc_equal(subchunkId, "adtl")) {
47388  continue;
47389  } else if (drwav_fourcc_equal(subchunkId, "INFO")) {
47391  continue;
47392  }
47393  bytesJustRead = drwav__metadata_parser_read(pParser, subchunkSizeBuffer, sizeof(subchunkSizeBuffer), &bytesRead);
47394  if (bytesJustRead != sizeof(subchunkSizeBuffer)) {
47395  break;
47396  }
47397  subchunkDataSize = drwav_bytes_to_u32(subchunkSizeBuffer);
47398  if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_label, "labl") || drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_note, "note")) {
47399  if (subchunkDataSize >= DRWAV_LIST_LABEL_OR_NOTE_BYTES) {
47400  drwav_uint64 stringSizeWithNullTerm = subchunkDataSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
47401  if (pParser->stage == drwav__metadata_parser_stage_count) {
47402  pParser->metadataCount += 1;
47403  drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerm, 1);
47404  } else {
47405  subchunkBytesRead = drwav__read_list_label_or_note_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize, drwav_fourcc_equal(subchunkId, "labl") ? drwav_metadata_type_list_label : drwav_metadata_type_list_note);
47406  if (subchunkBytesRead == subchunkDataSize) {
47407  pParser->metadataCursor += 1;
47408  } else {
47409  }
47410  }
47411  } else {
47412  }
47413  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_labelled_cue_region, "ltxt")) {
47414  if (subchunkDataSize >= DRWAV_LIST_LABELLED_TEXT_BYTES) {
47415  drwav_uint64 stringSizeWithNullTerminator = subchunkDataSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
47416  if (pParser->stage == drwav__metadata_parser_stage_count) {
47417  pParser->metadataCount += 1;
47418  drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerminator, 1);
47419  } else {
47420  subchunkBytesRead = drwav__read_list_labelled_cue_region_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize);
47421  if (subchunkBytesRead == subchunkDataSize) {
47422  pParser->metadataCursor += 1;
47423  } else {
47424  }
47425  }
47426  } else {
47427  }
47428  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_software, "ISFT")) {
47429  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_software);
47430  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_copyright, "ICOP")) {
47431  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_copyright);
47432  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_title, "INAM")) {
47433  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_title);
47434  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_artist, "IART")) {
47435  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_artist);
47436  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_comment, "ICMT")) {
47437  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_comment);
47438  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_date, "ICRD")) {
47439  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_date);
47440  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_genre, "IGNR")) {
47441  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_genre);
47442  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_album, "IPRD")) {
47443  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
47444  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
47445  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
47446  } else if (allowedMetadataTypes & drwav_metadata_type_unknown) {
47447  subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
47448  }
47449  bytesRead += subchunkBytesRead;
47450  DRWAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
47451  if (subchunkBytesRead < subchunkDataSize) {
47452  drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
47453  if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, drwav_seek_origin_current)) {
47454  break;
47455  }
47456  bytesRead += bytesToSeek;
47457  }
47458  if ((subchunkDataSize % 2) == 1) {
47459  if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
47460  break;
47461  }
47462  bytesRead += 1;
47463  }
47464  }
47465  } else if (allowedMetadataTypes & drwav_metadata_type_unknown) {
47466  bytesRead = drwav__metadata_process_unknown_chunk(pParser, pChunkID, pChunkHeader->sizeInBytes, drwav_metadata_location_top_level);
47467  }
47468  return bytesRead;
47469 }
47471 {
47472  if ((pWav->bitsPerSample & 0x7) == 0) {
47473  return (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
47474  } else {
47475  return pWav->fmt.blockAlign;
47476  }
47477 }
47479 {
47480  if (pFMT == NULL) {
47481  return 0;
47482  }
47483  if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
47484  return pFMT->formatTag;
47485  } else {
47486  return drwav_bytes_to_u16(pFMT->subFormat);
47487  }
47488 }
47489 DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
47490 {
47491  if (pWav == NULL || onRead == NULL || onSeek == NULL) {
47492  return DRWAV_FALSE;
47493  }
47494  DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
47495  pWav->onRead = onRead;
47496  pWav->onSeek = onSeek;
47497  pWav->pUserData = pReadSeekUserData;
47500  return DRWAV_FALSE;
47501  }
47502  return DRWAV_TRUE;
47503 }
47505 {
47506  drwav_uint64 cursor;
47507  drwav_bool32 sequential;
47508  drwav_uint8 riff[4];
47509  drwav_fmt fmt;
47510  unsigned short translatedFormatTag;
47511  drwav_bool32 foundDataChunk;
47512  drwav_uint64 dataChunkSize = 0;
47513  drwav_uint64 sampleCountFromFactChunk = 0;
47514  drwav_uint64 chunkSize;
47515  drwav__metadata_parser metadataParser;
47516  cursor = 0;
47517  sequential = (flags & DRWAV_SEQUENTIAL) != 0;
47518  if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
47519  return DRWAV_FALSE;
47520  }
47521  if (drwav_fourcc_equal(riff, "RIFF")) {
47523  } else if (drwav_fourcc_equal(riff, "riff")) {
47524  int i;
47525  drwav_uint8 riff2[12];
47527  if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
47528  return DRWAV_FALSE;
47529  }
47530  for (i = 0; i < 12; ++i) {
47531  if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
47532  return DRWAV_FALSE;
47533  }
47534  }
47535  } else if (drwav_fourcc_equal(riff, "RF64")) {
47537  } else {
47538  return DRWAV_FALSE;
47539  }
47540  if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
47541  drwav_uint8 chunkSizeBytes[4];
47542  drwav_uint8 wave[4];
47543  if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
47544  return DRWAV_FALSE;
47545  }
47546  if (pWav->container == drwav_container_riff) {
47547  if (drwav_bytes_to_u32(chunkSizeBytes) < 36) {
47548  return DRWAV_FALSE;
47549  }
47550  } else {
47551  if (drwav_bytes_to_u32(chunkSizeBytes) != 0xFFFFFFFF) {
47552  return DRWAV_FALSE;
47553  }
47554  }
47555  if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
47556  return DRWAV_FALSE;
47557  }
47558  if (!drwav_fourcc_equal(wave, "WAVE")) {
47559  return DRWAV_FALSE;
47560  }
47561  } else {
47562  drwav_uint8 chunkSizeBytes[8];
47563  drwav_uint8 wave[16];
47564  if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
47565  return DRWAV_FALSE;
47566  }
47567  if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
47568  return DRWAV_FALSE;
47569  }
47570  if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
47571  return DRWAV_FALSE;
47572  }
47573  if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
47574  return DRWAV_FALSE;
47575  }
47576  }
47577  if (pWav->container == drwav_container_rf64) {
47578  drwav_uint8 sizeBytes[8];
47579  drwav_uint64 bytesRemainingInChunk;
47581  drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
47582  if (result != DRWAV_SUCCESS) {
47583  return DRWAV_FALSE;
47584  }
47585  if (!drwav_fourcc_equal(header.id.fourcc, "ds64")) {
47586  return DRWAV_FALSE;
47587  }
47588  bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
47589  if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
47590  return DRWAV_FALSE;
47591  }
47592  bytesRemainingInChunk -= 8;
47593  cursor += 8;
47594  if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
47595  return DRWAV_FALSE;
47596  }
47597  bytesRemainingInChunk -= 8;
47598  dataChunkSize = drwav_bytes_to_u64(sizeBytes);
47599  if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
47600  return DRWAV_FALSE;
47601  }
47602  bytesRemainingInChunk -= 8;
47603  sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
47604  if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
47605  return DRWAV_FALSE;
47606  }
47607  cursor += bytesRemainingInChunk;
47608  }
47609  if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
47610  return DRWAV_FALSE;
47611  }
47612  if ((fmt.sampleRate == 0 || fmt.sampleRate > DRWAV_MAX_SAMPLE_RATE) ||
47613  (fmt.channels == 0 || fmt.channels > DRWAV_MAX_CHANNELS) ||
47615  fmt.blockAlign == 0) {
47616  return DRWAV_FALSE;
47617  }
47618  translatedFormatTag = fmt.formatTag;
47619  if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
47620  translatedFormatTag = drwav_bytes_to_u16(fmt.subFormat + 0);
47621  }
47622  memset(&metadataParser, 0, sizeof(metadataParser));
47623  if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
47624  drwav_uint64 cursorForMetadata = cursor;
47625  metadataParser.onRead = pWav->onRead;
47626  metadataParser.onSeek = pWav->onSeek;
47627  metadataParser.pReadSeekUserData = pWav->pUserData;
47628  metadataParser.stage = drwav__metadata_parser_stage_count;
47629  for (;;) {
47630  drwav_result result;
47631  drwav_uint64 bytesRead;
47632  drwav_uint64 remainingBytes;
47634  result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursorForMetadata, &header);
47635  if (result != DRWAV_SUCCESS) {
47636  break;
47637  }
47638  bytesRead = drwav__metadata_process_chunk(&metadataParser, &header, pWav->allowedMetadataTypes);
47639  DRWAV_ASSERT(bytesRead <= header.sizeInBytes);
47640  remainingBytes = header.sizeInBytes - bytesRead + header.paddingSize;
47641  if (!drwav__seek_forward(pWav->onSeek, remainingBytes, pWav->pUserData)) {
47642  break;
47643  }
47644  cursorForMetadata += remainingBytes;
47645  }
47646  if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
47647  return DRWAV_FALSE;
47648  }
47649  drwav__metadata_alloc(&metadataParser, &pWav->allocationCallbacks);
47650  metadataParser.stage = drwav__metadata_parser_stage_read;
47651  }
47652  foundDataChunk = DRWAV_FALSE;
47653  for (;;) {
47655  drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
47656  if (result != DRWAV_SUCCESS) {
47657  if (!foundDataChunk) {
47658  return DRWAV_FALSE;
47659  } else {
47660  break;
47661  }
47662  }
47663  if (!sequential && onChunk != NULL) {
47664  drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
47665  if (callbackBytesRead > 0) {
47666  if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
47667  return DRWAV_FALSE;
47668  }
47669  }
47670  }
47671  if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
47672  drwav_uint64 bytesRead = drwav__metadata_process_chunk(&metadataParser, &header, pWav->allowedMetadataTypes);
47673  if (bytesRead > 0) {
47674  if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
47675  return DRWAV_FALSE;
47676  }
47677  }
47678  }
47679  if (!foundDataChunk) {
47680  pWav->dataChunkDataPos = cursor;
47681  }
47682  chunkSize = header.sizeInBytes;
47683  if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
47684  if (drwav_fourcc_equal(header.id.fourcc, "data")) {
47685  foundDataChunk = DRWAV_TRUE;
47686  if (pWav->container != drwav_container_rf64) {
47687  dataChunkSize = chunkSize;
47688  }
47689  }
47690  } else {
47691  if (drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
47692  foundDataChunk = DRWAV_TRUE;
47693  dataChunkSize = chunkSize;
47694  }
47695  }
47696  if (foundDataChunk && sequential) {
47697  break;
47698  }
47699  if (pWav->container == drwav_container_riff) {
47700  if (drwav_fourcc_equal(header.id.fourcc, "fact")) {
47701  drwav_uint32 sampleCount;
47702  if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
47703  return DRWAV_FALSE;
47704  }
47705  chunkSize -= 4;
47706  if (!foundDataChunk) {
47707  pWav->dataChunkDataPos = cursor;
47708  }
47710  sampleCountFromFactChunk = sampleCount;
47711  } else {
47712  sampleCountFromFactChunk = 0;
47713  }
47714  }
47715  } else if (pWav->container == drwav_container_w64) {
47716  if (drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
47717  if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
47718  return DRWAV_FALSE;
47719  }
47720  chunkSize -= 8;
47721  if (!foundDataChunk) {
47722  pWav->dataChunkDataPos = cursor;
47723  }
47724  }
47725  } else if (pWav->container == drwav_container_rf64) {
47726  }
47727  chunkSize += header.paddingSize;
47728  if (!drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData)) {
47729  break;
47730  }
47731  cursor += chunkSize;
47732  if (!foundDataChunk) {
47733  pWav->dataChunkDataPos = cursor;
47734  }
47735  }
47736  pWav->pMetadata = metadataParser.pMetadata;
47737  pWav->metadataCount = metadataParser.metadataCount;
47738  if (!foundDataChunk) {
47739  return DRWAV_FALSE;
47740  }
47741  if (!sequential) {
47742  if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
47743  return DRWAV_FALSE;
47744  }
47745  cursor = pWav->dataChunkDataPos;
47746  }
47747  pWav->fmt = fmt;
47748  pWav->sampleRate = fmt.sampleRate;
47749  pWav->channels = fmt.channels;
47750  pWav->bitsPerSample = fmt.bitsPerSample;
47751  pWav->bytesRemaining = dataChunkSize;
47752  pWav->translatedFormatTag = translatedFormatTag;
47753  pWav->dataChunkDataSize = dataChunkSize;
47754  if (sampleCountFromFactChunk != 0) {
47755  pWav->totalPCMFrameCount = sampleCountFromFactChunk;
47756  } else {
47757  pWav->totalPCMFrameCount = dataChunkSize / drwav_get_bytes_per_pcm_frame(pWav);
47759  drwav_uint64 totalBlockHeaderSizeInBytes;
47760  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
47761  if ((blockCount * fmt.blockAlign) < dataChunkSize) {
47762  blockCount += 1;
47763  }
47764  totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
47765  pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
47766  }
47768  drwav_uint64 totalBlockHeaderSizeInBytes;
47769  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
47770  if ((blockCount * fmt.blockAlign) < dataChunkSize) {
47771  blockCount += 1;
47772  }
47773  totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
47774  pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
47775  pWav->totalPCMFrameCount += blockCount;
47776  }
47777  }
47779  if (pWav->channels > 2) {
47780  return DRWAV_FALSE;
47781  }
47782  }
47783 #ifdef DR_WAV_LIBSNDFILE_COMPAT
47785  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
47786  pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;
47787  }
47789  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
47790  pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
47791  }
47792 #endif
47793  return DRWAV_TRUE;
47794 }
47795 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
47796 {
47797  return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
47798 }
47799 DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
47800 {
47801  if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
47802  return DRWAV_FALSE;
47803  }
47804  return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
47805 }
47806 DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
47807 {
47808  if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
47809  return DRWAV_FALSE;
47810  }
47812  return drwav_init__internal(pWav, NULL, NULL, flags);
47813 }
47815 {
47816  drwav_metadata *result = pWav->pMetadata;
47817  pWav->pMetadata = NULL;
47818  pWav->metadataCount = 0;
47819  return result;
47820 }
47821 DRWAV_PRIVATE size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
47822 {
47823  DRWAV_ASSERT(pWav != NULL);
47824  DRWAV_ASSERT(pWav->onWrite != NULL);
47825  return pWav->onWrite(pWav->pUserData, pData, dataSize);
47826 }
47828 {
47829  DRWAV_ASSERT(pWav != NULL);
47830  DRWAV_ASSERT(pWav->onWrite != NULL);
47831  return pWav->onWrite(pWav->pUserData, &byte, 1);
47832 }
47834 {
47835  DRWAV_ASSERT(pWav != NULL);
47836  DRWAV_ASSERT(pWav->onWrite != NULL);
47837  if (!drwav__is_little_endian()) {
47838  value = drwav__bswap16(value);
47839  }
47840  return drwav__write(pWav, &value, 2);
47841 }
47843 {
47844  DRWAV_ASSERT(pWav != NULL);
47845  DRWAV_ASSERT(pWav->onWrite != NULL);
47846  if (!drwav__is_little_endian()) {
47847  value = drwav__bswap32(value);
47848  }
47849  return drwav__write(pWav, &value, 4);
47850 }
47852 {
47853  DRWAV_ASSERT(pWav != NULL);
47854  DRWAV_ASSERT(pWav->onWrite != NULL);
47855  if (!drwav__is_little_endian()) {
47856  value = drwav__bswap64(value);
47857  }
47858  return drwav__write(pWav, &value, 8);
47859 }
47861 {
47862  union {
47863  drwav_uint32 u32;
47864  float f32;
47865  } u;
47866  DRWAV_ASSERT(pWav != NULL);
47867  DRWAV_ASSERT(pWav->onWrite != NULL);
47868  u.f32 = value;
47869  if (!drwav__is_little_endian()) {
47870  u.u32 = drwav__bswap32(u.u32);
47871  }
47872  return drwav__write(pWav, &u.u32, 4);
47873 }
47874 DRWAV_PRIVATE size_t drwav__write_or_count(drwav* pWav, const void* pData, size_t dataSize)
47875 {
47876  if (pWav == NULL) {
47877  return dataSize;
47878  }
47879  return drwav__write(pWav, pData, dataSize);
47880 }
47882 {
47883  if (pWav == NULL) {
47884  return 1;
47885  }
47886  return drwav__write_byte(pWav, byte);
47887 }
47889 {
47890  if (pWav == NULL) {
47891  return 2;
47892  }
47893  return drwav__write_u16ne_to_le(pWav, value);
47894 }
47896 {
47897  if (pWav == NULL) {
47898  return 4;
47899  }
47900  return drwav__write_u32ne_to_le(pWav, value);
47901 }
47902 #if 0
47903 DRWAV_PRIVATE size_t drwav__write_or_count_u64ne_to_le(drwav* pWav, drwav_uint64 value)
47904 {
47905  if (pWav == NULL) {
47906  return 8;
47907  }
47908  return drwav__write_u64ne_to_le(pWav, value);
47909 }
47910 #endif
47912 {
47913  if (pWav == NULL) {
47914  return 4;
47915  }
47916  return drwav__write_f32ne_to_le(pWav, value);
47917 }
47918 DRWAV_PRIVATE size_t drwav__write_or_count_string_to_fixed_size_buf(drwav* pWav, char* str, size_t bufFixedSize)
47919 {
47920  size_t len;
47921  if (pWav == NULL) {
47922  return bufFixedSize;
47923  }
47924  len = drwav__strlen_clamped(str, bufFixedSize);
47925  drwav__write_or_count(pWav, str, len);
47926  if (len < bufFixedSize) {
47927  size_t i;
47928  for (i = 0; i < bufFixedSize - len; ++i) {
47929  drwav__write_byte(pWav, 0);
47930  }
47931  }
47932  return bufFixedSize;
47933 }
47935 {
47936  size_t bytesWritten = 0;
47937  drwav_bool32 hasListAdtl = DRWAV_FALSE;
47938  drwav_bool32 hasListInfo = DRWAV_FALSE;
47939  drwav_uint32 iMetadata;
47940  if (pMetadatas == NULL || metadataCount == 0) {
47941  return 0;
47942  }
47943  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
47944  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
47945  drwav_uint32 chunkSize = 0;
47947  hasListInfo = DRWAV_TRUE;
47948  }
47950  hasListAdtl = DRWAV_TRUE;
47951  }
47952  switch (pMetadata->type) {
47954  {
47955  drwav_uint32 iLoop;
47957  bytesWritten += drwav__write_or_count(pWav, "smpl", 4);
47958  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
47959  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.manufacturerId);
47960  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.productId);
47961  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplePeriodNanoseconds);
47962  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiUnityNote);
47963  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiPitchFraction);
47964  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteFormat);
47965  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteOffset);
47966  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.sampleLoopCount);
47968  for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
47969  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
47970  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
47971  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
47972  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
47973  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
47974  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
47975  }
47976  if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
47977  bytesWritten += drwav__write(pWav, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
47978  }
47979  } break;
47981  {
47982  chunkSize = DRWAV_INST_BYTES;
47983  bytesWritten += drwav__write_or_count(pWav, "inst", 4);
47984  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
47985  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.midiUnityNote, 1);
47986  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.fineTuneCents, 1);
47987  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.gainDecibels, 1);
47988  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowNote, 1);
47989  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highNote, 1);
47990  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowVelocity, 1);
47991  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highVelocity, 1);
47992  } break;
47994  {
47995  drwav_uint32 iCuePoint;
47996  chunkSize = DRWAV_CUE_BYTES + DRWAV_CUE_POINT_BYTES * pMetadata->data.cue.cuePointCount;
47997  bytesWritten += drwav__write_or_count(pWav, "cue ", 4);
47998  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
47999  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.cuePointCount);
48000  for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
48001  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].id);
48002  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition);
48003  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
48004  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
48005  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
48006  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
48007  }
48008  } break;
48010  {
48011  chunkSize = DRWAV_ACID_BYTES;
48012  bytesWritten += drwav__write_or_count(pWav, "acid", 4);
48013  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
48014  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.flags);
48015  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.midiUnityNote);
48016  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.reserved1);
48017  bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.reserved2);
48018  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.numBeats);
48019  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterDenominator);
48020  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterNumerator);
48021  bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.tempo);
48022  } break;
48024  {
48025  char reservedBuf[DRWAV_BEXT_RESERVED_BYTES];
48026  drwav_uint32 timeReferenceLow;
48027  drwav_uint32 timeReferenceHigh;
48028  chunkSize = DRWAV_BEXT_BYTES + pMetadata->data.bext.codingHistorySize;
48029  bytesWritten += drwav__write_or_count(pWav, "bext", 4);
48030  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
48034  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate));
48035  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime));
48036  timeReferenceLow = (drwav_uint32)(pMetadata->data.bext.timeReference & 0xFFFFFFFF);
48037  timeReferenceHigh = (drwav_uint32)(pMetadata->data.bext.timeReference >> 32);
48038  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceLow);
48039  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceHigh);
48040  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.version);
48041  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES);
48042  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessValue);
48043  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessRange);
48044  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxTruePeakLevel);
48045  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxMomentaryLoudness);
48046  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxShortTermLoudness);
48047  memset(reservedBuf, 0, sizeof(reservedBuf));
48048  bytesWritten += drwav__write_or_count(pWav, reservedBuf, sizeof(reservedBuf));
48049  if (pMetadata->data.bext.codingHistorySize > 0) {
48050  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pCodingHistory, pMetadata->data.bext.codingHistorySize);
48051  }
48052  } break;
48054  {
48056  chunkSize = pMetadata->data.unknown.dataSizeInBytes;
48057  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
48058  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
48059  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes);
48060  }
48061  } break;
48062  default: break;
48063  }
48064  if ((chunkSize % 2) != 0) {
48065  bytesWritten += drwav__write_or_count_byte(pWav, 0);
48066  }
48067  }
48068  if (hasListInfo) {
48069  drwav_uint32 chunkSize = 4;
48070  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
48071  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
48072  if ((pMetadata->type & drwav_metadata_type_list_all_info_strings)) {
48073  chunkSize += 8;
48074  chunkSize += pMetadata->data.infoText.stringLength + 1;
48076  chunkSize += 8;
48077  chunkSize += pMetadata->data.unknown.dataSizeInBytes;
48078  }
48079  if ((chunkSize % 2) != 0) {
48080  chunkSize += 1;
48081  }
48082  }
48083  bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
48084  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
48085  bytesWritten += drwav__write_or_count(pWav, "INFO", 4);
48086  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
48087  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
48088  drwav_uint32 subchunkSize = 0;
48090  const char* pID = NULL;
48091  switch (pMetadata->type) {
48092  case drwav_metadata_type_list_info_software: pID = "ISFT"; break;
48093  case drwav_metadata_type_list_info_copyright: pID = "ICOP"; break;
48094  case drwav_metadata_type_list_info_title: pID = "INAM"; break;
48095  case drwav_metadata_type_list_info_artist: pID = "IART"; break;
48096  case drwav_metadata_type_list_info_comment: pID = "ICMT"; break;
48097  case drwav_metadata_type_list_info_date: pID = "ICRD"; break;
48098  case drwav_metadata_type_list_info_genre: pID = "IGNR"; break;
48099  case drwav_metadata_type_list_info_album: pID = "IPRD"; break;
48100  case drwav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
48101  default: break;
48102  }
48103  DRWAV_ASSERT(pID != NULL);
48104  if (pMetadata->data.infoText.stringLength) {
48105  subchunkSize = pMetadata->data.infoText.stringLength + 1;
48106  bytesWritten += drwav__write_or_count(pWav, pID, 4);
48107  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
48108  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.infoText.pString, pMetadata->data.infoText.stringLength);
48109  bytesWritten += drwav__write_or_count_byte(pWav, '\0');
48110  }
48112  if (pMetadata->data.unknown.dataSizeInBytes) {
48113  subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
48114  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
48115  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.unknown.dataSizeInBytes);
48116  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
48117  }
48118  }
48119  if ((subchunkSize % 2) != 0) {
48120  bytesWritten += drwav__write_or_count_byte(pWav, 0);
48121  }
48122  }
48123  }
48124  if (hasListAdtl) {
48125  drwav_uint32 chunkSize = 4;
48126  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
48127  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
48128  switch (pMetadata->type)
48129  {
48132  {
48133  chunkSize += 8;
48134  chunkSize += DRWAV_LIST_LABEL_OR_NOTE_BYTES;
48135  if (pMetadata->data.labelOrNote.stringLength > 0) {
48136  chunkSize += pMetadata->data.labelOrNote.stringLength + 1;
48137  }
48138  } break;
48140  {
48141  chunkSize += 8;
48142  chunkSize += DRWAV_LIST_LABELLED_TEXT_BYTES;
48143  if (pMetadata->data.labelledCueRegion.stringLength > 0) {
48144  chunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
48145  }
48146  } break;
48148  {
48150  chunkSize += 8;
48151  chunkSize += pMetadata->data.unknown.dataSizeInBytes;
48152  }
48153  } break;
48154  default: break;
48155  }
48156  if ((chunkSize % 2) != 0) {
48157  chunkSize += 1;
48158  }
48159  }
48160  bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
48161  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
48162  bytesWritten += drwav__write_or_count(pWav, "adtl", 4);
48163  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
48164  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
48165  drwav_uint32 subchunkSize = 0;
48166  switch (pMetadata->type)
48167  {
48170  {
48171  if (pMetadata->data.labelOrNote.stringLength > 0) {
48172  const char *pID = NULL;
48173  if (pMetadata->type == drwav_metadata_type_list_label) {
48174  pID = "labl";
48175  }
48176  else if (pMetadata->type == drwav_metadata_type_list_note) {
48177  pID = "note";
48178  }
48179  DRWAV_ASSERT(pID != NULL);
48180  DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
48181  subchunkSize = DRWAV_LIST_LABEL_OR_NOTE_BYTES;
48182  bytesWritten += drwav__write_or_count(pWav, pID, 4);
48183  subchunkSize += pMetadata->data.labelOrNote.stringLength + 1;
48184  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
48185  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelOrNote.cuePointId);
48186  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelOrNote.pString, pMetadata->data.labelOrNote.stringLength);
48187  bytesWritten += drwav__write_or_count_byte(pWav, '\0');
48188  }
48189  } break;
48191  {
48192  subchunkSize = DRWAV_LIST_LABELLED_TEXT_BYTES;
48193  bytesWritten += drwav__write_or_count(pWav, "ltxt", 4);
48194  if (pMetadata->data.labelledCueRegion.stringLength > 0) {
48195  subchunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
48196  }
48197  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
48198  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.cuePointId);
48199  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.sampleLength);
48200  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.purposeId, 4);
48201  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.country);
48202  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.language);
48203  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.dialect);
48204  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.codePage);
48205  if (pMetadata->data.labelledCueRegion.stringLength > 0) {
48207  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.pString, pMetadata->data.labelledCueRegion.stringLength);
48208  bytesWritten += drwav__write_or_count_byte(pWav, '\0');
48209  }
48210  } break;
48212  {
48214  subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
48215  DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
48216  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
48217  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
48218  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
48219  }
48220  } break;
48221  default: break;
48222  }
48223  if ((subchunkSize % 2) != 0) {
48224  bytesWritten += drwav__write_or_count_byte(pWav, 0);
48225  }
48226  }
48227  }
48228  DRWAV_ASSERT((bytesWritten % 2) == 0);
48229  return bytesWritten;
48230 }
48232 {
48233  drwav_uint64 chunkSize = 4 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, pMetadata, metadataCount) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
48234  if (chunkSize > 0xFFFFFFFFUL) {
48235  chunkSize = 0xFFFFFFFFUL;
48236  }
48237  return (drwav_uint32)chunkSize;
48238 }
48240 {
48241  if (dataChunkSize <= 0xFFFFFFFFUL) {
48242  return (drwav_uint32)dataChunkSize;
48243  } else {
48244  return 0xFFFFFFFFUL;
48245  }
48246 }
48248 {
48249  drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
48250  return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;
48251 }
48253 {
48254  return 24 + dataChunkSize;
48255 }
48257 {
48258  drwav_uint64 chunkSize = 4 + 36 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, metadata, numMetadata) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
48259  if (chunkSize > 0xFFFFFFFFUL) {
48260  chunkSize = 0xFFFFFFFFUL;
48261  }
48262  return chunkSize;
48263 }
48265 {
48266  return dataChunkSize;
48267 }
48268 DRWAV_PRIVATE drwav_bool32 drwav_preinit_write(drwav* pWav, const drwav_data_format* pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
48269 {
48270  if (pWav == NULL || onWrite == NULL) {
48271  return DRWAV_FALSE;
48272  }
48273  if (!isSequential && onSeek == NULL) {
48274  return DRWAV_FALSE;
48275  }
48276  if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
48277  return DRWAV_FALSE;
48278  }
48279  if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
48280  return DRWAV_FALSE;
48281  }
48282  DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
48283  pWav->onWrite = onWrite;
48284  pWav->onSeek = onSeek;
48285  pWav->pUserData = pUserData;
48288  return DRWAV_FALSE;
48289  }
48290  pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
48291  pWav->fmt.channels = (drwav_uint16)pFormat->channels;
48292  pWav->fmt.sampleRate = pFormat->sampleRate;
48293  pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
48294  pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
48295  pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
48296  pWav->fmt.extendedSize = 0;
48297  pWav->isSequentialWrite = isSequential;
48298  return DRWAV_TRUE;
48299 }
48301 {
48302  size_t runningPos = 0;
48303  drwav_uint64 initialDataChunkSize = 0;
48304  drwav_uint64 chunkSizeFMT;
48305  if (pWav->isSequentialWrite) {
48306  initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
48307  if (pFormat->container == drwav_container_riff) {
48308  if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
48309  return DRWAV_FALSE;
48310  }
48311  }
48312  }
48313  pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
48314  if (pFormat->container == drwav_container_riff) {
48315  drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;
48316  runningPos += drwav__write(pWav, "RIFF", 4);
48317  runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
48318  runningPos += drwav__write(pWav, "WAVE", 4);
48319  } else if (pFormat->container == drwav_container_w64) {
48320  drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
48321  runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
48322  runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
48323  runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
48324  } else if (pFormat->container == drwav_container_rf64) {
48325  runningPos += drwav__write(pWav, "RF64", 4);
48326  runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
48327  runningPos += drwav__write(pWav, "WAVE", 4);
48328  }
48329  if (pFormat->container == drwav_container_rf64) {
48330  drwav_uint32 initialds64ChunkSize = 28;
48331  drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;
48332  runningPos += drwav__write(pWav, "ds64", 4);
48333  runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);
48334  runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);
48335  runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);
48336  runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);
48337  runningPos += drwav__write_u32ne_to_le(pWav, 0);
48338  }
48339  if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
48340  chunkSizeFMT = 16;
48341  runningPos += drwav__write(pWav, "fmt ", 4);
48342  runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
48343  } else if (pFormat->container == drwav_container_w64) {
48344  chunkSizeFMT = 40;
48345  runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
48346  runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
48347  }
48348  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
48349  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
48350  runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
48351  runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
48352  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
48353  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
48354  if (!pWav->isSequentialWrite && pWav->pMetadata != NULL && pWav->metadataCount > 0 && (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64)) {
48355  runningPos += drwav__write_or_count_metadata(pWav, pWav->pMetadata, pWav->metadataCount);
48356  }
48357  pWav->dataChunkDataPos = runningPos;
48358  if (pFormat->container == drwav_container_riff) {
48359  drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
48360  runningPos += drwav__write(pWav, "data", 4);
48361  runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
48362  } else if (pFormat->container == drwav_container_w64) {
48363  drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
48364  runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
48365  runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
48366  } else if (pFormat->container == drwav_container_rf64) {
48367  runningPos += drwav__write(pWav, "data", 4);
48368  runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
48369  }
48370  pWav->container = pFormat->container;
48371  pWav->channels = (drwav_uint16)pFormat->channels;
48372  pWav->sampleRate = pFormat->sampleRate;
48373  pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
48374  pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
48375  pWav->dataChunkDataPos = runningPos;
48376  return DRWAV_TRUE;
48377 }
48378 DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
48379 {
48380  if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
48381  return DRWAV_FALSE;
48382  }
48383  return drwav_init_write__internal(pWav, pFormat, 0);
48384 }
48385 DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
48386 {
48387  if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
48388  return DRWAV_FALSE;
48389  }
48390  return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
48391 }
48392 DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
48393 {
48394  if (pFormat == NULL) {
48395  return DRWAV_FALSE;
48396  }
48397  return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
48398 }
48399 DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
48400 {
48401  if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
48402  return DRWAV_FALSE;
48403  }
48404  pWav->pMetadata = pMetadata;
48405  pWav->metadataCount = metadataCount;
48406  return drwav_init_write__internal(pWav, pFormat, 0);
48407 }
48409 {
48410  drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalFrameCount * pFormat->channels * pFormat->bitsPerSample/8.0);
48411  drwav_uint64 riffChunkSizeBytes;
48412  drwav_uint64 fileSizeBytes = 0;
48413  if (pFormat->container == drwav_container_riff) {
48414  riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes, pMetadata, metadataCount);
48415  fileSizeBytes = (8 + riffChunkSizeBytes);
48416  } else if (pFormat->container == drwav_container_w64) {
48417  riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
48418  fileSizeBytes = riffChunkSizeBytes;
48419  } else if (pFormat->container == drwav_container_rf64) {
48420  riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes, pMetadata, metadataCount);
48421  fileSizeBytes = (8 + riffChunkSizeBytes);
48422  }
48423  return fileSizeBytes;
48424 }
48425 #ifndef DR_WAV_NO_STDIO
48426 #include <errno.h>
48428 {
48429  switch (e)
48430  {
48431  case 0: return DRWAV_SUCCESS;
48432  #ifdef EPERM
48433  case EPERM: return DRWAV_INVALID_OPERATION;
48434  #endif
48435  #ifdef ENOENT
48436  case ENOENT: return DRWAV_DOES_NOT_EXIST;
48437  #endif
48438  #ifdef ESRCH
48439  case ESRCH: return DRWAV_DOES_NOT_EXIST;
48440  #endif
48441  #ifdef EINTR
48442  case EINTR: return DRWAV_INTERRUPT;
48443  #endif
48444  #ifdef EIO
48445  case EIO: return DRWAV_IO_ERROR;
48446  #endif
48447  #ifdef ENXIO
48448  case ENXIO: return DRWAV_DOES_NOT_EXIST;
48449  #endif
48450  #ifdef E2BIG
48451  case E2BIG: return DRWAV_INVALID_ARGS;
48452  #endif
48453  #ifdef ENOEXEC
48454  case ENOEXEC: return DRWAV_INVALID_FILE;
48455  #endif
48456  #ifdef EBADF
48457  case EBADF: return DRWAV_INVALID_FILE;
48458  #endif
48459  #ifdef ECHILD
48460  case ECHILD: return DRWAV_ERROR;
48461  #endif
48462  #ifdef EAGAIN
48463  case EAGAIN: return DRWAV_UNAVAILABLE;
48464  #endif
48465  #ifdef ENOMEM
48466  case ENOMEM: return DRWAV_OUT_OF_MEMORY;
48467  #endif
48468  #ifdef EACCES
48469  case EACCES: return DRWAV_ACCESS_DENIED;
48470  #endif
48471  #ifdef EFAULT
48472  case EFAULT: return DRWAV_BAD_ADDRESS;
48473  #endif
48474  #ifdef ENOTBLK
48475  case ENOTBLK: return DRWAV_ERROR;
48476  #endif
48477  #ifdef EBUSY
48478  case EBUSY: return DRWAV_BUSY;
48479  #endif
48480  #ifdef EEXIST
48481  case EEXIST: return DRWAV_ALREADY_EXISTS;
48482  #endif
48483  #ifdef EXDEV
48484  case EXDEV: return DRWAV_ERROR;
48485  #endif
48486  #ifdef ENODEV
48487  case ENODEV: return DRWAV_DOES_NOT_EXIST;
48488  #endif
48489  #ifdef ENOTDIR
48490  case ENOTDIR: return DRWAV_NOT_DIRECTORY;
48491  #endif
48492  #ifdef EISDIR
48493  case EISDIR: return DRWAV_IS_DIRECTORY;
48494  #endif
48495  #ifdef EINVAL
48496  case EINVAL: return DRWAV_INVALID_ARGS;
48497  #endif
48498  #ifdef ENFILE
48499  case ENFILE: return DRWAV_TOO_MANY_OPEN_FILES;
48500  #endif
48501  #ifdef EMFILE
48502  case EMFILE: return DRWAV_TOO_MANY_OPEN_FILES;
48503  #endif
48504  #ifdef ENOTTY
48505  case ENOTTY: return DRWAV_INVALID_OPERATION;
48506  #endif
48507  #ifdef ETXTBSY
48508  case ETXTBSY: return DRWAV_BUSY;
48509  #endif
48510  #ifdef EFBIG
48511  case EFBIG: return DRWAV_TOO_BIG;
48512  #endif
48513  #ifdef ENOSPC
48514  case ENOSPC: return DRWAV_NO_SPACE;
48515  #endif
48516  #ifdef ESPIPE
48517  case ESPIPE: return DRWAV_BAD_SEEK;
48518  #endif
48519  #ifdef EROFS
48520  case EROFS: return DRWAV_ACCESS_DENIED;
48521  #endif
48522  #ifdef EMLINK
48523  case EMLINK: return DRWAV_TOO_MANY_LINKS;
48524  #endif
48525  #ifdef EPIPE
48526  case EPIPE: return DRWAV_BAD_PIPE;
48527  #endif
48528  #ifdef EDOM
48529  case EDOM: return DRWAV_OUT_OF_RANGE;
48530  #endif
48531  #ifdef ERANGE
48532  case ERANGE: return DRWAV_OUT_OF_RANGE;
48533  #endif
48534  #ifdef EDEADLK
48535  case EDEADLK: return DRWAV_DEADLOCK;
48536  #endif
48537  #ifdef ENAMETOOLONG
48538  case ENAMETOOLONG: return DRWAV_PATH_TOO_LONG;
48539  #endif
48540  #ifdef ENOLCK
48541  case ENOLCK: return DRWAV_ERROR;
48542  #endif
48543  #ifdef ENOSYS
48544  case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
48545  #endif
48546  #ifdef ENOTEMPTY
48547  case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
48548  #endif
48549  #ifdef ELOOP
48550  case ELOOP: return DRWAV_TOO_MANY_LINKS;
48551  #endif
48552  #ifdef ENOMSG
48553  case ENOMSG: return DRWAV_NO_MESSAGE;
48554  #endif
48555  #ifdef EIDRM
48556  case EIDRM: return DRWAV_ERROR;
48557  #endif
48558  #ifdef ECHRNG
48559  case ECHRNG: return DRWAV_ERROR;
48560  #endif
48561  #ifdef EL2NSYNC
48562  case EL2NSYNC: return DRWAV_ERROR;
48563  #endif
48564  #ifdef EL3HLT
48565  case EL3HLT: return DRWAV_ERROR;
48566  #endif
48567  #ifdef EL3RST
48568  case EL3RST: return DRWAV_ERROR;
48569  #endif
48570  #ifdef ELNRNG
48571  case ELNRNG: return DRWAV_OUT_OF_RANGE;
48572  #endif
48573  #ifdef EUNATCH
48574  case EUNATCH: return DRWAV_ERROR;
48575  #endif
48576  #ifdef ENOCSI
48577  case ENOCSI: return DRWAV_ERROR;
48578  #endif
48579  #ifdef EL2HLT
48580  case EL2HLT: return DRWAV_ERROR;
48581  #endif
48582  #ifdef EBADE
48583  case EBADE: return DRWAV_ERROR;
48584  #endif
48585  #ifdef EBADR
48586  case EBADR: return DRWAV_ERROR;
48587  #endif
48588  #ifdef EXFULL
48589  case EXFULL: return DRWAV_ERROR;
48590  #endif
48591  #ifdef ENOANO
48592  case ENOANO: return DRWAV_ERROR;
48593  #endif
48594  #ifdef EBADRQC
48595  case EBADRQC: return DRWAV_ERROR;
48596  #endif
48597  #ifdef EBADSLT
48598  case EBADSLT: return DRWAV_ERROR;
48599  #endif
48600  #ifdef EBFONT
48601  case EBFONT: return DRWAV_INVALID_FILE;
48602  #endif
48603  #ifdef ENOSTR
48604  case ENOSTR: return DRWAV_ERROR;
48605  #endif
48606  #ifdef ENODATA
48607  case ENODATA: return DRWAV_NO_DATA_AVAILABLE;
48608  #endif
48609  #ifdef ETIME
48610  case ETIME: return DRWAV_TIMEOUT;
48611  #endif
48612  #ifdef ENOSR
48613  case ENOSR: return DRWAV_NO_DATA_AVAILABLE;
48614  #endif
48615  #ifdef ENONET
48616  case ENONET: return DRWAV_NO_NETWORK;
48617  #endif
48618  #ifdef ENOPKG
48619  case ENOPKG: return DRWAV_ERROR;
48620  #endif
48621  #ifdef EREMOTE
48622  case EREMOTE: return DRWAV_ERROR;
48623  #endif
48624  #ifdef ENOLINK
48625  case ENOLINK: return DRWAV_ERROR;
48626  #endif
48627  #ifdef EADV
48628  case EADV: return DRWAV_ERROR;
48629  #endif
48630  #ifdef ESRMNT
48631  case ESRMNT: return DRWAV_ERROR;
48632  #endif
48633  #ifdef ECOMM
48634  case ECOMM: return DRWAV_ERROR;
48635  #endif
48636  #ifdef EPROTO
48637  case EPROTO: return DRWAV_ERROR;
48638  #endif
48639  #ifdef EMULTIHOP
48640  case EMULTIHOP: return DRWAV_ERROR;
48641  #endif
48642  #ifdef EDOTDOT
48643  case EDOTDOT: return DRWAV_ERROR;
48644  #endif
48645  #ifdef EBADMSG
48646  case EBADMSG: return DRWAV_BAD_MESSAGE;
48647  #endif
48648  #ifdef EOVERFLOW
48649  case EOVERFLOW: return DRWAV_TOO_BIG;
48650  #endif
48651  #ifdef ENOTUNIQ
48652  case ENOTUNIQ: return DRWAV_NOT_UNIQUE;
48653  #endif
48654  #ifdef EBADFD
48655  case EBADFD: return DRWAV_ERROR;
48656  #endif
48657  #ifdef EREMCHG
48658  case EREMCHG: return DRWAV_ERROR;
48659  #endif
48660  #ifdef ELIBACC
48661  case ELIBACC: return DRWAV_ACCESS_DENIED;
48662  #endif
48663  #ifdef ELIBBAD
48664  case ELIBBAD: return DRWAV_INVALID_FILE;
48665  #endif
48666  #ifdef ELIBSCN
48667  case ELIBSCN: return DRWAV_INVALID_FILE;
48668  #endif
48669  #ifdef ELIBMAX
48670  case ELIBMAX: return DRWAV_ERROR;
48671  #endif
48672  #ifdef ELIBEXEC
48673  case ELIBEXEC: return DRWAV_ERROR;
48674  #endif
48675  #ifdef EILSEQ
48676  case EILSEQ: return DRWAV_INVALID_DATA;
48677  #endif
48678  #ifdef ERESTART
48679  case ERESTART: return DRWAV_ERROR;
48680  #endif
48681  #ifdef ESTRPIPE
48682  case ESTRPIPE: return DRWAV_ERROR;
48683  #endif
48684  #ifdef EUSERS
48685  case EUSERS: return DRWAV_ERROR;
48686  #endif
48687  #ifdef ENOTSOCK
48688  case ENOTSOCK: return DRWAV_NOT_SOCKET;
48689  #endif
48690  #ifdef EDESTADDRREQ
48691  case EDESTADDRREQ: return DRWAV_NO_ADDRESS;
48692  #endif
48693  #ifdef EMSGSIZE
48694  case EMSGSIZE: return DRWAV_TOO_BIG;
48695  #endif
48696  #ifdef EPROTOTYPE
48697  case EPROTOTYPE: return DRWAV_BAD_PROTOCOL;
48698  #endif
48699  #ifdef ENOPROTOOPT
48700  case ENOPROTOOPT: return DRWAV_PROTOCOL_UNAVAILABLE;
48701  #endif
48702  #ifdef EPROTONOSUPPORT
48703  case EPROTONOSUPPORT: return DRWAV_PROTOCOL_NOT_SUPPORTED;
48704  #endif
48705  #ifdef ESOCKTNOSUPPORT
48706  case ESOCKTNOSUPPORT: return DRWAV_SOCKET_NOT_SUPPORTED;
48707  #endif
48708  #ifdef EOPNOTSUPP
48709  case EOPNOTSUPP: return DRWAV_INVALID_OPERATION;
48710  #endif
48711  #ifdef EPFNOSUPPORT
48712  case EPFNOSUPPORT: return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
48713  #endif
48714  #ifdef EAFNOSUPPORT
48715  case EAFNOSUPPORT: return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
48716  #endif
48717  #ifdef EADDRINUSE
48718  case EADDRINUSE: return DRWAV_ALREADY_IN_USE;
48719  #endif
48720  #ifdef EADDRNOTAVAIL
48721  case EADDRNOTAVAIL: return DRWAV_ERROR;
48722  #endif
48723  #ifdef ENETDOWN
48724  case ENETDOWN: return DRWAV_NO_NETWORK;
48725  #endif
48726  #ifdef ENETUNREACH
48727  case ENETUNREACH: return DRWAV_NO_NETWORK;
48728  #endif
48729  #ifdef ENETRESET
48730  case ENETRESET: return DRWAV_NO_NETWORK;
48731  #endif
48732  #ifdef ECONNABORTED
48733  case ECONNABORTED: return DRWAV_NO_NETWORK;
48734  #endif
48735  #ifdef ECONNRESET
48736  case ECONNRESET: return DRWAV_CONNECTION_RESET;
48737  #endif
48738  #ifdef ENOBUFS
48739  case ENOBUFS: return DRWAV_NO_SPACE;
48740  #endif
48741  #ifdef EISCONN
48742  case EISCONN: return DRWAV_ALREADY_CONNECTED;
48743  #endif
48744  #ifdef ENOTCONN
48745  case ENOTCONN: return DRWAV_NOT_CONNECTED;
48746  #endif
48747  #ifdef ESHUTDOWN
48748  case ESHUTDOWN: return DRWAV_ERROR;
48749  #endif
48750  #ifdef ETOOMANYREFS
48751  case ETOOMANYREFS: return DRWAV_ERROR;
48752  #endif
48753  #ifdef ETIMEDOUT
48754  case ETIMEDOUT: return DRWAV_TIMEOUT;
48755  #endif
48756  #ifdef ECONNREFUSED
48757  case ECONNREFUSED: return DRWAV_CONNECTION_REFUSED;
48758  #endif
48759  #ifdef EHOSTDOWN
48760  case EHOSTDOWN: return DRWAV_NO_HOST;
48761  #endif
48762  #ifdef EHOSTUNREACH
48763  case EHOSTUNREACH: return DRWAV_NO_HOST;
48764  #endif
48765  #ifdef EALREADY
48766  case EALREADY: return DRWAV_IN_PROGRESS;
48767  #endif
48768  #ifdef EINPROGRESS
48769  case EINPROGRESS: return DRWAV_IN_PROGRESS;
48770  #endif
48771  #ifdef ESTALE
48772  case ESTALE: return DRWAV_INVALID_FILE;
48773  #endif
48774  #ifdef EUCLEAN
48775  case EUCLEAN: return DRWAV_ERROR;
48776  #endif
48777  #ifdef ENOTNAM
48778  case ENOTNAM: return DRWAV_ERROR;
48779  #endif
48780  #ifdef ENAVAIL
48781  case ENAVAIL: return DRWAV_ERROR;
48782  #endif
48783  #ifdef EISNAM
48784  case EISNAM: return DRWAV_ERROR;
48785  #endif
48786  #ifdef EREMOTEIO
48787  case EREMOTEIO: return DRWAV_IO_ERROR;
48788  #endif
48789  #ifdef EDQUOT
48790  case EDQUOT: return DRWAV_NO_SPACE;
48791  #endif
48792  #ifdef ENOMEDIUM
48793  case ENOMEDIUM: return DRWAV_DOES_NOT_EXIST;
48794  #endif
48795  #ifdef EMEDIUMTYPE
48796  case EMEDIUMTYPE: return DRWAV_ERROR;
48797  #endif
48798  #ifdef ECANCELED
48799  case ECANCELED: return DRWAV_CANCELLED;
48800  #endif
48801  #ifdef ENOKEY
48802  case ENOKEY: return DRWAV_ERROR;
48803  #endif
48804  #ifdef EKEYEXPIRED
48805  case EKEYEXPIRED: return DRWAV_ERROR;
48806  #endif
48807  #ifdef EKEYREVOKED
48808  case EKEYREVOKED: return DRWAV_ERROR;
48809  #endif
48810  #ifdef EKEYREJECTED
48811  case EKEYREJECTED: return DRWAV_ERROR;
48812  #endif
48813  #ifdef EOWNERDEAD
48814  case EOWNERDEAD: return DRWAV_ERROR;
48815  #endif
48816  #ifdef ENOTRECOVERABLE
48817  case ENOTRECOVERABLE: return DRWAV_ERROR;
48818  #endif
48819  #ifdef ERFKILL
48820  case ERFKILL: return DRWAV_ERROR;
48821  #endif
48822  #ifdef EHWPOISON
48823  case EHWPOISON: return DRWAV_ERROR;
48824  #endif
48825  default: return DRWAV_ERROR;
48826  }
48827 }
48828 DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
48829 {
48830 #if defined(_MSC_VER) && _MSC_VER >= 1400
48831  errno_t err;
48832 #endif
48833  if (ppFile != NULL) {
48834  *ppFile = NULL;
48835  }
48836  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
48837  return DRWAV_INVALID_ARGS;
48838  }
48839 #if defined(_MSC_VER) && _MSC_VER >= 1400
48840  err = fopen_s(ppFile, pFilePath, pOpenMode);
48841  if (err != 0) {
48842  return drwav_result_from_errno(err);
48843  }
48844 #else
48845 #if defined(_WIN32) || defined(__APPLE__)
48846  *ppFile = fopen(pFilePath, pOpenMode);
48847 #else
48848  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
48849  *ppFile = fopen64(pFilePath, pOpenMode);
48850  #else
48851  *ppFile = fopen(pFilePath, pOpenMode);
48852  #endif
48853 #endif
48854  if (*ppFile == NULL) {
48856  if (result == DRWAV_SUCCESS) {
48857  result = DRWAV_ERROR;
48858  }
48859  return result;
48860  }
48861 #endif
48862  return DRWAV_SUCCESS;
48863 }
48864 #if defined(_WIN32)
48865  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
48866  #define DRWAV_HAS_WFOPEN
48867  #endif
48868 #endif
48869 DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
48870 {
48871  if (ppFile != NULL) {
48872  *ppFile = NULL;
48873  }
48874  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
48875  return DRWAV_INVALID_ARGS;
48876  }
48877 #if defined(DRWAV_HAS_WFOPEN)
48878  {
48879  #if defined(_MSC_VER) && _MSC_VER >= 1400
48880  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
48881  if (err != 0) {
48882  return drwav_result_from_errno(err);
48883  }
48884  #else
48885  *ppFile = _wfopen(pFilePath, pOpenMode);
48886  if (*ppFile == NULL) {
48888  }
48889  #endif
48890  (void)pAllocationCallbacks;
48891  }
48892 #else
48893  {
48894  mbstate_t mbs;
48895  size_t lenMB;
48896  const wchar_t* pFilePathTemp = pFilePath;
48897  char* pFilePathMB = NULL;
48898  char pOpenModeMB[32] = {0};
48899  DRWAV_ZERO_OBJECT(&mbs);
48900  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
48901  if (lenMB == (size_t)-1) {
48903  }
48904  pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
48905  if (pFilePathMB == NULL) {
48906  return DRWAV_OUT_OF_MEMORY;
48907  }
48908  pFilePathTemp = pFilePath;
48909  DRWAV_ZERO_OBJECT(&mbs);
48910  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
48911  {
48912  size_t i = 0;
48913  for (;;) {
48914  if (pOpenMode[i] == 0) {
48915  pOpenModeMB[i] = '\0';
48916  break;
48917  }
48918  pOpenModeMB[i] = (char)pOpenMode[i];
48919  i += 1;
48920  }
48921  }
48922  *ppFile = fopen(pFilePathMB, pOpenModeMB);
48923  drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
48924  }
48925  if (*ppFile == NULL) {
48926  return DRWAV_ERROR;
48927  }
48928 #endif
48929  return DRWAV_SUCCESS;
48930 }
48931 DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
48932 {
48933  return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
48934 }
48935 DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
48936 {
48937  return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
48938 }
48940 {
48941  return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
48942 }
48943 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
48944 {
48945  return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
48946 }
48947 DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(drwav* pWav, FILE* pFile, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, drwav_metadata_type allowedMetadataTypes, const drwav_allocation_callbacks* pAllocationCallbacks)
48948 {
48949  drwav_bool32 result;
48950  result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
48951  if (result != DRWAV_TRUE) {
48952  fclose(pFile);
48953  return result;
48954  }
48955  pWav->allowedMetadataTypes = allowedMetadataTypes;
48956  result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
48957  if (result != DRWAV_TRUE) {
48958  fclose(pFile);
48959  return result;
48960  }
48961  return DRWAV_TRUE;
48962 }
48963 DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
48964 {
48965  FILE* pFile;
48966  if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
48967  return DRWAV_FALSE;
48968  }
48969  return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
48970 }
48971 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
48972 {
48973  return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
48974 }
48975 DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
48976 {
48977  FILE* pFile;
48978  if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
48979  return DRWAV_FALSE;
48980  }
48981  return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
48982 }
48983 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
48984 {
48985  FILE* pFile;
48986  if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
48987  return DRWAV_FALSE;
48988  }
48989  return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
48990 }
48991 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
48992 {
48993  FILE* pFile;
48994  if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
48995  return DRWAV_FALSE;
48996  }
48997  return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
48998 }
48999 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(drwav* pWav, FILE* pFile, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
49000 {
49001  drwav_bool32 result;
49002  result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
49003  if (result != DRWAV_TRUE) {
49004  fclose(pFile);
49005  return result;
49006  }
49007  result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
49008  if (result != DRWAV_TRUE) {
49009  fclose(pFile);
49010  return result;
49011  }
49012  return DRWAV_TRUE;
49013 }
49014 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
49015 {
49016  FILE* pFile;
49017  if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
49018  return DRWAV_FALSE;
49019  }
49020  return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
49021 }
49022 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
49023 {
49024  FILE* pFile;
49025  if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
49026  return DRWAV_FALSE;
49027  }
49028  return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
49029 }
49030 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
49031 {
49032  return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
49033 }
49034 DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
49035 {
49036  return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
49037 }
49038 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
49039 {
49040  if (pFormat == NULL) {
49041  return DRWAV_FALSE;
49042  }
49043  return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
49044 }
49045 DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
49046 {
49047  return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
49048 }
49049 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
49050 {
49051  return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
49052 }
49053 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
49054 {
49055  if (pFormat == NULL) {
49056  return DRWAV_FALSE;
49057  }
49058  return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
49059 }
49060 #endif
49061 DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
49062 {
49063  drwav* pWav = (drwav*)pUserData;
49064  size_t bytesRemaining;
49065  DRWAV_ASSERT(pWav != NULL);
49067  bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
49068  if (bytesToRead > bytesRemaining) {
49069  bytesToRead = bytesRemaining;
49070  }
49071  if (bytesToRead > 0) {
49072  DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
49073  pWav->memoryStream.currentReadPos += bytesToRead;
49074  }
49075  return bytesToRead;
49076 }
49078 {
49079  drwav* pWav = (drwav*)pUserData;
49080  DRWAV_ASSERT(pWav != NULL);
49081  if (origin == drwav_seek_origin_current) {
49082  if (offset > 0) {
49083  if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
49084  return DRWAV_FALSE;
49085  }
49086  } else {
49087  if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
49088  return DRWAV_FALSE;
49089  }
49090  }
49091  pWav->memoryStream.currentReadPos += offset;
49092  } else {
49093  if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
49094  pWav->memoryStream.currentReadPos = offset;
49095  } else {
49096  return DRWAV_FALSE;
49097  }
49098  }
49099  return DRWAV_TRUE;
49100 }
49101 DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
49102 {
49103  drwav* pWav = (drwav*)pUserData;
49104  size_t bytesRemaining;
49105  DRWAV_ASSERT(pWav != NULL);
49107  bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
49108  if (bytesRemaining < bytesToWrite) {
49109  void* pNewData;
49110  size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
49111  if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
49112  newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
49113  }
49115  if (pNewData == NULL) {
49116  return 0;
49117  }
49118  *pWav->memoryStreamWrite.ppData = pNewData;
49119  pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
49120  }
49121  DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
49122  pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
49125  }
49127  return bytesToWrite;
49128 }
49130 {
49131  drwav* pWav = (drwav*)pUserData;
49132  DRWAV_ASSERT(pWav != NULL);
49133  if (origin == drwav_seek_origin_current) {
49134  if (offset > 0) {
49135  if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
49136  offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);
49137  }
49138  } else {
49139  if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
49140  offset = -(int)pWav->memoryStreamWrite.currentWritePos;
49141  }
49142  }
49143  pWav->memoryStreamWrite.currentWritePos += offset;
49144  } else {
49145  if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
49146  pWav->memoryStreamWrite.currentWritePos = offset;
49147  } else {
49149  }
49150  }
49151  return DRWAV_TRUE;
49152 }
49153 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
49154 {
49155  return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
49156 }
49157 DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
49158 {
49159  if (data == NULL || dataSize == 0) {
49160  return DRWAV_FALSE;
49161  }
49162  if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
49163  return DRWAV_FALSE;
49164  }
49165  pWav->memoryStream.data = (const drwav_uint8*)data;
49166  pWav->memoryStream.dataSize = dataSize;
49167  pWav->memoryStream.currentReadPos = 0;
49168  return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
49169 }
49170 DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void* data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
49171 {
49172  if (data == NULL || dataSize == 0) {
49173  return DRWAV_FALSE;
49174  }
49175  if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
49176  return DRWAV_FALSE;
49177  }
49178  pWav->memoryStream.data = (const drwav_uint8*)data;
49179  pWav->memoryStream.dataSize = dataSize;
49180  pWav->memoryStream.currentReadPos = 0;
49182  return drwav_init__internal(pWav, NULL, NULL, flags);
49183 }
49184 DRWAV_PRIVATE drwav_bool32 drwav_init_memory_write__internal(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
49185 {
49186  if (ppData == NULL || pDataSize == NULL) {
49187  return DRWAV_FALSE;
49188  }
49189  *ppData = NULL;
49190  *pDataSize = 0;
49191  if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
49192  return DRWAV_FALSE;
49193  }
49194  pWav->memoryStreamWrite.ppData = ppData;
49195  pWav->memoryStreamWrite.pDataSize = pDataSize;
49196  pWav->memoryStreamWrite.dataSize = 0;
49197  pWav->memoryStreamWrite.dataCapacity = 0;
49199  return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
49200 }
49201 DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
49202 {
49203  return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
49204 }
49205 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
49206 {
49207  return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
49208 }
49209 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
49210 {
49211  if (pFormat == NULL) {
49212  return DRWAV_FALSE;
49213  }
49214  return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
49215 }
49217 {
49218  drwav_result result = DRWAV_SUCCESS;
49219  if (pWav == NULL) {
49220  return DRWAV_INVALID_ARGS;
49221  }
49222  if (pWav->onWrite != NULL) {
49223  drwav_uint32 paddingSize = 0;
49224  if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
49226  } else {
49227  paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
49228  }
49229  if (paddingSize > 0) {
49230  drwav_uint64 paddingData = 0;
49231  drwav__write(pWav, &paddingData, paddingSize);
49232  }
49233  if (pWav->onSeek && !pWav->isSequentialWrite) {
49234  if (pWav->container == drwav_container_riff) {
49235  if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
49237  drwav__write_u32ne_to_le(pWav, riffChunkSize);
49238  }
49239  if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
49241  drwav__write_u32ne_to_le(pWav, dataChunkSize);
49242  }
49243  } else if (pWav->container == drwav_container_w64) {
49244  if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
49246  drwav__write_u64ne_to_le(pWav, riffChunkSize);
49247  }
49248  if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
49250  drwav__write_u64ne_to_le(pWav, dataChunkSize);
49251  }
49252  } else if (pWav->container == drwav_container_rf64) {
49253  int ds64BodyPos = 12 + 8;
49254  if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
49256  drwav__write_u64ne_to_le(pWav, riffChunkSize);
49257  }
49258  if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
49260  drwav__write_u64ne_to_le(pWav, dataChunkSize);
49261  }
49262  }
49263  }
49264  if (pWav->isSequentialWrite) {
49265  if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
49266  result = DRWAV_INVALID_FILE;
49267  }
49268  }
49269  } else {
49270  if (pWav->pMetadata != NULL) {
49272  }
49273  }
49274 #ifndef DR_WAV_NO_STDIO
49275  if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
49276  fclose((FILE*)pWav->pUserData);
49277  }
49278 #endif
49279  return result;
49280 }
49281 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
49282 {
49283  size_t bytesRead;
49284  if (pWav == NULL || bytesToRead == 0) {
49285  return 0;
49286  }
49287  if (bytesToRead > pWav->bytesRemaining) {
49288  bytesToRead = (size_t)pWav->bytesRemaining;
49289  }
49290  if (bytesToRead == 0) {
49291  return 0;
49292  }
49293  if (pBufferOut != NULL) {
49294  bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
49295  } else {
49296  bytesRead = 0;
49297  while (bytesRead < bytesToRead) {
49298  size_t bytesToSeek = (bytesToRead - bytesRead);
49299  if (bytesToSeek > 0x7FFFFFFF) {
49300  bytesToSeek = 0x7FFFFFFF;
49301  }
49302  if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
49303  break;
49304  }
49305  bytesRead += bytesToSeek;
49306  }
49307  while (bytesRead < bytesToRead) {
49308  drwav_uint8 buffer[4096];
49309  size_t bytesSeeked;
49310  size_t bytesToSeek = (bytesToRead - bytesRead);
49311  if (bytesToSeek > sizeof(buffer)) {
49312  bytesToSeek = sizeof(buffer);
49313  }
49314  bytesSeeked = pWav->onRead(pWav->pUserData, buffer, bytesToSeek);
49315  bytesRead += bytesSeeked;
49316  if (bytesSeeked < bytesToSeek) {
49317  break;
49318  }
49319  }
49320  }
49321  pWav->readCursorInPCMFrames += bytesRead / drwav_get_bytes_per_pcm_frame(pWav);
49322  pWav->bytesRemaining -= bytesRead;
49323  return bytesRead;
49324 }
49325 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
49326 {
49327  drwav_uint32 bytesPerFrame;
49328  drwav_uint64 bytesToRead;
49329  if (pWav == NULL || framesToRead == 0) {
49330  return 0;
49331  }
49333  return 0;
49334  }
49335  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
49336  if (bytesPerFrame == 0) {
49337  return 0;
49338  }
49339  bytesToRead = framesToRead * bytesPerFrame;
49340  if (bytesToRead > DRWAV_SIZE_MAX) {
49341  bytesToRead = (DRWAV_SIZE_MAX / bytesPerFrame) * bytesPerFrame;
49342  }
49343  if (bytesToRead == 0) {
49344  return 0;
49345  }
49346  return drwav_read_raw(pWav, (size_t)bytesToRead, pBufferOut) / bytesPerFrame;
49347 }
49348 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
49349 {
49350  drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
49351  if (pBufferOut != NULL) {
49352  drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, drwav_get_bytes_per_pcm_frame(pWav)/pWav->channels, pWav->translatedFormatTag);
49353  }
49354  return framesRead;
49355 }
49356 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
49357 {
49358  if (drwav__is_little_endian()) {
49359  return drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
49360  } else {
49361  return drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
49362  }
49363 }
49365 {
49366  if (pWav->onWrite != NULL) {
49367  return DRWAV_FALSE;
49368  }
49369  if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
49370  return DRWAV_FALSE;
49371  }
49374  DRWAV_ZERO_OBJECT(&pWav->msadpcm);
49375  } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
49376  DRWAV_ZERO_OBJECT(&pWav->ima);
49377  } else {
49379  }
49380  }
49381  pWav->readCursorInPCMFrames = 0;
49382  pWav->bytesRemaining = pWav->dataChunkDataSize;
49383  return DRWAV_TRUE;
49384 }
49386 {
49387  if (pWav == NULL || pWav->onSeek == NULL) {
49388  return DRWAV_FALSE;
49389  }
49390  if (pWav->onWrite != NULL) {
49391  return DRWAV_FALSE;
49392  }
49393  if (pWav->totalPCMFrameCount == 0) {
49394  return DRWAV_TRUE;
49395  }
49396  if (targetFrameIndex >= pWav->totalPCMFrameCount) {
49397  targetFrameIndex = pWav->totalPCMFrameCount - 1;
49398  }
49400  if (targetFrameIndex < pWav->readCursorInPCMFrames) {
49401  if (!drwav_seek_to_first_pcm_frame(pWav)) {
49402  return DRWAV_FALSE;
49403  }
49404  }
49405  if (targetFrameIndex > pWav->readCursorInPCMFrames) {
49406  drwav_uint64 offsetInFrames = targetFrameIndex - pWav->readCursorInPCMFrames;
49407  drwav_int16 devnull[2048];
49408  while (offsetInFrames > 0) {
49409  drwav_uint64 framesRead = 0;
49410  drwav_uint64 framesToRead = offsetInFrames;
49411  if (framesToRead > drwav_countof(devnull)/pWav->channels) {
49412  framesToRead = drwav_countof(devnull)/pWav->channels;
49413  }
49415  framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
49416  } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
49417  framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
49418  } else {
49420  }
49421  if (framesRead != framesToRead) {
49422  return DRWAV_FALSE;
49423  }
49424  offsetInFrames -= framesRead;
49425  }
49426  }
49427  } else {
49428  drwav_uint64 totalSizeInBytes;
49429  drwav_uint64 currentBytePos;
49430  drwav_uint64 targetBytePos;
49431  drwav_uint64 offset;
49432  totalSizeInBytes = pWav->totalPCMFrameCount * drwav_get_bytes_per_pcm_frame(pWav);
49433  DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);
49434  currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
49435  targetBytePos = targetFrameIndex * drwav_get_bytes_per_pcm_frame(pWav);
49436  if (currentBytePos < targetBytePos) {
49437  offset = (targetBytePos - currentBytePos);
49438  } else {
49439  if (!drwav_seek_to_first_pcm_frame(pWav)) {
49440  return DRWAV_FALSE;
49441  }
49442  offset = targetBytePos;
49443  }
49444  while (offset > 0) {
49445  int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
49446  if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
49447  return DRWAV_FALSE;
49448  }
49449  pWav->readCursorInPCMFrames += offset32 / drwav_get_bytes_per_pcm_frame(pWav);
49450  pWav->bytesRemaining -= offset32;
49451  offset -= offset32;
49452  }
49453  }
49454  return DRWAV_TRUE;
49455 }
49457 {
49458  if (pCursor == NULL) {
49459  return DRWAV_INVALID_ARGS;
49460  }
49461  *pCursor = 0;
49462  if (pWav == NULL) {
49463  return DRWAV_INVALID_ARGS;
49464  }
49465  *pCursor = pWav->readCursorInPCMFrames;
49466  return DRWAV_SUCCESS;
49467 }
49469 {
49470  if (pLength == NULL) {
49471  return DRWAV_INVALID_ARGS;
49472  }
49473  *pLength = 0;
49474  if (pWav == NULL) {
49475  return DRWAV_INVALID_ARGS;
49476  }
49477  *pLength = pWav->totalPCMFrameCount;
49478  return DRWAV_SUCCESS;
49479 }
49480 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
49481 {
49482  size_t bytesWritten;
49483  if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
49484  return 0;
49485  }
49486  bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
49487  pWav->dataChunkDataSize += bytesWritten;
49488  return bytesWritten;
49489 }
49490 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
49491 {
49492  drwav_uint64 bytesToWrite;
49493  drwav_uint64 bytesWritten;
49494  const drwav_uint8* pRunningData;
49495  if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
49496  return 0;
49497  }
49498  bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
49499  if (bytesToWrite > DRWAV_SIZE_MAX) {
49500  return 0;
49501  }
49502  bytesWritten = 0;
49503  pRunningData = (const drwav_uint8*)pData;
49504  while (bytesToWrite > 0) {
49505  size_t bytesJustWritten;
49506  drwav_uint64 bytesToWriteThisIteration;
49507  bytesToWriteThisIteration = bytesToWrite;
49508  DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
49509  bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
49510  if (bytesJustWritten == 0) {
49511  break;
49512  }
49513  bytesToWrite -= bytesJustWritten;
49514  bytesWritten += bytesJustWritten;
49515  pRunningData += bytesJustWritten;
49516  }
49517  return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
49518 }
49519 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
49520 {
49521  drwav_uint64 bytesToWrite;
49522  drwav_uint64 bytesWritten;
49523  drwav_uint32 bytesPerSample;
49524  const drwav_uint8* pRunningData;
49525  if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
49526  return 0;
49527  }
49528  bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
49529  if (bytesToWrite > DRWAV_SIZE_MAX) {
49530  return 0;
49531  }
49532  bytesWritten = 0;
49533  pRunningData = (const drwav_uint8*)pData;
49534  bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
49535  while (bytesToWrite > 0) {
49536  drwav_uint8 temp[4096];
49537  drwav_uint32 sampleCount;
49538  size_t bytesJustWritten;
49539  drwav_uint64 bytesToWriteThisIteration;
49540  bytesToWriteThisIteration = bytesToWrite;
49541  DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
49542  sampleCount = sizeof(temp)/bytesPerSample;
49543  if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
49544  bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
49545  }
49546  DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
49547  drwav__bswap_samples(temp, sampleCount, bytesPerSample, pWav->translatedFormatTag);
49548  bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, temp);
49549  if (bytesJustWritten == 0) {
49550  break;
49551  }
49552  bytesToWrite -= bytesJustWritten;
49553  bytesWritten += bytesJustWritten;
49554  pRunningData += bytesJustWritten;
49555  }
49556  return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
49557 }
49558 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
49559 {
49560  if (drwav__is_little_endian()) {
49561  return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
49562  } else {
49563  return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
49564  }
49565 }
49567 {
49568  drwav_uint64 totalFramesRead = 0;
49569  DRWAV_ASSERT(pWav != NULL);
49570  DRWAV_ASSERT(framesToRead > 0);
49571  while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
49572  DRWAV_ASSERT(framesToRead > 0);
49573  if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
49574  if (pWav->channels == 1) {
49575  drwav_uint8 header[7];
49576  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
49577  return totalFramesRead;
49578  }
49579  pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
49580  pWav->msadpcm.predictor[0] = header[0];
49581  pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 1);
49584  pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0];
49585  pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1];
49586  pWav->msadpcm.cachedFrameCount = 2;
49587  } else {
49588  drwav_uint8 header[14];
49589  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
49590  return totalFramesRead;
49591  }
49592  pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
49593  pWav->msadpcm.predictor[0] = header[0];
49594  pWav->msadpcm.predictor[1] = header[1];
49595  pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 2);
49596  pWav->msadpcm.delta[1] = drwav_bytes_to_s16(header + 4);
49601  pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
49602  pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
49603  pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
49604  pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
49605  pWav->msadpcm.cachedFrameCount = 2;
49606  }
49607  }
49608  while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
49609  if (pBufferOut != NULL) {
49610  drwav_uint32 iSample = 0;
49611  for (iSample = 0; iSample < pWav->channels; iSample += 1) {
49612  pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
49613  }
49614  pBufferOut += pWav->channels;
49615  }
49616  framesToRead -= 1;
49617  totalFramesRead += 1;
49618  pWav->readCursorInPCMFrames += 1;
49619  pWav->msadpcm.cachedFrameCount -= 1;
49620  }
49621  if (framesToRead == 0) {
49622  break;
49623  }
49624  if (pWav->msadpcm.cachedFrameCount == 0) {
49625  if (pWav->msadpcm.bytesRemainingInBlock == 0) {
49626  continue;
49627  } else {
49628  static drwav_int32 adaptationTable[] = {
49629  230, 230, 230, 230, 307, 409, 512, 614,
49630  768, 614, 512, 409, 307, 230, 230, 230
49631  };
49632  static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
49633  static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
49634  drwav_uint8 nibbles;
49635  drwav_int32 nibble0;
49636  drwav_int32 nibble1;
49637  if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
49638  return totalFramesRead;
49639  }
49640  pWav->msadpcm.bytesRemainingInBlock -= 1;
49641  nibble0 = ((nibbles & 0xF0) >> 4); if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
49642  nibble1 = ((nibbles & 0x0F) >> 0); if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
49643  if (pWav->channels == 1) {
49644  drwav_int32 newSample0;
49645  drwav_int32 newSample1;
49646  newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
49647  newSample0 += nibble0 * pWav->msadpcm.delta[0];
49648  newSample0 = drwav_clamp(newSample0, -32768, 32767);
49649  pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
49650  if (pWav->msadpcm.delta[0] < 16) {
49651  pWav->msadpcm.delta[0] = 16;
49652  }
49653  pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
49654  pWav->msadpcm.prevFrames[0][1] = newSample0;
49655  newSample1 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
49656  newSample1 += nibble1 * pWav->msadpcm.delta[0];
49657  newSample1 = drwav_clamp(newSample1, -32768, 32767);
49658  pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
49659  if (pWav->msadpcm.delta[0] < 16) {
49660  pWav->msadpcm.delta[0] = 16;
49661  }
49662  pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
49663  pWav->msadpcm.prevFrames[0][1] = newSample1;
49664  pWav->msadpcm.cachedFrames[2] = newSample0;
49665  pWav->msadpcm.cachedFrames[3] = newSample1;
49666  pWav->msadpcm.cachedFrameCount = 2;
49667  } else {
49668  drwav_int32 newSample0;
49669  drwav_int32 newSample1;
49670  newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
49671  newSample0 += nibble0 * pWav->msadpcm.delta[0];
49672  newSample0 = drwav_clamp(newSample0, -32768, 32767);
49673  pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
49674  if (pWav->msadpcm.delta[0] < 16) {
49675  pWav->msadpcm.delta[0] = 16;
49676  }
49677  pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
49678  pWav->msadpcm.prevFrames[0][1] = newSample0;
49679  newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
49680  newSample1 += nibble1 * pWav->msadpcm.delta[1];
49681  newSample1 = drwav_clamp(newSample1, -32768, 32767);
49682  pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
49683  if (pWav->msadpcm.delta[1] < 16) {
49684  pWav->msadpcm.delta[1] = 16;
49685  }
49686  pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
49687  pWav->msadpcm.prevFrames[1][1] = newSample1;
49688  pWav->msadpcm.cachedFrames[2] = newSample0;
49689  pWav->msadpcm.cachedFrames[3] = newSample1;
49690  pWav->msadpcm.cachedFrameCount = 1;
49691  }
49692  }
49693  }
49694  }
49695  return totalFramesRead;
49696 }
49698 {
49699  drwav_uint64 totalFramesRead = 0;
49700  drwav_uint32 iChannel;
49701  static drwav_int32 indexTable[16] = {
49702  -1, -1, -1, -1, 2, 4, 6, 8,
49703  -1, -1, -1, -1, 2, 4, 6, 8
49704  };
49705  static drwav_int32 stepTable[89] = {
49706  7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
49707  19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
49708  50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
49709  130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
49710  337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
49711  876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
49712  2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
49713  5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
49714  15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
49715  };
49716  DRWAV_ASSERT(pWav != NULL);
49717  DRWAV_ASSERT(framesToRead > 0);
49718  while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
49719  DRWAV_ASSERT(framesToRead > 0);
49720  if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
49721  if (pWav->channels == 1) {
49722  drwav_uint8 header[4];
49723  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
49724  return totalFramesRead;
49725  }
49726  pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
49727  if (header[2] >= drwav_countof(stepTable)) {
49729  pWav->ima.bytesRemainingInBlock = 0;
49730  return totalFramesRead;
49731  }
49732  pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
49733  pWav->ima.stepIndex[0] = header[2];
49734  pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
49735  pWav->ima.cachedFrameCount = 1;
49736  } else {
49737  drwav_uint8 header[8];
49738  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
49739  return totalFramesRead;
49740  }
49741  pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
49742  if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
49744  pWav->ima.bytesRemainingInBlock = 0;
49745  return totalFramesRead;
49746  }
49747  pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
49748  pWav->ima.stepIndex[0] = header[2];
49749  pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
49750  pWav->ima.stepIndex[1] = header[6];
49751  pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
49752  pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
49753  pWav->ima.cachedFrameCount = 1;
49754  }
49755  }
49756  while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
49757  if (pBufferOut != NULL) {
49758  drwav_uint32 iSample;
49759  for (iSample = 0; iSample < pWav->channels; iSample += 1) {
49760  pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
49761  }
49762  pBufferOut += pWav->channels;
49763  }
49764  framesToRead -= 1;
49765  totalFramesRead += 1;
49766  pWav->readCursorInPCMFrames += 1;
49767  pWav->ima.cachedFrameCount -= 1;
49768  }
49769  if (framesToRead == 0) {
49770  break;
49771  }
49772  if (pWav->ima.cachedFrameCount == 0) {
49773  if (pWav->ima.bytesRemainingInBlock == 0) {
49774  continue;
49775  } else {
49776  pWav->ima.cachedFrameCount = 8;
49777  for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
49778  drwav_uint32 iByte;
49779  drwav_uint8 nibbles[4];
49780  if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
49781  pWav->ima.cachedFrameCount = 0;
49782  return totalFramesRead;
49783  }
49784  pWav->ima.bytesRemainingInBlock -= 4;
49785  for (iByte = 0; iByte < 4; ++iByte) {
49786  drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
49787  drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
49788  drwav_int32 step = stepTable[pWav->ima.stepIndex[iChannel]];
49789  drwav_int32 predictor = pWav->ima.predictor[iChannel];
49790  drwav_int32 diff = step >> 3;
49791  if (nibble0 & 1) diff += step >> 2;
49792  if (nibble0 & 2) diff += step >> 1;
49793  if (nibble0 & 4) diff += step;
49794  if (nibble0 & 8) diff = -diff;
49795  predictor = drwav_clamp(predictor + diff, -32768, 32767);
49796  pWav->ima.predictor[iChannel] = predictor;
49797  pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
49798  pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
49799  step = stepTable[pWav->ima.stepIndex[iChannel]];
49800  predictor = pWav->ima.predictor[iChannel];
49801  diff = step >> 3;
49802  if (nibble1 & 1) diff += step >> 2;
49803  if (nibble1 & 2) diff += step >> 1;
49804  if (nibble1 & 4) diff += step;
49805  if (nibble1 & 8) diff = -diff;
49806  predictor = drwav_clamp(predictor + diff, -32768, 32767);
49807  pWav->ima.predictor[iChannel] = predictor;
49808  pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
49809  pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
49810  }
49811  }
49812  }
49813  }
49814  }
49815  return totalFramesRead;
49816 }
49817 #ifndef DR_WAV_NO_CONVERSION_API
49818 static unsigned short g_drwavAlawTable[256] = {
49819  0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
49820  0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
49821  0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
49822  0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
49823  0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
49824  0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
49825  0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
49826  0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
49827  0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
49828  0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
49829  0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
49830  0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
49831  0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
49832  0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
49833  0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
49834  0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
49835 };
49836 static unsigned short g_drwavMulawTable[256] = {
49837  0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
49838  0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
49839  0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
49840  0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
49841  0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
49842  0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
49843  0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
49844  0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
49845  0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
49846  0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
49847  0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
49848  0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
49849  0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
49850  0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
49851  0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
49852  0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
49853 };
49855 {
49856  return (short)g_drwavAlawTable[sampleIn];
49857 }
49859 {
49860  return (short)g_drwavMulawTable[sampleIn];
49861 }
49862 DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
49863 {
49864  unsigned int i;
49865  if (bytesPerSample == 1) {
49866  drwav_u8_to_s16(pOut, pIn, totalSampleCount);
49867  return;
49868  }
49869  if (bytesPerSample == 2) {
49870  for (i = 0; i < totalSampleCount; ++i) {
49871  *pOut++ = ((const drwav_int16*)pIn)[i];
49872  }
49873  return;
49874  }
49875  if (bytesPerSample == 3) {
49876  drwav_s24_to_s16(pOut, pIn, totalSampleCount);
49877  return;
49878  }
49879  if (bytesPerSample == 4) {
49880  drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
49881  return;
49882  }
49883  if (bytesPerSample > 8) {
49884  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
49885  return;
49886  }
49887  for (i = 0; i < totalSampleCount; ++i) {
49888  drwav_uint64 sample = 0;
49889  unsigned int shift = (8 - bytesPerSample) * 8;
49890  unsigned int j;
49891  for (j = 0; j < bytesPerSample; j += 1) {
49892  DRWAV_ASSERT(j < 8);
49893  sample |= (drwav_uint64)(pIn[j]) << shift;
49894  shift += 8;
49895  }
49896  pIn += j;
49897  *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
49898  }
49899 }
49900 DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
49901 {
49902  if (bytesPerSample == 4) {
49903  drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
49904  return;
49905  } else if (bytesPerSample == 8) {
49906  drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
49907  return;
49908  } else {
49909  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
49910  return;
49911  }
49912 }
49914 {
49915  drwav_uint64 totalFramesRead;
49916  drwav_uint8 sampleData[4096];
49917  drwav_uint32 bytesPerFrame;
49918  if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
49919  return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
49920  }
49921  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
49922  if (bytesPerFrame == 0) {
49923  return 0;
49924  }
49925  totalFramesRead = 0;
49926  while (framesToRead > 0) {
49927  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
49928  if (framesRead == 0) {
49929  break;
49930  }
49931  drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
49932  pBufferOut += framesRead*pWav->channels;
49933  framesToRead -= framesRead;
49934  totalFramesRead += framesRead;
49935  }
49936  return totalFramesRead;
49937 }
49939 {
49940  drwav_uint64 totalFramesRead;
49941  drwav_uint8 sampleData[4096];
49942  drwav_uint32 bytesPerFrame;
49943  if (pBufferOut == NULL) {
49944  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
49945  }
49946  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
49947  if (bytesPerFrame == 0) {
49948  return 0;
49949  }
49950  totalFramesRead = 0;
49951  while (framesToRead > 0) {
49952  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
49953  if (framesRead == 0) {
49954  break;
49955  }
49956  drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
49957  pBufferOut += framesRead*pWav->channels;
49958  framesToRead -= framesRead;
49959  totalFramesRead += framesRead;
49960  }
49961  return totalFramesRead;
49962 }
49964 {
49965  drwav_uint64 totalFramesRead;
49966  drwav_uint8 sampleData[4096];
49967  drwav_uint32 bytesPerFrame;
49968  if (pBufferOut == NULL) {
49969  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
49970  }
49971  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
49972  if (bytesPerFrame == 0) {
49973  return 0;
49974  }
49975  totalFramesRead = 0;
49976  while (framesToRead > 0) {
49977  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
49978  if (framesRead == 0) {
49979  break;
49980  }
49981  drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
49982  pBufferOut += framesRead*pWav->channels;
49983  framesToRead -= framesRead;
49984  totalFramesRead += framesRead;
49985  }
49986  return totalFramesRead;
49987 }
49989 {
49990  drwav_uint64 totalFramesRead;
49991  drwav_uint8 sampleData[4096];
49992  drwav_uint32 bytesPerFrame;
49993  if (pBufferOut == NULL) {
49994  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
49995  }
49996  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
49997  if (bytesPerFrame == 0) {
49998  return 0;
49999  }
50000  totalFramesRead = 0;
50001  while (framesToRead > 0) {
50002  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50003  if (framesRead == 0) {
50004  break;
50005  }
50006  drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
50007  pBufferOut += framesRead*pWav->channels;
50008  framesToRead -= framesRead;
50009  totalFramesRead += framesRead;
50010  }
50011  return totalFramesRead;
50012 }
50014 {
50015  if (pWav == NULL || framesToRead == 0) {
50016  return 0;
50017  }
50018  if (pBufferOut == NULL) {
50019  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
50020  }
50021  if (framesToRead * pWav->channels * sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
50022  framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int16) / pWav->channels;
50023  }
50024  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
50025  return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
50026  }
50028  return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
50029  }
50031  return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
50032  }
50034  return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
50035  }
50037  return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
50038  }
50040  return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
50041  }
50042  return 0;
50043 }
50045 {
50046  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
50047  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
50048  drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
50049  }
50050  return framesRead;
50051 }
50053 {
50054  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
50055  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
50056  drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
50057  }
50058  return framesRead;
50059 }
50060 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
50061 {
50062  int r;
50063  size_t i;
50064  for (i = 0; i < sampleCount; ++i) {
50065  int x = pIn[i];
50066  r = x << 8;
50067  r = r - 32768;
50068  pOut[i] = (short)r;
50069  }
50070 }
50071 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
50072 {
50073  int r;
50074  size_t i;
50075  for (i = 0; i < sampleCount; ++i) {
50076  int x = ((int)(((unsigned int)(((const drwav_uint8*)pIn)[i*3+0]) << 8) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+1]) << 16) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+2])) << 24)) >> 8;
50077  r = x >> 8;
50078  pOut[i] = (short)r;
50079  }
50080 }
50081 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount)
50082 {
50083  int r;
50084  size_t i;
50085  for (i = 0; i < sampleCount; ++i) {
50086  int x = pIn[i];
50087  r = x >> 16;
50088  pOut[i] = (short)r;
50089  }
50090 }
50091 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount)
50092 {
50093  int r;
50094  size_t i;
50095  for (i = 0; i < sampleCount; ++i) {
50096  float x = pIn[i];
50097  float c;
50098  c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
50099  c = c + 1;
50100  r = (int)(c * 32767.5f);
50101  r = r - 32768;
50102  pOut[i] = (short)r;
50103  }
50104 }
50105 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount)
50106 {
50107  int r;
50108  size_t i;
50109  for (i = 0; i < sampleCount; ++i) {
50110  double x = pIn[i];
50111  double c;
50112  c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
50113  c = c + 1;
50114  r = (int)(c * 32767.5);
50115  r = r - 32768;
50116  pOut[i] = (short)r;
50117  }
50118 }
50119 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
50120 {
50121  size_t i;
50122  for (i = 0; i < sampleCount; ++i) {
50123  pOut[i] = drwav__alaw_to_s16(pIn[i]);
50124  }
50125 }
50126 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
50127 {
50128  size_t i;
50129  for (i = 0; i < sampleCount; ++i) {
50130  pOut[i] = drwav__mulaw_to_s16(pIn[i]);
50131  }
50132 }
50133 DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
50134 {
50135  unsigned int i;
50136  if (bytesPerSample == 1) {
50137  drwav_u8_to_f32(pOut, pIn, sampleCount);
50138  return;
50139  }
50140  if (bytesPerSample == 2) {
50141  drwav_s16_to_f32(pOut, (const drwav_int16*)pIn, sampleCount);
50142  return;
50143  }
50144  if (bytesPerSample == 3) {
50145  drwav_s24_to_f32(pOut, pIn, sampleCount);
50146  return;
50147  }
50148  if (bytesPerSample == 4) {
50149  drwav_s32_to_f32(pOut, (const drwav_int32*)pIn, sampleCount);
50150  return;
50151  }
50152  if (bytesPerSample > 8) {
50153  DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
50154  return;
50155  }
50156  for (i = 0; i < sampleCount; ++i) {
50157  drwav_uint64 sample = 0;
50158  unsigned int shift = (8 - bytesPerSample) * 8;
50159  unsigned int j;
50160  for (j = 0; j < bytesPerSample; j += 1) {
50161  DRWAV_ASSERT(j < 8);
50162  sample |= (drwav_uint64)(pIn[j]) << shift;
50163  shift += 8;
50164  }
50165  pIn += j;
50166  *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
50167  }
50168 }
50169 DRWAV_PRIVATE void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
50170 {
50171  if (bytesPerSample == 4) {
50172  unsigned int i;
50173  for (i = 0; i < sampleCount; ++i) {
50174  *pOut++ = ((const float*)pIn)[i];
50175  }
50176  return;
50177  } else if (bytesPerSample == 8) {
50178  drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
50179  return;
50180  } else {
50181  DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
50182  return;
50183  }
50184 }
50186 {
50187  drwav_uint64 totalFramesRead;
50188  drwav_uint8 sampleData[4096];
50189  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50190  if (bytesPerFrame == 0) {
50191  return 0;
50192  }
50193  totalFramesRead = 0;
50194  while (framesToRead > 0) {
50195  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50196  if (framesRead == 0) {
50197  break;
50198  }
50199  drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)framesRead*pWav->channels, bytesPerFrame/pWav->channels);
50200  pBufferOut += framesRead*pWav->channels;
50201  framesToRead -= framesRead;
50202  totalFramesRead += framesRead;
50203  }
50204  return totalFramesRead;
50205 }
50207 {
50208  drwav_uint64 totalFramesRead = 0;
50209  drwav_int16 samples16[2048];
50210  while (framesToRead > 0) {
50211  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
50212  if (framesRead == 0) {
50213  break;
50214  }
50215  drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
50216  pBufferOut += framesRead*pWav->channels;
50217  framesToRead -= framesRead;
50218  totalFramesRead += framesRead;
50219  }
50220  return totalFramesRead;
50221 }
50223 {
50224  drwav_uint64 totalFramesRead = 0;
50225  drwav_int16 samples16[2048];
50226  while (framesToRead > 0) {
50227  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
50228  if (framesRead == 0) {
50229  break;
50230  }
50231  drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
50232  pBufferOut += framesRead*pWav->channels;
50233  framesToRead -= framesRead;
50234  totalFramesRead += framesRead;
50235  }
50236  return totalFramesRead;
50237 }
50239 {
50240  drwav_uint64 totalFramesRead;
50241  drwav_uint8 sampleData[4096];
50242  drwav_uint32 bytesPerFrame;
50243  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
50244  return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
50245  }
50246  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50247  if (bytesPerFrame == 0) {
50248  return 0;
50249  }
50250  totalFramesRead = 0;
50251  while (framesToRead > 0) {
50252  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50253  if (framesRead == 0) {
50254  break;
50255  }
50256  drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
50257  pBufferOut += framesRead*pWav->channels;
50258  framesToRead -= framesRead;
50259  totalFramesRead += framesRead;
50260  }
50261  return totalFramesRead;
50262 }
50264 {
50265  drwav_uint64 totalFramesRead;
50266  drwav_uint8 sampleData[4096];
50267  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50268  if (bytesPerFrame == 0) {
50269  return 0;
50270  }
50271  totalFramesRead = 0;
50272  while (framesToRead > 0) {
50273  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50274  if (framesRead == 0) {
50275  break;
50276  }
50277  drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
50278  pBufferOut += framesRead*pWav->channels;
50279  framesToRead -= framesRead;
50280  totalFramesRead += framesRead;
50281  }
50282  return totalFramesRead;
50283 }
50285 {
50286  drwav_uint64 totalFramesRead;
50287  drwav_uint8 sampleData[4096];
50288  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50289  if (bytesPerFrame == 0) {
50290  return 0;
50291  }
50292  totalFramesRead = 0;
50293  while (framesToRead > 0) {
50294  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50295  if (framesRead == 0) {
50296  break;
50297  }
50298  drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
50299  pBufferOut += framesRead*pWav->channels;
50300  framesToRead -= framesRead;
50301  totalFramesRead += framesRead;
50302  }
50303  return totalFramesRead;
50304 }
50305 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
50306 {
50307  if (pWav == NULL || framesToRead == 0) {
50308  return 0;
50309  }
50310  if (pBufferOut == NULL) {
50311  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
50312  }
50313  if (framesToRead * pWav->channels * sizeof(float) > DRWAV_SIZE_MAX) {
50314  framesToRead = DRWAV_SIZE_MAX / sizeof(float) / pWav->channels;
50315  }
50316  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
50317  return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
50318  }
50320  return drwav_read_pcm_frames_f32__msadpcm(pWav, framesToRead, pBufferOut);
50321  }
50323  return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
50324  }
50326  return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
50327  }
50329  return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
50330  }
50332  return drwav_read_pcm_frames_f32__ima(pWav, framesToRead, pBufferOut);
50333  }
50334  return 0;
50335 }
50337 {
50338  drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
50339  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
50340  drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
50341  }
50342  return framesRead;
50343 }
50345 {
50346  drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
50347  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
50348  drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
50349  }
50350  return framesRead;
50351 }
50352 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
50353 {
50354  size_t i;
50355  if (pOut == NULL || pIn == NULL) {
50356  return;
50357  }
50358 #ifdef DR_WAV_LIBSNDFILE_COMPAT
50359  for (i = 0; i < sampleCount; ++i) {
50360  *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
50361  }
50362 #else
50363  for (i = 0; i < sampleCount; ++i) {
50364  float x = pIn[i];
50365  x = x * 0.00784313725490196078f;
50366  x = x - 1;
50367  *pOut++ = x;
50368  }
50369 #endif
50370 }
50371 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount)
50372 {
50373  size_t i;
50374  if (pOut == NULL || pIn == NULL) {
50375  return;
50376  }
50377  for (i = 0; i < sampleCount; ++i) {
50378  *pOut++ = pIn[i] * 0.000030517578125f;
50379  }
50380 }
50381 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
50382 {
50383  size_t i;
50384  if (pOut == NULL || pIn == NULL) {
50385  return;
50386  }
50387  for (i = 0; i < sampleCount; ++i) {
50388  double x;
50389  drwav_uint32 a = ((drwav_uint32)(pIn[i*3+0]) << 8);
50390  drwav_uint32 b = ((drwav_uint32)(pIn[i*3+1]) << 16);
50391  drwav_uint32 c = ((drwav_uint32)(pIn[i*3+2]) << 24);
50392  x = (double)((drwav_int32)(a | b | c) >> 8);
50393  *pOut++ = (float)(x * 0.00000011920928955078125);
50394  }
50395 }
50396 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount)
50397 {
50398  size_t i;
50399  if (pOut == NULL || pIn == NULL) {
50400  return;
50401  }
50402  for (i = 0; i < sampleCount; ++i) {
50403  *pOut++ = (float)(pIn[i] / 2147483648.0);
50404  }
50405 }
50406 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount)
50407 {
50408  size_t i;
50409  if (pOut == NULL || pIn == NULL) {
50410  return;
50411  }
50412  for (i = 0; i < sampleCount; ++i) {
50413  *pOut++ = (float)pIn[i];
50414  }
50415 }
50416 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
50417 {
50418  size_t i;
50419  if (pOut == NULL || pIn == NULL) {
50420  return;
50421  }
50422  for (i = 0; i < sampleCount; ++i) {
50423  *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
50424  }
50425 }
50426 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
50427 {
50428  size_t i;
50429  if (pOut == NULL || pIn == NULL) {
50430  return;
50431  }
50432  for (i = 0; i < sampleCount; ++i) {
50433  *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
50434  }
50435 }
50436 DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
50437 {
50438  unsigned int i;
50439  if (bytesPerSample == 1) {
50440  drwav_u8_to_s32(pOut, pIn, totalSampleCount);
50441  return;
50442  }
50443  if (bytesPerSample == 2) {
50444  drwav_s16_to_s32(pOut, (const drwav_int16*)pIn, totalSampleCount);
50445  return;
50446  }
50447  if (bytesPerSample == 3) {
50448  drwav_s24_to_s32(pOut, pIn, totalSampleCount);
50449  return;
50450  }
50451  if (bytesPerSample == 4) {
50452  for (i = 0; i < totalSampleCount; ++i) {
50453  *pOut++ = ((const drwav_int32*)pIn)[i];
50454  }
50455  return;
50456  }
50457  if (bytesPerSample > 8) {
50458  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
50459  return;
50460  }
50461  for (i = 0; i < totalSampleCount; ++i) {
50462  drwav_uint64 sample = 0;
50463  unsigned int shift = (8 - bytesPerSample) * 8;
50464  unsigned int j;
50465  for (j = 0; j < bytesPerSample; j += 1) {
50466  DRWAV_ASSERT(j < 8);
50467  sample |= (drwav_uint64)(pIn[j]) << shift;
50468  shift += 8;
50469  }
50470  pIn += j;
50471  *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
50472  }
50473 }
50474 DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
50475 {
50476  if (bytesPerSample == 4) {
50477  drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
50478  return;
50479  } else if (bytesPerSample == 8) {
50480  drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
50481  return;
50482  } else {
50483  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
50484  return;
50485  }
50486 }
50488 {
50489  drwav_uint64 totalFramesRead;
50490  drwav_uint8 sampleData[4096];
50491  drwav_uint32 bytesPerFrame;
50492  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
50493  return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
50494  }
50495  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50496  if (bytesPerFrame == 0) {
50497  return 0;
50498  }
50499  totalFramesRead = 0;
50500  while (framesToRead > 0) {
50501  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50502  if (framesRead == 0) {
50503  break;
50504  }
50505  drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
50506  pBufferOut += framesRead*pWav->channels;
50507  framesToRead -= framesRead;
50508  totalFramesRead += framesRead;
50509  }
50510  return totalFramesRead;
50511 }
50513 {
50514  drwav_uint64 totalFramesRead = 0;
50515  drwav_int16 samples16[2048];
50516  while (framesToRead > 0) {
50517  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
50518  if (framesRead == 0) {
50519  break;
50520  }
50521  drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
50522  pBufferOut += framesRead*pWav->channels;
50523  framesToRead -= framesRead;
50524  totalFramesRead += framesRead;
50525  }
50526  return totalFramesRead;
50527 }
50529 {
50530  drwav_uint64 totalFramesRead = 0;
50531  drwav_int16 samples16[2048];
50532  while (framesToRead > 0) {
50533  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
50534  if (framesRead == 0) {
50535  break;
50536  }
50537  drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
50538  pBufferOut += framesRead*pWav->channels;
50539  framesToRead -= framesRead;
50540  totalFramesRead += framesRead;
50541  }
50542  return totalFramesRead;
50543 }
50545 {
50546  drwav_uint64 totalFramesRead;
50547  drwav_uint8 sampleData[4096];
50548  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50549  if (bytesPerFrame == 0) {
50550  return 0;
50551  }
50552  totalFramesRead = 0;
50553  while (framesToRead > 0) {
50554  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50555  if (framesRead == 0) {
50556  break;
50557  }
50558  drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
50559  pBufferOut += framesRead*pWav->channels;
50560  framesToRead -= framesRead;
50561  totalFramesRead += framesRead;
50562  }
50563  return totalFramesRead;
50564 }
50566 {
50567  drwav_uint64 totalFramesRead;
50568  drwav_uint8 sampleData[4096];
50569  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50570  if (bytesPerFrame == 0) {
50571  return 0;
50572  }
50573  totalFramesRead = 0;
50574  while (framesToRead > 0) {
50575  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50576  if (framesRead == 0) {
50577  break;
50578  }
50579  drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
50580  pBufferOut += framesRead*pWav->channels;
50581  framesToRead -= framesRead;
50582  totalFramesRead += framesRead;
50583  }
50584  return totalFramesRead;
50585 }
50587 {
50588  drwav_uint64 totalFramesRead;
50589  drwav_uint8 sampleData[4096];
50590  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
50591  if (bytesPerFrame == 0) {
50592  return 0;
50593  }
50594  totalFramesRead = 0;
50595  while (framesToRead > 0) {
50596  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
50597  if (framesRead == 0) {
50598  break;
50599  }
50600  drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
50601  pBufferOut += framesRead*pWav->channels;
50602  framesToRead -= framesRead;
50603  totalFramesRead += framesRead;
50604  }
50605  return totalFramesRead;
50606 }
50608 {
50609  if (pWav == NULL || framesToRead == 0) {
50610  return 0;
50611  }
50612  if (pBufferOut == NULL) {
50613  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
50614  }
50615  if (framesToRead * pWav->channels * sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
50616  framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int32) / pWav->channels;
50617  }
50618  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
50619  return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
50620  }
50622  return drwav_read_pcm_frames_s32__msadpcm(pWav, framesToRead, pBufferOut);
50623  }
50625  return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
50626  }
50628  return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
50629  }
50631  return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
50632  }
50634  return drwav_read_pcm_frames_s32__ima(pWav, framesToRead, pBufferOut);
50635  }
50636  return 0;
50637 }
50639 {
50640  drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
50641  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
50642  drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
50643  }
50644  return framesRead;
50645 }
50647 {
50648  drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
50649  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
50650  drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
50651  }
50652  return framesRead;
50653 }
50654 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
50655 {
50656  size_t i;
50657  if (pOut == NULL || pIn == NULL) {
50658  return;
50659  }
50660  for (i = 0; i < sampleCount; ++i) {
50661  *pOut++ = ((int)pIn[i] - 128) << 24;
50662  }
50663 }
50664 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount)
50665 {
50666  size_t i;
50667  if (pOut == NULL || pIn == NULL) {
50668  return;
50669  }
50670  for (i = 0; i < sampleCount; ++i) {
50671  *pOut++ = pIn[i] << 16;
50672  }
50673 }
50674 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
50675 {
50676  size_t i;
50677  if (pOut == NULL || pIn == NULL) {
50678  return;
50679  }
50680  for (i = 0; i < sampleCount; ++i) {
50681  unsigned int s0 = pIn[i*3 + 0];
50682  unsigned int s1 = pIn[i*3 + 1];
50683  unsigned int s2 = pIn[i*3 + 2];
50684  drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
50685  *pOut++ = sample32;
50686  }
50687 }
50688 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
50689 {
50690  size_t i;
50691  if (pOut == NULL || pIn == NULL) {
50692  return;
50693  }
50694  for (i = 0; i < sampleCount; ++i) {
50695  *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
50696  }
50697 }
50698 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
50699 {
50700  size_t i;
50701  if (pOut == NULL || pIn == NULL) {
50702  return;
50703  }
50704  for (i = 0; i < sampleCount; ++i) {
50705  *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
50706  }
50707 }
50708 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
50709 {
50710  size_t i;
50711  if (pOut == NULL || pIn == NULL) {
50712  return;
50713  }
50714  for (i = 0; i < sampleCount; ++i) {
50715  *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
50716  }
50717 }
50718 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
50719 {
50720  size_t i;
50721  if (pOut == NULL || pIn == NULL) {
50722  return;
50723  }
50724  for (i= 0; i < sampleCount; ++i) {
50725  *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
50726  }
50727 }
50728 DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
50729 {
50730  drwav_uint64 sampleDataSize;
50731  drwav_int16* pSampleData;
50732  drwav_uint64 framesRead;
50733  DRWAV_ASSERT(pWav != NULL);
50734  sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
50735  if (sampleDataSize > DRWAV_SIZE_MAX) {
50736  drwav_uninit(pWav);
50737  return NULL;
50738  }
50739  pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
50740  if (pSampleData == NULL) {
50741  drwav_uninit(pWav);
50742  return NULL;
50743  }
50744  framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
50745  if (framesRead != pWav->totalPCMFrameCount) {
50746  drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
50747  drwav_uninit(pWav);
50748  return NULL;
50749  }
50750  drwav_uninit(pWav);
50751  if (sampleRate) {
50752  *sampleRate = pWav->sampleRate;
50753  }
50754  if (channels) {
50755  *channels = pWav->channels;
50756  }
50757  if (totalFrameCount) {
50758  *totalFrameCount = pWav->totalPCMFrameCount;
50759  }
50760  return pSampleData;
50761 }
50762 DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
50763 {
50764  drwav_uint64 sampleDataSize;
50765  float* pSampleData;
50766  drwav_uint64 framesRead;
50767  DRWAV_ASSERT(pWav != NULL);
50768  sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
50769  if (sampleDataSize > DRWAV_SIZE_MAX) {
50770  drwav_uninit(pWav);
50771  return NULL;
50772  }
50773  pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
50774  if (pSampleData == NULL) {
50775  drwav_uninit(pWav);
50776  return NULL;
50777  }
50778  framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
50779  if (framesRead != pWav->totalPCMFrameCount) {
50780  drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
50781  drwav_uninit(pWav);
50782  return NULL;
50783  }
50784  drwav_uninit(pWav);
50785  if (sampleRate) {
50786  *sampleRate = pWav->sampleRate;
50787  }
50788  if (channels) {
50789  *channels = pWav->channels;
50790  }
50791  if (totalFrameCount) {
50792  *totalFrameCount = pWav->totalPCMFrameCount;
50793  }
50794  return pSampleData;
50795 }
50796 DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
50797 {
50798  drwav_uint64 sampleDataSize;
50799  drwav_int32* pSampleData;
50800  drwav_uint64 framesRead;
50801  DRWAV_ASSERT(pWav != NULL);
50802  sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
50803  if (sampleDataSize > DRWAV_SIZE_MAX) {
50804  drwav_uninit(pWav);
50805  return NULL;
50806  }
50807  pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
50808  if (pSampleData == NULL) {
50809  drwav_uninit(pWav);
50810  return NULL;
50811  }
50812  framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
50813  if (framesRead != pWav->totalPCMFrameCount) {
50814  drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
50815  drwav_uninit(pWav);
50816  return NULL;
50817  }
50818  drwav_uninit(pWav);
50819  if (sampleRate) {
50820  *sampleRate = pWav->sampleRate;
50821  }
50822  if (channels) {
50823  *channels = pWav->channels;
50824  }
50825  if (totalFrameCount) {
50826  *totalFrameCount = pWav->totalPCMFrameCount;
50827  }
50828  return pSampleData;
50829 }
50830 DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50831 {
50832  drwav wav;
50833  if (channelsOut) {
50834  *channelsOut = 0;
50835  }
50836  if (sampleRateOut) {
50837  *sampleRateOut = 0;
50838  }
50839  if (totalFrameCountOut) {
50840  *totalFrameCountOut = 0;
50841  }
50842  if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
50843  return NULL;
50844  }
50845  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50846 }
50847 DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50848 {
50849  drwav wav;
50850  if (channelsOut) {
50851  *channelsOut = 0;
50852  }
50853  if (sampleRateOut) {
50854  *sampleRateOut = 0;
50855  }
50856  if (totalFrameCountOut) {
50857  *totalFrameCountOut = 0;
50858  }
50859  if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
50860  return NULL;
50861  }
50862  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50863 }
50864 DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50865 {
50866  drwav wav;
50867  if (channelsOut) {
50868  *channelsOut = 0;
50869  }
50870  if (sampleRateOut) {
50871  *sampleRateOut = 0;
50872  }
50873  if (totalFrameCountOut) {
50874  *totalFrameCountOut = 0;
50875  }
50876  if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
50877  return NULL;
50878  }
50879  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50880 }
50881 #ifndef DR_WAV_NO_STDIO
50882 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50883 {
50884  drwav wav;
50885  if (channelsOut) {
50886  *channelsOut = 0;
50887  }
50888  if (sampleRateOut) {
50889  *sampleRateOut = 0;
50890  }
50891  if (totalFrameCountOut) {
50892  *totalFrameCountOut = 0;
50893  }
50894  if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
50895  return NULL;
50896  }
50897  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50898 }
50899 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50900 {
50901  drwav wav;
50902  if (channelsOut) {
50903  *channelsOut = 0;
50904  }
50905  if (sampleRateOut) {
50906  *sampleRateOut = 0;
50907  }
50908  if (totalFrameCountOut) {
50909  *totalFrameCountOut = 0;
50910  }
50911  if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
50912  return NULL;
50913  }
50914  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50915 }
50916 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50917 {
50918  drwav wav;
50919  if (channelsOut) {
50920  *channelsOut = 0;
50921  }
50922  if (sampleRateOut) {
50923  *sampleRateOut = 0;
50924  }
50925  if (totalFrameCountOut) {
50926  *totalFrameCountOut = 0;
50927  }
50928  if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
50929  return NULL;
50930  }
50931  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50932 }
50933 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50934 {
50935  drwav wav;
50936  if (sampleRateOut) {
50937  *sampleRateOut = 0;
50938  }
50939  if (channelsOut) {
50940  *channelsOut = 0;
50941  }
50942  if (totalFrameCountOut) {
50943  *totalFrameCountOut = 0;
50944  }
50945  if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
50946  return NULL;
50947  }
50948  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50949 }
50950 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50951 {
50952  drwav wav;
50953  if (sampleRateOut) {
50954  *sampleRateOut = 0;
50955  }
50956  if (channelsOut) {
50957  *channelsOut = 0;
50958  }
50959  if (totalFrameCountOut) {
50960  *totalFrameCountOut = 0;
50961  }
50962  if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
50963  return NULL;
50964  }
50965  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50966 }
50967 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50968 {
50969  drwav wav;
50970  if (sampleRateOut) {
50971  *sampleRateOut = 0;
50972  }
50973  if (channelsOut) {
50974  *channelsOut = 0;
50975  }
50976  if (totalFrameCountOut) {
50977  *totalFrameCountOut = 0;
50978  }
50979  if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
50980  return NULL;
50981  }
50982  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
50983 }
50984 #endif
50985 DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
50986 {
50987  drwav wav;
50988  if (channelsOut) {
50989  *channelsOut = 0;
50990  }
50991  if (sampleRateOut) {
50992  *sampleRateOut = 0;
50993  }
50994  if (totalFrameCountOut) {
50995  *totalFrameCountOut = 0;
50996  }
50997  if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
50998  return NULL;
50999  }
51000  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
51001 }
51002 DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
51003 {
51004  drwav wav;
51005  if (channelsOut) {
51006  *channelsOut = 0;
51007  }
51008  if (sampleRateOut) {
51009  *sampleRateOut = 0;
51010  }
51011  if (totalFrameCountOut) {
51012  *totalFrameCountOut = 0;
51013  }
51014  if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
51015  return NULL;
51016  }
51017  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
51018 }
51019 DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
51020 {
51021  drwav wav;
51022  if (channelsOut) {
51023  *channelsOut = 0;
51024  }
51025  if (sampleRateOut) {
51026  *sampleRateOut = 0;
51027  }
51028  if (totalFrameCountOut) {
51029  *totalFrameCountOut = 0;
51030  }
51031  if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
51032  return NULL;
51033  }
51034  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
51035 }
51036 #endif
51037 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
51038 {
51039  if (pAllocationCallbacks != NULL) {
51040  drwav__free_from_callbacks(p, pAllocationCallbacks);
51041  } else {
51043  }
51044 }
51046 {
51047  return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
51048 }
51050 {
51051  return (drwav_int16)drwav_bytes_to_u16(data);
51052 }
51054 {
51055  return ((drwav_uint32)data[0] << 0) | ((drwav_uint32)data[1] << 8) | ((drwav_uint32)data[2] << 16) | ((drwav_uint32)data[3] << 24);
51056 }
51058 {
51059  union {
51060  drwav_uint32 u32;
51061  float f32;
51062  } value;
51063  value.u32 = drwav_bytes_to_u32(data);
51064  return value.f32;
51065 }
51067 {
51068  return (drwav_int32)drwav_bytes_to_u32(data);
51069 }
51071 {
51072  return
51073  ((drwav_uint64)data[0] << 0) | ((drwav_uint64)data[1] << 8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
51074  ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
51075 }
51077 {
51078  return (drwav_int64)drwav_bytes_to_u64(data);
51079 }
51081 {
51082  int i;
51083  for (i = 0; i < 16; i += 1) {
51084  if (a[i] != b[i]) {
51085  return DRWAV_FALSE;
51086  }
51087  }
51088  return DRWAV_TRUE;
51089 }
51091 {
51092  return
51093  a[0] == b[0] &&
51094  a[1] == b[1] &&
51095  a[2] == b[2] &&
51096  a[3] == b[3];
51097 }
51098 #endif
51099 /* dr_wav_c end */
51100 #endif /* DRWAV_IMPLEMENTATION */
51101 #endif /* MA_NO_WAV */
51102 
51103 #if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING)
51104 #if !defined(DR_FLAC_IMPLEMENTATION) && !defined(DRFLAC_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
51105 /* dr_flac_c begin */
51106 #ifndef dr_flac_c
51107 #define dr_flac_c
51108 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
51109  #pragma GCC diagnostic push
51110  #if __GNUC__ >= 7
51111  #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
51112  #endif
51113 #endif
51114 #ifdef __linux__
51115  #ifndef _BSD_SOURCE
51116  #define _BSD_SOURCE
51117  #endif
51118  #ifndef _DEFAULT_SOURCE
51119  #define _DEFAULT_SOURCE
51120  #endif
51121  #ifndef __USE_BSD
51122  #define __USE_BSD
51123  #endif
51124  #include <endian.h>
51125 #endif
51126 #include <stdlib.h>
51127 #include <string.h>
51128 #ifdef _MSC_VER
51129  #define DRFLAC_INLINE __forceinline
51130 #elif defined(__GNUC__)
51131  #if defined(__STRICT_ANSI__)
51132  #define DRFLAC_INLINE __inline__ __attribute__((always_inline))
51133  #else
51134  #define DRFLAC_INLINE inline __attribute__((always_inline))
51135  #endif
51136 #elif defined(__WATCOMC__)
51137  #define DRFLAC_INLINE __inline
51138 #else
51139  #define DRFLAC_INLINE
51140 #endif
51141 #if defined(__x86_64__) || defined(_M_X64)
51142  #define DRFLAC_X64
51143 #elif defined(__i386) || defined(_M_IX86)
51144  #define DRFLAC_X86
51145 #elif defined(__arm__) || defined(_M_ARM) || defined(_M_ARM64)
51146  #define DRFLAC_ARM
51147 #endif
51148 #if !defined(DR_FLAC_NO_SIMD)
51149  #if defined(DRFLAC_X64) || defined(DRFLAC_X86)
51150  #if defined(_MSC_VER) && !defined(__clang__)
51151  #if _MSC_VER >= 1400 && !defined(DRFLAC_NO_SSE2)
51152  #define DRFLAC_SUPPORT_SSE2
51153  #endif
51154  #if _MSC_VER >= 1600 && !defined(DRFLAC_NO_SSE41)
51155  #define DRFLAC_SUPPORT_SSE41
51156  #endif
51157  #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
51158  #if defined(__SSE2__) && !defined(DRFLAC_NO_SSE2)
51159  #define DRFLAC_SUPPORT_SSE2
51160  #endif
51161  #if defined(__SSE4_1__) && !defined(DRFLAC_NO_SSE41)
51162  #define DRFLAC_SUPPORT_SSE41
51163  #endif
51164  #endif
51165  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
51166  #if !defined(DRFLAC_SUPPORT_SSE2) && !defined(DRFLAC_NO_SSE2) && __has_include(<emmintrin.h>)
51167  #define DRFLAC_SUPPORT_SSE2
51168  #endif
51169  #if !defined(DRFLAC_SUPPORT_SSE41) && !defined(DRFLAC_NO_SSE41) && __has_include(<smmintrin.h>)
51170  #define DRFLAC_SUPPORT_SSE41
51171  #endif
51172  #endif
51173  #if defined(DRFLAC_SUPPORT_SSE41)
51174  #include <smmintrin.h>
51175  #elif defined(DRFLAC_SUPPORT_SSE2)
51176  #include <emmintrin.h>
51177  #endif
51178  #endif
51179  #if defined(DRFLAC_ARM)
51180  #if !defined(DRFLAC_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
51181  #define DRFLAC_SUPPORT_NEON
51182  #endif
51183  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
51184  #if !defined(DRFLAC_SUPPORT_NEON) && !defined(DRFLAC_NO_NEON) && __has_include(<arm_neon.h>)
51185  #define DRFLAC_SUPPORT_NEON
51186  #endif
51187  #endif
51188  #if defined(DRFLAC_SUPPORT_NEON)
51189  #include <arm_neon.h>
51190  #endif
51191  #endif
51192 #endif
51193 #if !defined(DR_FLAC_NO_SIMD) && (defined(DRFLAC_X86) || defined(DRFLAC_X64))
51194  #if defined(_MSC_VER) && !defined(__clang__)
51195  #if _MSC_VER >= 1400
51196  #include <intrin.h>
51197  static void drflac__cpuid(int info[4], int fid)
51198  {
51199  __cpuid(info, fid);
51200  }
51201  #else
51202  #define DRFLAC_NO_CPUID
51203  #endif
51204  #else
51205  #if defined(__GNUC__) || defined(__clang__)
51206  static void drflac__cpuid(int info[4], int fid)
51207  {
51208  #if defined(DRFLAC_X86) && defined(__PIC__)
51209  __asm__ __volatile__ (
51210  "xchg{l} {%%}ebx, %k1;"
51211  "cpuid;"
51212  "xchg{l} {%%}ebx, %k1;"
51213  : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
51214  );
51215  #else
51216  __asm__ __volatile__ (
51217  "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
51218  );
51219  #endif
51220  }
51221  #else
51222  #define DRFLAC_NO_CPUID
51223  #endif
51224  #endif
51225 #else
51226  #define DRFLAC_NO_CPUID
51227 #endif
51229 {
51230 #if defined(DRFLAC_SUPPORT_SSE2)
51231  #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE2)
51232  #if defined(DRFLAC_X64)
51233  return DRFLAC_TRUE;
51234  #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
51235  return DRFLAC_TRUE;
51236  #else
51237  #if defined(DRFLAC_NO_CPUID)
51238  return DRFLAC_FALSE;
51239  #else
51240  int info[4];
51241  drflac__cpuid(info, 1);
51242  return (info[3] & (1 << 26)) != 0;
51243  #endif
51244  #endif
51245  #else
51246  return DRFLAC_FALSE;
51247  #endif
51248 #else
51249  return DRFLAC_FALSE;
51250 #endif
51251 }
51253 {
51254 #if defined(DRFLAC_SUPPORT_SSE41)
51255  #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE41)
51256  #if defined(DRFLAC_X64)
51257  return DRFLAC_TRUE;
51258  #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE4_1__)
51259  return DRFLAC_TRUE;
51260  #else
51261  #if defined(DRFLAC_NO_CPUID)
51262  return DRFLAC_FALSE;
51263  #else
51264  int info[4];
51265  drflac__cpuid(info, 1);
51266  return (info[2] & (1 << 19)) != 0;
51267  #endif
51268  #endif
51269  #else
51270  return DRFLAC_FALSE;
51271  #endif
51272 #else
51273  return DRFLAC_FALSE;
51274 #endif
51275 }
51276 #if defined(_MSC_VER) && _MSC_VER >= 1500 && (defined(DRFLAC_X86) || defined(DRFLAC_X64)) && !defined(__clang__)
51277  #define DRFLAC_HAS_LZCNT_INTRINSIC
51278 #elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
51279  #define DRFLAC_HAS_LZCNT_INTRINSIC
51280 #elif defined(__clang__)
51281  #if defined(__has_builtin)
51282  #if __has_builtin(__builtin_clzll) || __has_builtin(__builtin_clzl)
51283  #define DRFLAC_HAS_LZCNT_INTRINSIC
51284  #endif
51285  #endif
51286 #endif
51287 #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(__clang__)
51288  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
51289  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
51290  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
51291 #elif defined(__clang__)
51292  #if defined(__has_builtin)
51293  #if __has_builtin(__builtin_bswap16)
51294  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
51295  #endif
51296  #if __has_builtin(__builtin_bswap32)
51297  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
51298  #endif
51299  #if __has_builtin(__builtin_bswap64)
51300  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
51301  #endif
51302  #endif
51303 #elif defined(__GNUC__)
51304  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
51305  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
51306  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
51307  #endif
51308  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
51309  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
51310  #endif
51311 #elif defined(__WATCOMC__) && defined(__386__)
51312  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
51313  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
51314  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
51315  extern __inline drflac_uint16 _watcom_bswap16(drflac_uint16);
51316  extern __inline drflac_uint32 _watcom_bswap32(drflac_uint32);
51317  extern __inline drflac_uint64 _watcom_bswap64(drflac_uint64);
51318 #pragma aux _watcom_bswap16 = \
51319  "xchg al, ah" \
51320  parm [ax] \
51321  modify [ax];
51322 #pragma aux _watcom_bswap32 = \
51323  "bswap eax" \
51324  parm [eax] \
51325  modify [eax];
51326 #pragma aux _watcom_bswap64 = \
51327  "bswap eax" \
51328  "bswap edx" \
51329  "xchg eax,edx" \
51330  parm [eax edx] \
51331  modify [eax edx];
51332 #endif
51333 #ifndef DRFLAC_ASSERT
51334 #include <assert.h>
51335 #define DRFLAC_ASSERT(expression) assert(expression)
51336 #endif
51337 #ifndef DRFLAC_MALLOC
51338 #define DRFLAC_MALLOC(sz) malloc((sz))
51339 #endif
51340 #ifndef DRFLAC_REALLOC
51341 #define DRFLAC_REALLOC(p, sz) realloc((p), (sz))
51342 #endif
51343 #ifndef DRFLAC_FREE
51344 #define DRFLAC_FREE(p) free((p))
51345 #endif
51346 #ifndef DRFLAC_COPY_MEMORY
51347 #define DRFLAC_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
51348 #endif
51349 #ifndef DRFLAC_ZERO_MEMORY
51350 #define DRFLAC_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
51351 #endif
51352 #ifndef DRFLAC_ZERO_OBJECT
51353 #define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
51354 #endif
51355 #define DRFLAC_MAX_SIMD_VECTOR_SIZE 64
51357 #define DRFLAC_SUCCESS 0
51358 #define DRFLAC_ERROR -1
51359 #define DRFLAC_INVALID_ARGS -2
51360 #define DRFLAC_INVALID_OPERATION -3
51361 #define DRFLAC_OUT_OF_MEMORY -4
51362 #define DRFLAC_OUT_OF_RANGE -5
51363 #define DRFLAC_ACCESS_DENIED -6
51364 #define DRFLAC_DOES_NOT_EXIST -7
51365 #define DRFLAC_ALREADY_EXISTS -8
51366 #define DRFLAC_TOO_MANY_OPEN_FILES -9
51367 #define DRFLAC_INVALID_FILE -10
51368 #define DRFLAC_TOO_BIG -11
51369 #define DRFLAC_PATH_TOO_LONG -12
51370 #define DRFLAC_NAME_TOO_LONG -13
51371 #define DRFLAC_NOT_DIRECTORY -14
51372 #define DRFLAC_IS_DIRECTORY -15
51373 #define DRFLAC_DIRECTORY_NOT_EMPTY -16
51374 #define DRFLAC_END_OF_FILE -17
51375 #define DRFLAC_NO_SPACE -18
51376 #define DRFLAC_BUSY -19
51377 #define DRFLAC_IO_ERROR -20
51378 #define DRFLAC_INTERRUPT -21
51379 #define DRFLAC_UNAVAILABLE -22
51380 #define DRFLAC_ALREADY_IN_USE -23
51381 #define DRFLAC_BAD_ADDRESS -24
51382 #define DRFLAC_BAD_SEEK -25
51383 #define DRFLAC_BAD_PIPE -26
51384 #define DRFLAC_DEADLOCK -27
51385 #define DRFLAC_TOO_MANY_LINKS -28
51386 #define DRFLAC_NOT_IMPLEMENTED -29
51387 #define DRFLAC_NO_MESSAGE -30
51388 #define DRFLAC_BAD_MESSAGE -31
51389 #define DRFLAC_NO_DATA_AVAILABLE -32
51390 #define DRFLAC_INVALID_DATA -33
51391 #define DRFLAC_TIMEOUT -34
51392 #define DRFLAC_NO_NETWORK -35
51393 #define DRFLAC_NOT_UNIQUE -36
51394 #define DRFLAC_NOT_SOCKET -37
51395 #define DRFLAC_NO_ADDRESS -38
51396 #define DRFLAC_BAD_PROTOCOL -39
51397 #define DRFLAC_PROTOCOL_UNAVAILABLE -40
51398 #define DRFLAC_PROTOCOL_NOT_SUPPORTED -41
51399 #define DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED -42
51400 #define DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED -43
51401 #define DRFLAC_SOCKET_NOT_SUPPORTED -44
51402 #define DRFLAC_CONNECTION_RESET -45
51403 #define DRFLAC_ALREADY_CONNECTED -46
51404 #define DRFLAC_NOT_CONNECTED -47
51405 #define DRFLAC_CONNECTION_REFUSED -48
51406 #define DRFLAC_NO_HOST -49
51407 #define DRFLAC_IN_PROGRESS -50
51408 #define DRFLAC_CANCELLED -51
51409 #define DRFLAC_MEMORY_ALREADY_MAPPED -52
51410 #define DRFLAC_AT_END -53
51411 #define DRFLAC_CRC_MISMATCH -128
51412 #define DRFLAC_SUBFRAME_CONSTANT 0
51413 #define DRFLAC_SUBFRAME_VERBATIM 1
51414 #define DRFLAC_SUBFRAME_FIXED 8
51415 #define DRFLAC_SUBFRAME_LPC 32
51416 #define DRFLAC_SUBFRAME_RESERVED 255
51417 #define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE 0
51418 #define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 1
51419 #define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT 0
51420 #define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE 8
51421 #define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9
51422 #define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10
51423 #define drflac_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
51425 {
51426  if (pMajor) {
51427  *pMajor = DRFLAC_VERSION_MAJOR;
51428  }
51429  if (pMinor) {
51430  *pMinor = DRFLAC_VERSION_MINOR;
51431  }
51432  if (pRevision) {
51433  *pRevision = DRFLAC_VERSION_REVISION;
51434  }
51435 }
51437 {
51438  return DRFLAC_VERSION_STRING;
51439 }
51440 #if defined(__has_feature)
51441  #if __has_feature(thread_sanitizer)
51442  #define DRFLAC_NO_THREAD_SANITIZE __attribute__((no_sanitize("thread")))
51443  #else
51444  #define DRFLAC_NO_THREAD_SANITIZE
51445  #endif
51446 #else
51447  #define DRFLAC_NO_THREAD_SANITIZE
51448 #endif
51449 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
51450 static drflac_bool32 drflac__gIsLZCNTSupported = DRFLAC_FALSE;
51451 #endif
51452 #ifndef DRFLAC_NO_CPUID
51453 static drflac_bool32 drflac__gIsSSE2Supported = DRFLAC_FALSE;
51454 static drflac_bool32 drflac__gIsSSE41Supported = DRFLAC_FALSE;
51456 {
51457  static drflac_bool32 isCPUCapsInitialized = DRFLAC_FALSE;
51458  if (!isCPUCapsInitialized) {
51459 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
51460  int info[4] = {0};
51461  drflac__cpuid(info, 0x80000001);
51462  drflac__gIsLZCNTSupported = (info[2] & (1 << 5)) != 0;
51463 #endif
51464  drflac__gIsSSE2Supported = drflac_has_sse2();
51465  drflac__gIsSSE41Supported = drflac_has_sse41();
51466  isCPUCapsInitialized = DRFLAC_TRUE;
51467  }
51468 }
51469 #else
51472 {
51473 #if defined(DRFLAC_SUPPORT_NEON)
51474  #if defined(DRFLAC_ARM) && !defined(DRFLAC_NO_NEON)
51475  #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
51476  return DRFLAC_TRUE;
51477  #else
51478  return DRFLAC_FALSE;
51479  #endif
51480  #else
51481  return DRFLAC_FALSE;
51482  #endif
51483 #else
51484  return DRFLAC_FALSE;
51485 #endif
51486 }
51488 {
51490 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
51491  drflac__gIsLZCNTSupported = DRFLAC_TRUE;
51492 #endif
51493 }
51494 #endif
51496 {
51497 #if defined(DRFLAC_X86) || defined(DRFLAC_X64)
51498  return DRFLAC_TRUE;
51499 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
51500  return DRFLAC_TRUE;
51501 #else
51502  int n = 1;
51503  return (*(char*)&n) == 1;
51504 #endif
51505 }
51507 {
51508 #ifdef DRFLAC_HAS_BYTESWAP16_INTRINSIC
51509  #if defined(_MSC_VER) && !defined(__clang__)
51510  return _byteswap_ushort(n);
51511  #elif defined(__GNUC__) || defined(__clang__)
51512  return __builtin_bswap16(n);
51513  #elif defined(__WATCOMC__) && defined(__386__)
51514  return _watcom_bswap16(n);
51515  #else
51516  #error "This compiler does not support the byte swap intrinsic."
51517  #endif
51518 #else
51519  return ((n & 0xFF00) >> 8) |
51520  ((n & 0x00FF) << 8);
51521 #endif
51522 }
51524 {
51525 #ifdef DRFLAC_HAS_BYTESWAP32_INTRINSIC
51526  #if defined(_MSC_VER) && !defined(__clang__)
51527  return _byteswap_ulong(n);
51528  #elif defined(__GNUC__) || defined(__clang__)
51529  #if defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRFLAC_64BIT)
51530  drflac_uint32 r;
51531  __asm__ __volatile__ (
51532  #if defined(DRFLAC_64BIT)
51533  "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n)
51534  #else
51535  "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
51536  #endif
51537  );
51538  return r;
51539  #else
51540  return __builtin_bswap32(n);
51541  #endif
51542  #elif defined(__WATCOMC__) && defined(__386__)
51543  return _watcom_bswap32(n);
51544  #else
51545  #error "This compiler does not support the byte swap intrinsic."
51546  #endif
51547 #else
51548  return ((n & 0xFF000000) >> 24) |
51549  ((n & 0x00FF0000) >> 8) |
51550  ((n & 0x0000FF00) << 8) |
51551  ((n & 0x000000FF) << 24);
51552 #endif
51553 }
51555 {
51556 #ifdef DRFLAC_HAS_BYTESWAP64_INTRINSIC
51557  #if defined(_MSC_VER) && !defined(__clang__)
51558  return _byteswap_uint64(n);
51559  #elif defined(__GNUC__) || defined(__clang__)
51560  return __builtin_bswap64(n);
51561  #elif defined(__WATCOMC__) && defined(__386__)
51562  return _watcom_bswap64(n);
51563  #else
51564  #error "This compiler does not support the byte swap intrinsic."
51565  #endif
51566 #else
51567  return ((n & ((drflac_uint64)0xFF000000 << 32)) >> 56) |
51568  ((n & ((drflac_uint64)0x00FF0000 << 32)) >> 40) |
51569  ((n & ((drflac_uint64)0x0000FF00 << 32)) >> 24) |
51570  ((n & ((drflac_uint64)0x000000FF << 32)) >> 8) |
51571  ((n & ((drflac_uint64)0xFF000000 )) << 8) |
51572  ((n & ((drflac_uint64)0x00FF0000 )) << 24) |
51573  ((n & ((drflac_uint64)0x0000FF00 )) << 40) |
51574  ((n & ((drflac_uint64)0x000000FF )) << 56);
51575 #endif
51576 }
51578 {
51579  if (drflac__is_little_endian()) {
51580  return drflac__swap_endian_uint16(n);
51581  }
51582  return n;
51583 }
51585 {
51586  if (drflac__is_little_endian()) {
51587  return drflac__swap_endian_uint32(n);
51588  }
51589  return n;
51590 }
51592 {
51593  if (drflac__is_little_endian()) {
51594  return drflac__swap_endian_uint64(n);
51595  }
51596  return n;
51597 }
51599 {
51600  if (!drflac__is_little_endian()) {
51601  return drflac__swap_endian_uint32(n);
51602  }
51603  return n;
51604 }
51606 {
51607  drflac_uint32 result = 0;
51608  result |= (n & 0x7F000000) >> 3;
51609  result |= (n & 0x007F0000) >> 2;
51610  result |= (n & 0x00007F00) >> 1;
51611  result |= (n & 0x0000007F) >> 0;
51612  return result;
51613 }
51615  0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
51616  0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
51617  0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
51618  0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
51619  0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
51620  0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
51621  0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
51622  0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
51623  0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
51624  0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
51625  0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
51626  0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
51627  0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
51628  0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
51629  0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
51630  0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
51631 };
51633  0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
51634  0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
51635  0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
51636  0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
51637  0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
51638  0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
51639  0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
51640  0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
51641  0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
51642  0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
51643  0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
51644  0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
51645  0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
51646  0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
51647  0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
51648  0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
51649  0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
51650  0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
51651  0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
51652  0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
51653  0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
51654  0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
51655  0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
51656  0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
51657  0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
51658  0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
51659  0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
51660  0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
51661  0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
51662  0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
51663  0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
51664  0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
51665 };
51667 {
51668  return drflac__crc8_table[crc ^ data];
51669 }
51671 {
51672 #ifdef DR_FLAC_NO_CRC
51673  (void)crc;
51674  (void)data;
51675  (void)count;
51676  return 0;
51677 #else
51678 #if 0
51679  drflac_uint8 p = 0x07;
51680  for (int i = count-1; i >= 0; --i) {
51681  drflac_uint8 bit = (data & (1 << i)) >> i;
51682  if (crc & 0x80) {
51683  crc = ((crc << 1) | bit) ^ p;
51684  } else {
51685  crc = ((crc << 1) | bit);
51686  }
51687  }
51688  return crc;
51689 #else
51690  drflac_uint32 wholeBytes;
51691  drflac_uint32 leftoverBits;
51692  drflac_uint64 leftoverDataMask;
51693  static drflac_uint64 leftoverDataMaskTable[8] = {
51694  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
51695  };
51696  DRFLAC_ASSERT(count <= 32);
51697  wholeBytes = count >> 3;
51698  leftoverBits = count - (wholeBytes*8);
51699  leftoverDataMask = leftoverDataMaskTable[leftoverBits];
51700  switch (wholeBytes) {
51701  case 4: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits)));
51702  case 3: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits)));
51703  case 2: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits)));
51704  case 1: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits)));
51705  case 0: if (leftoverBits > 0) crc = (drflac_uint8)((crc << leftoverBits) ^ drflac__crc8_table[(crc >> (8 - leftoverBits)) ^ (data & leftoverDataMask)]);
51706  }
51707  return crc;
51708 #endif
51709 #endif
51710 }
51712 {
51713  return (crc << 8) ^ drflac__crc16_table[(drflac_uint8)(crc >> 8) ^ data];
51714 }
51716 {
51717 #ifdef DRFLAC_64BIT
51718  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF));
51719  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF));
51720  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF));
51721  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF));
51722 #endif
51723  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF));
51724  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF));
51725  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF));
51726  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF));
51727  return crc;
51728 }
51730 {
51731  switch (byteCount)
51732  {
51733 #ifdef DRFLAC_64BIT
51734  case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF));
51735  case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF));
51736  case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF));
51737  case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF));
51738 #endif
51739  case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF));
51740  case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF));
51741  case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF));
51742  case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF));
51743  }
51744  return crc;
51745 }
51746 #if 0
51747 static DRFLAC_INLINE drflac_uint16 drflac_crc16__32bit(drflac_uint16 crc, drflac_uint32 data, drflac_uint32 count)
51748 {
51749 #ifdef DR_FLAC_NO_CRC
51750  (void)crc;
51751  (void)data;
51752  (void)count;
51753  return 0;
51754 #else
51755 #if 0
51756  drflac_uint16 p = 0x8005;
51757  for (int i = count-1; i >= 0; --i) {
51758  drflac_uint16 bit = (data & (1ULL << i)) >> i;
51759  if (r & 0x8000) {
51760  r = ((r << 1) | bit) ^ p;
51761  } else {
51762  r = ((r << 1) | bit);
51763  }
51764  }
51765  return crc;
51766 #else
51767  drflac_uint32 wholeBytes;
51768  drflac_uint32 leftoverBits;
51769  drflac_uint64 leftoverDataMask;
51770  static drflac_uint64 leftoverDataMaskTable[8] = {
51771  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
51772  };
51773  DRFLAC_ASSERT(count <= 64);
51774  wholeBytes = count >> 3;
51775  leftoverBits = count & 7;
51776  leftoverDataMask = leftoverDataMaskTable[leftoverBits];
51777  switch (wholeBytes) {
51778  default:
51779  case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits)));
51780  case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits)));
51781  case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits)));
51782  case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits)));
51783  case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)];
51784  }
51785  return crc;
51786 #endif
51787 #endif
51788 }
51789 static DRFLAC_INLINE drflac_uint16 drflac_crc16__64bit(drflac_uint16 crc, drflac_uint64 data, drflac_uint32 count)
51790 {
51791 #ifdef DR_FLAC_NO_CRC
51792  (void)crc;
51793  (void)data;
51794  (void)count;
51795  return 0;
51796 #else
51797  drflac_uint32 wholeBytes;
51798  drflac_uint32 leftoverBits;
51799  drflac_uint64 leftoverDataMask;
51800  static drflac_uint64 leftoverDataMaskTable[8] = {
51801  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
51802  };
51803  DRFLAC_ASSERT(count <= 64);
51804  wholeBytes = count >> 3;
51805  leftoverBits = count & 7;
51806  leftoverDataMask = leftoverDataMaskTable[leftoverBits];
51807  switch (wholeBytes) {
51808  default:
51809  case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0xFF000000 << 32) << leftoverBits)) >> (56 + leftoverBits)));
51810  case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x00FF0000 << 32) << leftoverBits)) >> (48 + leftoverBits)));
51811  case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x0000FF00 << 32) << leftoverBits)) >> (40 + leftoverBits)));
51812  case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x000000FF << 32) << leftoverBits)) >> (32 + leftoverBits)));
51813  case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0xFF000000 ) << leftoverBits)) >> (24 + leftoverBits)));
51814  case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x00FF0000 ) << leftoverBits)) >> (16 + leftoverBits)));
51815  case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x0000FF00 ) << leftoverBits)) >> ( 8 + leftoverBits)));
51816  case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x000000FF ) << leftoverBits)) >> ( 0 + leftoverBits)));
51817  case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)];
51818  }
51819  return crc;
51820 #endif
51821 }
51823 {
51824 #ifdef DRFLAC_64BIT
51825  return drflac_crc16__64bit(crc, data, count);
51826 #else
51827  return drflac_crc16__32bit(crc, data, count);
51828 #endif
51829 }
51830 #endif
51831 #ifdef DRFLAC_64BIT
51832 #define drflac__be2host__cache_line drflac__be2host_64
51833 #else
51834 #define drflac__be2host__cache_line drflac__be2host_32
51835 #endif
51836 #define DRFLAC_CACHE_L1_SIZE_BYTES(bs) (sizeof((bs)->cache))
51837 #define DRFLAC_CACHE_L1_SIZE_BITS(bs) (sizeof((bs)->cache)*8)
51838 #define DRFLAC_CACHE_L1_BITS_REMAINING(bs) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (bs)->consumedBits)
51839 #define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~((~(drflac_cache_t)0) >> (_bitCount)))
51840 #define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (_bitCount))
51841 #define DRFLAC_CACHE_L1_SELECT(bs, _bitCount) (((bs)->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount))
51842 #define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)))
51843 #define DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, _bitCount)(DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> (DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)) & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1)))
51844 #define DRFLAC_CACHE_L2_SIZE_BYTES(bs) (sizeof((bs)->cacheL2))
51845 #define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0]))
51846 #define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line)
51847 #ifndef DR_FLAC_NO_CRC
51849 {
51850  bs->crc16 = 0;
51851  bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
51852 }
51854 {
51855  if (bs->crc16CacheIgnoredBytes == 0) {
51856  bs->crc16 = drflac_crc16_cache(bs->crc16, bs->crc16Cache);
51857  } else {
51859  bs->crc16CacheIgnoredBytes = 0;
51860  }
51861 }
51863 {
51865  if (DRFLAC_CACHE_L1_BITS_REMAINING(bs) == 0) {
51867  } else {
51869  bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
51870  }
51871  return bs->crc16;
51872 }
51873 #endif
51875 {
51876  size_t bytesRead;
51877  size_t alignedL1LineCount;
51878  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
51879  bs->cache = bs->cacheL2[bs->nextL2Line++];
51880  return DRFLAC_TRUE;
51881  }
51882  if (bs->unalignedByteCount > 0) {
51883  return DRFLAC_FALSE;
51884  }
51885  bytesRead = bs->onRead(bs->pUserData, bs->cacheL2, DRFLAC_CACHE_L2_SIZE_BYTES(bs));
51886  bs->nextL2Line = 0;
51887  if (bytesRead == DRFLAC_CACHE_L2_SIZE_BYTES(bs)) {
51888  bs->cache = bs->cacheL2[bs->nextL2Line++];
51889  return DRFLAC_TRUE;
51890  }
51891  alignedL1LineCount = bytesRead / DRFLAC_CACHE_L1_SIZE_BYTES(bs);
51892  bs->unalignedByteCount = bytesRead - (alignedL1LineCount * DRFLAC_CACHE_L1_SIZE_BYTES(bs));
51893  if (bs->unalignedByteCount > 0) {
51894  bs->unalignedCache = bs->cacheL2[alignedL1LineCount];
51895  }
51896  if (alignedL1LineCount > 0) {
51897  size_t offset = DRFLAC_CACHE_L2_LINE_COUNT(bs) - alignedL1LineCount;
51898  size_t i;
51899  for (i = alignedL1LineCount; i > 0; --i) {
51900  bs->cacheL2[i-1 + offset] = bs->cacheL2[i-1];
51901  }
51902  bs->nextL2Line = (drflac_uint32)offset;
51903  bs->cache = bs->cacheL2[bs->nextL2Line++];
51904  return DRFLAC_TRUE;
51905  } else {
51907  return DRFLAC_FALSE;
51908  }
51909 }
51911 {
51912  size_t bytesRead;
51913 #ifndef DR_FLAC_NO_CRC
51915 #endif
51918  bs->consumedBits = 0;
51919 #ifndef DR_FLAC_NO_CRC
51920  bs->crc16Cache = bs->cache;
51921 #endif
51922  return DRFLAC_TRUE;
51923  }
51924  bytesRead = bs->unalignedByteCount;
51925  if (bytesRead == 0) {
51927  return DRFLAC_FALSE;
51928  }
51929  DRFLAC_ASSERT(bytesRead < DRFLAC_CACHE_L1_SIZE_BYTES(bs));
51930  bs->consumedBits = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bytesRead) * 8;
51933  bs->unalignedByteCount = 0;
51934 #ifndef DR_FLAC_NO_CRC
51935  bs->crc16Cache = bs->cache >> bs->consumedBits;
51936  bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
51937 #endif
51938  return DRFLAC_TRUE;
51939 }
51941 {
51944  bs->cache = 0;
51945  bs->unalignedByteCount = 0;
51946  bs->unalignedCache = 0;
51947 #ifndef DR_FLAC_NO_CRC
51948  bs->crc16Cache = 0;
51949  bs->crc16CacheIgnoredBytes = 0;
51950 #endif
51951 }
51952 static DRFLAC_INLINE drflac_bool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, drflac_uint32* pResultOut)
51953 {
51954  DRFLAC_ASSERT(bs != NULL);
51955  DRFLAC_ASSERT(pResultOut != NULL);
51956  DRFLAC_ASSERT(bitCount > 0);
51957  DRFLAC_ASSERT(bitCount <= 32);
51958  if (bs->consumedBits == DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
51959  if (!drflac__reload_cache(bs)) {
51960  return DRFLAC_FALSE;
51961  }
51962  }
51963  if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
51964 #ifdef DRFLAC_64BIT
51965  *pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
51966  bs->consumedBits += bitCount;
51967  bs->cache <<= bitCount;
51968 #else
51969  if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
51970  *pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
51971  bs->consumedBits += bitCount;
51972  bs->cache <<= bitCount;
51973  } else {
51974  *pResultOut = (drflac_uint32)bs->cache;
51976  bs->cache = 0;
51977  }
51978 #endif
51979  return DRFLAC_TRUE;
51980  } else {
51982  drflac_uint32 bitCountLo = bitCount - bitCountHi;
51983  drflac_uint32 resultHi;
51984  DRFLAC_ASSERT(bitCountHi > 0);
51985  DRFLAC_ASSERT(bitCountHi < 32);
51986  resultHi = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountHi);
51987  if (!drflac__reload_cache(bs)) {
51988  return DRFLAC_FALSE;
51989  }
51990  *pResultOut = (resultHi << bitCountLo) | (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo);
51991  bs->consumedBits += bitCountLo;
51992  bs->cache <<= bitCountLo;
51993  return DRFLAC_TRUE;
51994  }
51995 }
51996 static drflac_bool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, drflac_int32* pResult)
51997 {
51998  drflac_uint32 result;
51999  DRFLAC_ASSERT(bs != NULL);
52000  DRFLAC_ASSERT(pResult != NULL);
52001  DRFLAC_ASSERT(bitCount > 0);
52002  DRFLAC_ASSERT(bitCount <= 32);
52003  if (!drflac__read_uint32(bs, bitCount, &result)) {
52004  return DRFLAC_FALSE;
52005  }
52006  if (bitCount < 32) {
52007  drflac_uint32 signbit;
52008  signbit = ((result >> (bitCount-1)) & 0x01);
52009  result |= (~signbit + 1) << bitCount;
52010  }
52011  *pResult = (drflac_int32)result;
52012  return DRFLAC_TRUE;
52013 }
52014 #ifdef DRFLAC_64BIT
52015 static drflac_bool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, drflac_uint64* pResultOut)
52016 {
52017  drflac_uint32 resultHi;
52018  drflac_uint32 resultLo;
52019  DRFLAC_ASSERT(bitCount <= 64);
52020  DRFLAC_ASSERT(bitCount > 32);
52021  if (!drflac__read_uint32(bs, bitCount - 32, &resultHi)) {
52022  return DRFLAC_FALSE;
52023  }
52024  if (!drflac__read_uint32(bs, 32, &resultLo)) {
52025  return DRFLAC_FALSE;
52026  }
52027  *pResultOut = (((drflac_uint64)resultHi) << 32) | ((drflac_uint64)resultLo);
52028  return DRFLAC_TRUE;
52029 }
52030 #endif
52031 #if 0
52032 static drflac_bool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, drflac_int64* pResultOut)
52033 {
52034  drflac_uint64 result;
52035  drflac_uint64 signbit;
52036  DRFLAC_ASSERT(bitCount <= 64);
52037  if (!drflac__read_uint64(bs, bitCount, &result)) {
52038  return DRFLAC_FALSE;
52039  }
52040  signbit = ((result >> (bitCount-1)) & 0x01);
52041  result |= (~signbit + 1) << bitCount;
52042  *pResultOut = (drflac_int64)result;
52043  return DRFLAC_TRUE;
52044 }
52045 #endif
52046 static drflac_bool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, drflac_uint16* pResult)
52047 {
52048  drflac_uint32 result;
52049  DRFLAC_ASSERT(bs != NULL);
52050  DRFLAC_ASSERT(pResult != NULL);
52051  DRFLAC_ASSERT(bitCount > 0);
52052  DRFLAC_ASSERT(bitCount <= 16);
52053  if (!drflac__read_uint32(bs, bitCount, &result)) {
52054  return DRFLAC_FALSE;
52055  }
52056  *pResult = (drflac_uint16)result;
52057  return DRFLAC_TRUE;
52058 }
52059 #if 0
52060 static drflac_bool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, drflac_int16* pResult)
52061 {
52062  drflac_int32 result;
52063  DRFLAC_ASSERT(bs != NULL);
52064  DRFLAC_ASSERT(pResult != NULL);
52065  DRFLAC_ASSERT(bitCount > 0);
52066  DRFLAC_ASSERT(bitCount <= 16);
52067  if (!drflac__read_int32(bs, bitCount, &result)) {
52068  return DRFLAC_FALSE;
52069  }
52070  *pResult = (drflac_int16)result;
52071  return DRFLAC_TRUE;
52072 }
52073 #endif
52074 static drflac_bool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, drflac_uint8* pResult)
52075 {
52076  drflac_uint32 result;
52077  DRFLAC_ASSERT(bs != NULL);
52078  DRFLAC_ASSERT(pResult != NULL);
52079  DRFLAC_ASSERT(bitCount > 0);
52080  DRFLAC_ASSERT(bitCount <= 8);
52081  if (!drflac__read_uint32(bs, bitCount, &result)) {
52082  return DRFLAC_FALSE;
52083  }
52084  *pResult = (drflac_uint8)result;
52085  return DRFLAC_TRUE;
52086 }
52087 static drflac_bool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, drflac_int8* pResult)
52088 {
52089  drflac_int32 result;
52090  DRFLAC_ASSERT(bs != NULL);
52091  DRFLAC_ASSERT(pResult != NULL);
52092  DRFLAC_ASSERT(bitCount > 0);
52093  DRFLAC_ASSERT(bitCount <= 8);
52094  if (!drflac__read_int32(bs, bitCount, &result)) {
52095  return DRFLAC_FALSE;
52096  }
52097  *pResult = (drflac_int8)result;
52098  return DRFLAC_TRUE;
52099 }
52100 static drflac_bool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek)
52101 {
52102  if (bitsToSeek <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
52103  bs->consumedBits += (drflac_uint32)bitsToSeek;
52104  bs->cache <<= bitsToSeek;
52105  return DRFLAC_TRUE;
52106  } else {
52107  bitsToSeek -= DRFLAC_CACHE_L1_BITS_REMAINING(bs);
52109  bs->cache = 0;
52110 #ifdef DRFLAC_64BIT
52111  while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
52112  drflac_uint64 bin;
52113  if (!drflac__read_uint64(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) {
52114  return DRFLAC_FALSE;
52115  }
52116  bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs);
52117  }
52118 #else
52119  while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
52120  drflac_uint32 bin;
52121  if (!drflac__read_uint32(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) {
52122  return DRFLAC_FALSE;
52123  }
52124  bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs);
52125  }
52126 #endif
52127  while (bitsToSeek >= 8) {
52128  drflac_uint8 bin;
52129  if (!drflac__read_uint8(bs, 8, &bin)) {
52130  return DRFLAC_FALSE;
52131  }
52132  bitsToSeek -= 8;
52133  }
52134  if (bitsToSeek > 0) {
52135  drflac_uint8 bin;
52136  if (!drflac__read_uint8(bs, (drflac_uint32)bitsToSeek, &bin)) {
52137  return DRFLAC_FALSE;
52138  }
52139  bitsToSeek = 0;
52140  }
52141  DRFLAC_ASSERT(bitsToSeek == 0);
52142  return DRFLAC_TRUE;
52143  }
52144 }
52146 {
52147  DRFLAC_ASSERT(bs != NULL);
52149  return DRFLAC_FALSE;
52150  }
52151  for (;;) {
52152  drflac_uint8 hi;
52153 #ifndef DR_FLAC_NO_CRC
52154  drflac__reset_crc16(bs);
52155 #endif
52156  if (!drflac__read_uint8(bs, 8, &hi)) {
52157  return DRFLAC_FALSE;
52158  }
52159  if (hi == 0xFF) {
52160  drflac_uint8 lo;
52161  if (!drflac__read_uint8(bs, 6, &lo)) {
52162  return DRFLAC_FALSE;
52163  }
52164  if (lo == 0x3E) {
52165  return DRFLAC_TRUE;
52166  } else {
52168  return DRFLAC_FALSE;
52169  }
52170  }
52171  }
52172  }
52173 }
52174 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
52175 #define DRFLAC_IMPLEMENT_CLZ_LZCNT
52176 #endif
52177 #if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(__clang__)
52178 #define DRFLAC_IMPLEMENT_CLZ_MSVC
52179 #endif
52180 #if defined(__WATCOMC__) && defined(__386__)
52181 #define DRFLAC_IMPLEMENT_CLZ_WATCOM
52182 #endif
52184 {
52185  drflac_uint32 n;
52186  static drflac_uint32 clz_table_4[] = {
52187  0,
52188  4,
52189  3, 3,
52190  2, 2, 2, 2,
52191  1, 1, 1, 1, 1, 1, 1, 1
52192  };
52193  if (x == 0) {
52194  return sizeof(x)*8;
52195  }
52196  n = clz_table_4[x >> (sizeof(x)*8 - 4)];
52197  if (n == 0) {
52198 #ifdef DRFLAC_64BIT
52199  if ((x & ((drflac_uint64)0xFFFFFFFF << 32)) == 0) { n = 32; x <<= 32; }
52200  if ((x & ((drflac_uint64)0xFFFF0000 << 32)) == 0) { n += 16; x <<= 16; }
52201  if ((x & ((drflac_uint64)0xFF000000 << 32)) == 0) { n += 8; x <<= 8; }
52202  if ((x & ((drflac_uint64)0xF0000000 << 32)) == 0) { n += 4; x <<= 4; }
52203 #else
52204  if ((x & 0xFFFF0000) == 0) { n = 16; x <<= 16; }
52205  if ((x & 0xFF000000) == 0) { n += 8; x <<= 8; }
52206  if ((x & 0xF0000000) == 0) { n += 4; x <<= 4; }
52207 #endif
52208  n += clz_table_4[x >> (sizeof(x)*8 - 4)];
52209  }
52210  return n - 1;
52211 }
52212 #ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
52213 static DRFLAC_INLINE drflac_bool32 drflac__is_lzcnt_supported(void)
52214 {
52215 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
52216  return DRFLAC_TRUE;
52217 #else
52218  #ifdef DRFLAC_HAS_LZCNT_INTRINSIC
52219  return drflac__gIsLZCNTSupported;
52220  #else
52221  return DRFLAC_FALSE;
52222  #endif
52223 #endif
52224 }
52225 static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
52226 {
52227 #if defined(_MSC_VER)
52228  #ifdef DRFLAC_64BIT
52229  return (drflac_uint32)__lzcnt64(x);
52230  #else
52231  return (drflac_uint32)__lzcnt(x);
52232  #endif
52233 #else
52234  #if defined(__GNUC__) || defined(__clang__)
52235  #if defined(DRFLAC_X64)
52236  {
52237  drflac_uint64 r;
52238  __asm__ __volatile__ (
52239  "lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
52240  );
52241  return (drflac_uint32)r;
52242  }
52243  #elif defined(DRFLAC_X86)
52244  {
52245  drflac_uint32 r;
52246  __asm__ __volatile__ (
52247  "lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
52248  );
52249  return r;
52250  }
52251  #elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(DRFLAC_64BIT)
52252  {
52253  unsigned int r;
52254  __asm__ __volatile__ (
52255  #if defined(DRFLAC_64BIT)
52256  "clz %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(x)
52257  #else
52258  "clz %[out], %[in]" : [out]"=r"(r) : [in]"r"(x)
52259  #endif
52260  );
52261  return r;
52262  }
52263  #else
52264  if (x == 0) {
52265  return sizeof(x)*8;
52266  }
52267  #ifdef DRFLAC_64BIT
52268  return (drflac_uint32)__builtin_clzll((drflac_uint64)x);
52269  #else
52270  return (drflac_uint32)__builtin_clzl((drflac_uint32)x);
52271  #endif
52272  #endif
52273  #else
52274  #error "This compiler does not support the lzcnt intrinsic."
52275  #endif
52276 #endif
52277 }
52278 #endif
52279 #ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
52280 #include <intrin.h>
52281 static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x)
52282 {
52283  drflac_uint32 n;
52284  if (x == 0) {
52285  return sizeof(x)*8;
52286  }
52287 #ifdef DRFLAC_64BIT
52288  _BitScanReverse64((unsigned long*)&n, x);
52289 #else
52290  _BitScanReverse((unsigned long*)&n, x);
52291 #endif
52292  return sizeof(x)*8 - n - 1;
52293 }
52294 #endif
52295 #ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM
52296 static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
52297 #pragma aux drflac__clz_watcom = \
52298  "bsr eax, eax" \
52299  "xor eax, 31" \
52300  parm [eax] nomemory \
52301  value [eax] \
52302  modify exact [eax] nomemory;
52303 #endif
52305 {
52306 #ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
52307  if (drflac__is_lzcnt_supported()) {
52308  return drflac__clz_lzcnt(x);
52309  } else
52310 #endif
52311  {
52312 #ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
52313  return drflac__clz_msvc(x);
52314 #elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
52315  return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
52316 #else
52317  return drflac__clz_software(x);
52318 #endif
52319  }
52320 }
52322 {
52323  drflac_uint32 zeroCounter = 0;
52324  drflac_uint32 setBitOffsetPlus1;
52325  while (bs->cache == 0) {
52326  zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
52327  if (!drflac__reload_cache(bs)) {
52328  return DRFLAC_FALSE;
52329  }
52330  }
52331  setBitOffsetPlus1 = drflac__clz(bs->cache);
52332  setBitOffsetPlus1 += 1;
52333  bs->consumedBits += setBitOffsetPlus1;
52334  bs->cache <<= setBitOffsetPlus1;
52335  *pOffsetOut = zeroCounter + setBitOffsetPlus1 - 1;
52336  return DRFLAC_TRUE;
52337 }
52339 {
52340  DRFLAC_ASSERT(bs != NULL);
52341  DRFLAC_ASSERT(offsetFromStart > 0);
52342  if (offsetFromStart > 0x7FFFFFFF) {
52343  drflac_uint64 bytesRemaining = offsetFromStart;
52344  if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
52345  return DRFLAC_FALSE;
52346  }
52347  bytesRemaining -= 0x7FFFFFFF;
52348  while (bytesRemaining > 0x7FFFFFFF) {
52349  if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
52350  return DRFLAC_FALSE;
52351  }
52352  bytesRemaining -= 0x7FFFFFFF;
52353  }
52354  if (bytesRemaining > 0) {
52355  if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
52356  return DRFLAC_FALSE;
52357  }
52358  }
52359  } else {
52360  if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
52361  return DRFLAC_FALSE;
52362  }
52363  }
52364  drflac__reset_cache(bs);
52365  return DRFLAC_TRUE;
52366 }
52368 {
52369  drflac_uint8 crc;
52370  drflac_uint64 result;
52371  drflac_uint8 utf8[7] = {0};
52372  int byteCount;
52373  int i;
52374  DRFLAC_ASSERT(bs != NULL);
52375  DRFLAC_ASSERT(pNumberOut != NULL);
52376  DRFLAC_ASSERT(pCRCOut != NULL);
52377  crc = *pCRCOut;
52378  if (!drflac__read_uint8(bs, 8, utf8)) {
52379  *pNumberOut = 0;
52380  return DRFLAC_AT_END;
52381  }
52382  crc = drflac_crc8(crc, utf8[0], 8);
52383  if ((utf8[0] & 0x80) == 0) {
52384  *pNumberOut = utf8[0];
52385  *pCRCOut = crc;
52386  return DRFLAC_SUCCESS;
52387  }
52388  if ((utf8[0] & 0xE0) == 0xC0) {
52389  byteCount = 2;
52390  } else if ((utf8[0] & 0xF0) == 0xE0) {
52391  byteCount = 3;
52392  } else if ((utf8[0] & 0xF8) == 0xF0) {
52393  byteCount = 4;
52394  } else if ((utf8[0] & 0xFC) == 0xF8) {
52395  byteCount = 5;
52396  } else if ((utf8[0] & 0xFE) == 0xFC) {
52397  byteCount = 6;
52398  } else if ((utf8[0] & 0xFF) == 0xFE) {
52399  byteCount = 7;
52400  } else {
52401  *pNumberOut = 0;
52402  return DRFLAC_CRC_MISMATCH;
52403  }
52404  DRFLAC_ASSERT(byteCount > 1);
52405  result = (drflac_uint64)(utf8[0] & (0xFF >> (byteCount + 1)));
52406  for (i = 1; i < byteCount; ++i) {
52407  if (!drflac__read_uint8(bs, 8, utf8 + i)) {
52408  *pNumberOut = 0;
52409  return DRFLAC_AT_END;
52410  }
52411  crc = drflac_crc8(crc, utf8[i], 8);
52412  result = (result << 6) | (utf8[i] & 0x3F);
52413  }
52414  *pNumberOut = result;
52415  *pCRCOut = crc;
52416  return DRFLAC_SUCCESS;
52417 }
52419 {
52420  drflac_int32 prediction = 0;
52421  DRFLAC_ASSERT(order <= 32);
52422  switch (order)
52423  {
52424  case 32: prediction += coefficients[31] * pDecodedSamples[-32];
52425  case 31: prediction += coefficients[30] * pDecodedSamples[-31];
52426  case 30: prediction += coefficients[29] * pDecodedSamples[-30];
52427  case 29: prediction += coefficients[28] * pDecodedSamples[-29];
52428  case 28: prediction += coefficients[27] * pDecodedSamples[-28];
52429  case 27: prediction += coefficients[26] * pDecodedSamples[-27];
52430  case 26: prediction += coefficients[25] * pDecodedSamples[-26];
52431  case 25: prediction += coefficients[24] * pDecodedSamples[-25];
52432  case 24: prediction += coefficients[23] * pDecodedSamples[-24];
52433  case 23: prediction += coefficients[22] * pDecodedSamples[-23];
52434  case 22: prediction += coefficients[21] * pDecodedSamples[-22];
52435  case 21: prediction += coefficients[20] * pDecodedSamples[-21];
52436  case 20: prediction += coefficients[19] * pDecodedSamples[-20];
52437  case 19: prediction += coefficients[18] * pDecodedSamples[-19];
52438  case 18: prediction += coefficients[17] * pDecodedSamples[-18];
52439  case 17: prediction += coefficients[16] * pDecodedSamples[-17];
52440  case 16: prediction += coefficients[15] * pDecodedSamples[-16];
52441  case 15: prediction += coefficients[14] * pDecodedSamples[-15];
52442  case 14: prediction += coefficients[13] * pDecodedSamples[-14];
52443  case 13: prediction += coefficients[12] * pDecodedSamples[-13];
52444  case 12: prediction += coefficients[11] * pDecodedSamples[-12];
52445  case 11: prediction += coefficients[10] * pDecodedSamples[-11];
52446  case 10: prediction += coefficients[ 9] * pDecodedSamples[-10];
52447  case 9: prediction += coefficients[ 8] * pDecodedSamples[- 9];
52448  case 8: prediction += coefficients[ 7] * pDecodedSamples[- 8];
52449  case 7: prediction += coefficients[ 6] * pDecodedSamples[- 7];
52450  case 6: prediction += coefficients[ 5] * pDecodedSamples[- 6];
52451  case 5: prediction += coefficients[ 4] * pDecodedSamples[- 5];
52452  case 4: prediction += coefficients[ 3] * pDecodedSamples[- 4];
52453  case 3: prediction += coefficients[ 2] * pDecodedSamples[- 3];
52454  case 2: prediction += coefficients[ 1] * pDecodedSamples[- 2];
52455  case 1: prediction += coefficients[ 0] * pDecodedSamples[- 1];
52456  }
52457  return (drflac_int32)(prediction >> shift);
52458 }
52460 {
52461  drflac_int64 prediction;
52462  DRFLAC_ASSERT(order <= 32);
52463 #ifndef DRFLAC_64BIT
52464  if (order == 8)
52465  {
52466  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52467  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52468  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52469  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52470  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52471  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52472  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
52473  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
52474  }
52475  else if (order == 7)
52476  {
52477  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52478  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52479  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52480  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52481  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52482  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52483  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
52484  }
52485  else if (order == 3)
52486  {
52487  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52488  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52489  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52490  }
52491  else if (order == 6)
52492  {
52493  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52494  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52495  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52496  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52497  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52498  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52499  }
52500  else if (order == 5)
52501  {
52502  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52503  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52504  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52505  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52506  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52507  }
52508  else if (order == 4)
52509  {
52510  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52511  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52512  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52513  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52514  }
52515  else if (order == 12)
52516  {
52517  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52518  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52519  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52520  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52521  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52522  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52523  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
52524  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
52525  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
52526  prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
52527  prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
52528  prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12];
52529  }
52530  else if (order == 2)
52531  {
52532  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52533  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52534  }
52535  else if (order == 1)
52536  {
52537  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52538  }
52539  else if (order == 10)
52540  {
52541  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52542  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52543  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52544  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52545  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52546  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52547  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
52548  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
52549  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
52550  prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
52551  }
52552  else if (order == 9)
52553  {
52554  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52555  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52556  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52557  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52558  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52559  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52560  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
52561  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
52562  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
52563  }
52564  else if (order == 11)
52565  {
52566  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
52567  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
52568  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
52569  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
52570  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
52571  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
52572  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
52573  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
52574  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
52575  prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
52576  prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
52577  }
52578  else
52579  {
52580  int j;
52581  prediction = 0;
52582  for (j = 0; j < (int)order; ++j) {
52583  prediction += coefficients[j] * (drflac_int64)pDecodedSamples[-j-1];
52584  }
52585  }
52586 #endif
52587 #ifdef DRFLAC_64BIT
52588  prediction = 0;
52589  switch (order)
52590  {
52591  case 32: prediction += coefficients[31] * (drflac_int64)pDecodedSamples[-32];
52592  case 31: prediction += coefficients[30] * (drflac_int64)pDecodedSamples[-31];
52593  case 30: prediction += coefficients[29] * (drflac_int64)pDecodedSamples[-30];
52594  case 29: prediction += coefficients[28] * (drflac_int64)pDecodedSamples[-29];
52595  case 28: prediction += coefficients[27] * (drflac_int64)pDecodedSamples[-28];
52596  case 27: prediction += coefficients[26] * (drflac_int64)pDecodedSamples[-27];
52597  case 26: prediction += coefficients[25] * (drflac_int64)pDecodedSamples[-26];
52598  case 25: prediction += coefficients[24] * (drflac_int64)pDecodedSamples[-25];
52599  case 24: prediction += coefficients[23] * (drflac_int64)pDecodedSamples[-24];
52600  case 23: prediction += coefficients[22] * (drflac_int64)pDecodedSamples[-23];
52601  case 22: prediction += coefficients[21] * (drflac_int64)pDecodedSamples[-22];
52602  case 21: prediction += coefficients[20] * (drflac_int64)pDecodedSamples[-21];
52603  case 20: prediction += coefficients[19] * (drflac_int64)pDecodedSamples[-20];
52604  case 19: prediction += coefficients[18] * (drflac_int64)pDecodedSamples[-19];
52605  case 18: prediction += coefficients[17] * (drflac_int64)pDecodedSamples[-18];
52606  case 17: prediction += coefficients[16] * (drflac_int64)pDecodedSamples[-17];
52607  case 16: prediction += coefficients[15] * (drflac_int64)pDecodedSamples[-16];
52608  case 15: prediction += coefficients[14] * (drflac_int64)pDecodedSamples[-15];
52609  case 14: prediction += coefficients[13] * (drflac_int64)pDecodedSamples[-14];
52610  case 13: prediction += coefficients[12] * (drflac_int64)pDecodedSamples[-13];
52611  case 12: prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12];
52612  case 11: prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
52613  case 10: prediction += coefficients[ 9] * (drflac_int64)pDecodedSamples[-10];
52614  case 9: prediction += coefficients[ 8] * (drflac_int64)pDecodedSamples[- 9];
52615  case 8: prediction += coefficients[ 7] * (drflac_int64)pDecodedSamples[- 8];
52616  case 7: prediction += coefficients[ 6] * (drflac_int64)pDecodedSamples[- 7];
52617  case 6: prediction += coefficients[ 5] * (drflac_int64)pDecodedSamples[- 6];
52618  case 5: prediction += coefficients[ 4] * (drflac_int64)pDecodedSamples[- 5];
52619  case 4: prediction += coefficients[ 3] * (drflac_int64)pDecodedSamples[- 4];
52620  case 3: prediction += coefficients[ 2] * (drflac_int64)pDecodedSamples[- 3];
52621  case 2: prediction += coefficients[ 1] * (drflac_int64)pDecodedSamples[- 2];
52622  case 1: prediction += coefficients[ 0] * (drflac_int64)pDecodedSamples[- 1];
52623  }
52624 #endif
52625  return (drflac_int32)(prediction >> shift);
52626 }
52627 #if 0
52628 static drflac_bool32 drflac__decode_samples_with_residual__rice__reference(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
52629 {
52630  drflac_uint32 i;
52631  DRFLAC_ASSERT(bs != NULL);
52632  DRFLAC_ASSERT(pSamplesOut != NULL);
52633  for (i = 0; i < count; ++i) {
52634  drflac_uint32 zeroCounter = 0;
52635  for (;;) {
52636  drflac_uint8 bit;
52637  if (!drflac__read_uint8(bs, 1, &bit)) {
52638  return DRFLAC_FALSE;
52639  }
52640  if (bit == 0) {
52641  zeroCounter += 1;
52642  } else {
52643  break;
52644  }
52645  }
52646  drflac_uint32 decodedRice;
52647  if (riceParam > 0) {
52648  if (!drflac__read_uint32(bs, riceParam, &decodedRice)) {
52649  return DRFLAC_FALSE;
52650  }
52651  } else {
52652  decodedRice = 0;
52653  }
52654  decodedRice |= (zeroCounter << riceParam);
52655  if ((decodedRice & 0x01)) {
52656  decodedRice = ~(decodedRice >> 1);
52657  } else {
52658  decodedRice = (decodedRice >> 1);
52659  }
52660  if (bitsPerSample+shift >= 32) {
52661  pSamplesOut[i] = decodedRice + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
52662  } else {
52663  pSamplesOut[i] = decodedRice + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i);
52664  }
52665  }
52666  return DRFLAC_TRUE;
52667 }
52668 #endif
52669 #if 0
52670 static drflac_bool32 drflac__read_rice_parts__reference(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
52671 {
52672  drflac_uint32 zeroCounter = 0;
52673  drflac_uint32 decodedRice;
52674  for (;;) {
52675  drflac_uint8 bit;
52676  if (!drflac__read_uint8(bs, 1, &bit)) {
52677  return DRFLAC_FALSE;
52678  }
52679  if (bit == 0) {
52680  zeroCounter += 1;
52681  } else {
52682  break;
52683  }
52684  }
52685  if (riceParam > 0) {
52686  if (!drflac__read_uint32(bs, riceParam, &decodedRice)) {
52687  return DRFLAC_FALSE;
52688  }
52689  } else {
52690  decodedRice = 0;
52691  }
52692  *pZeroCounterOut = zeroCounter;
52693  *pRiceParamPartOut = decodedRice;
52694  return DRFLAC_TRUE;
52695 }
52696 #endif
52697 #if 0
52698 static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
52699 {
52700  drflac_cache_t riceParamMask;
52701  drflac_uint32 zeroCounter;
52702  drflac_uint32 setBitOffsetPlus1;
52703  drflac_uint32 riceParamPart;
52704  drflac_uint32 riceLength;
52705  DRFLAC_ASSERT(riceParam > 0);
52706  riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam);
52707  zeroCounter = 0;
52708  while (bs->cache == 0) {
52709  zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
52710  if (!drflac__reload_cache(bs)) {
52711  return DRFLAC_FALSE;
52712  }
52713  }
52714  setBitOffsetPlus1 = drflac__clz(bs->cache);
52715  zeroCounter += setBitOffsetPlus1;
52716  setBitOffsetPlus1 += 1;
52717  riceLength = setBitOffsetPlus1 + riceParam;
52718  if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
52719  riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceLength));
52720  bs->consumedBits += riceLength;
52721  bs->cache <<= riceLength;
52722  } else {
52723  drflac_uint32 bitCountLo;
52724  drflac_cache_t resultHi;
52725  bs->consumedBits += riceLength;
52726  bs->cache <<= setBitOffsetPlus1 & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1);
52727  bitCountLo = bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs);
52728  resultHi = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, riceParam);
52729  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
52730 #ifndef DR_FLAC_NO_CRC
52732 #endif
52734  bs->consumedBits = 0;
52735 #ifndef DR_FLAC_NO_CRC
52736  bs->crc16Cache = bs->cache;
52737 #endif
52738  } else {
52739  if (!drflac__reload_cache(bs)) {
52740  return DRFLAC_FALSE;
52741  }
52742  }
52743  riceParamPart = (drflac_uint32)(resultHi | DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, bitCountLo));
52744  bs->consumedBits += bitCountLo;
52745  bs->cache <<= bitCountLo;
52746  }
52747  pZeroCounterOut[0] = zeroCounter;
52748  pRiceParamPartOut[0] = riceParamPart;
52749  return DRFLAC_TRUE;
52750 }
52751 #endif
52753 {
52754  drflac_uint32 riceParamPlus1 = riceParam + 1;
52755  drflac_uint32 riceParamPlus1Shift = DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceParamPlus1);
52756  drflac_uint32 riceParamPlus1MaxConsumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParamPlus1;
52757  drflac_cache_t bs_cache = bs->cache;
52758  drflac_uint32 bs_consumedBits = bs->consumedBits;
52759  drflac_uint32 lzcount = drflac__clz(bs_cache);
52760  if (lzcount < sizeof(bs_cache)*8) {
52761  pZeroCounterOut[0] = lzcount;
52762  extract_rice_param_part:
52763  bs_cache <<= lzcount;
52764  bs_consumedBits += lzcount;
52765  if (bs_consumedBits <= riceParamPlus1MaxConsumedBits) {
52766  pRiceParamPartOut[0] = (drflac_uint32)(bs_cache >> riceParamPlus1Shift);
52767  bs_cache <<= riceParamPlus1;
52768  bs_consumedBits += riceParamPlus1;
52769  } else {
52770  drflac_uint32 riceParamPartHi;
52771  drflac_uint32 riceParamPartLo;
52772  drflac_uint32 riceParamPartLoBitCount;
52773  riceParamPartHi = (drflac_uint32)(bs_cache >> riceParamPlus1Shift);
52774  riceParamPartLoBitCount = bs_consumedBits - riceParamPlus1MaxConsumedBits;
52775  DRFLAC_ASSERT(riceParamPartLoBitCount > 0 && riceParamPartLoBitCount < 32);
52776  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
52777  #ifndef DR_FLAC_NO_CRC
52779  #endif
52780  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
52781  bs_consumedBits = riceParamPartLoBitCount;
52782  #ifndef DR_FLAC_NO_CRC
52783  bs->crc16Cache = bs_cache;
52784  #endif
52785  } else {
52786  if (!drflac__reload_cache(bs)) {
52787  return DRFLAC_FALSE;
52788  }
52789  bs_cache = bs->cache;
52790  bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
52791  }
52792  riceParamPartLo = (drflac_uint32)(bs_cache >> (DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceParamPartLoBitCount)));
52793  pRiceParamPartOut[0] = riceParamPartHi | riceParamPartLo;
52794  bs_cache <<= riceParamPartLoBitCount;
52795  }
52796  } else {
52797  drflac_uint32 zeroCounter = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BITS(bs) - bs_consumedBits);
52798  for (;;) {
52799  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
52800  #ifndef DR_FLAC_NO_CRC
52802  #endif
52803  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
52804  bs_consumedBits = 0;
52805  #ifndef DR_FLAC_NO_CRC
52806  bs->crc16Cache = bs_cache;
52807  #endif
52808  } else {
52809  if (!drflac__reload_cache(bs)) {
52810  return DRFLAC_FALSE;
52811  }
52812  bs_cache = bs->cache;
52813  bs_consumedBits = bs->consumedBits;
52814  }
52815  lzcount = drflac__clz(bs_cache);
52816  zeroCounter += lzcount;
52817  if (lzcount < sizeof(bs_cache)*8) {
52818  break;
52819  }
52820  }
52821  pZeroCounterOut[0] = zeroCounter;
52822  goto extract_rice_param_part;
52823  }
52824  bs->cache = bs_cache;
52825  bs->consumedBits = bs_consumedBits;
52826  return DRFLAC_TRUE;
52827 }
52829 {
52830  drflac_uint32 riceParamPlus1 = riceParam + 1;
52831  drflac_uint32 riceParamPlus1MaxConsumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParamPlus1;
52832  drflac_cache_t bs_cache = bs->cache;
52833  drflac_uint32 bs_consumedBits = bs->consumedBits;
52834  drflac_uint32 lzcount = drflac__clz(bs_cache);
52835  if (lzcount < sizeof(bs_cache)*8) {
52836  extract_rice_param_part:
52837  bs_cache <<= lzcount;
52838  bs_consumedBits += lzcount;
52839  if (bs_consumedBits <= riceParamPlus1MaxConsumedBits) {
52840  bs_cache <<= riceParamPlus1;
52841  bs_consumedBits += riceParamPlus1;
52842  } else {
52843  drflac_uint32 riceParamPartLoBitCount = bs_consumedBits - riceParamPlus1MaxConsumedBits;
52844  DRFLAC_ASSERT(riceParamPartLoBitCount > 0 && riceParamPartLoBitCount < 32);
52845  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
52846  #ifndef DR_FLAC_NO_CRC
52848  #endif
52849  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
52850  bs_consumedBits = riceParamPartLoBitCount;
52851  #ifndef DR_FLAC_NO_CRC
52852  bs->crc16Cache = bs_cache;
52853  #endif
52854  } else {
52855  if (!drflac__reload_cache(bs)) {
52856  return DRFLAC_FALSE;
52857  }
52858  bs_cache = bs->cache;
52859  bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
52860  }
52861  bs_cache <<= riceParamPartLoBitCount;
52862  }
52863  } else {
52864  for (;;) {
52865  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
52866  #ifndef DR_FLAC_NO_CRC
52868  #endif
52869  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
52870  bs_consumedBits = 0;
52871  #ifndef DR_FLAC_NO_CRC
52872  bs->crc16Cache = bs_cache;
52873  #endif
52874  } else {
52875  if (!drflac__reload_cache(bs)) {
52876  return DRFLAC_FALSE;
52877  }
52878  bs_cache = bs->cache;
52879  bs_consumedBits = bs->consumedBits;
52880  }
52881  lzcount = drflac__clz(bs_cache);
52882  if (lzcount < sizeof(bs_cache)*8) {
52883  break;
52884  }
52885  }
52886  goto extract_rice_param_part;
52887  }
52888  bs->cache = bs_cache;
52889  bs->consumedBits = bs_consumedBits;
52890  return DRFLAC_TRUE;
52891 }
52893 {
52894  drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
52895  drflac_uint32 zeroCountPart0;
52896  drflac_uint32 riceParamPart0;
52897  drflac_uint32 riceParamMask;
52898  drflac_uint32 i;
52899  DRFLAC_ASSERT(bs != NULL);
52900  DRFLAC_ASSERT(pSamplesOut != NULL);
52901  (void)bitsPerSample;
52902  (void)order;
52903  (void)shift;
52904  (void)coefficients;
52905  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
52906  i = 0;
52907  while (i < count) {
52908  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0)) {
52909  return DRFLAC_FALSE;
52910  }
52911  riceParamPart0 &= riceParamMask;
52912  riceParamPart0 |= (zeroCountPart0 << riceParam);
52913  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
52914  pSamplesOut[i] = riceParamPart0;
52915  i += 1;
52916  }
52917  return DRFLAC_TRUE;
52918 }
52920 {
52921  drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
52922  drflac_uint32 zeroCountPart0 = 0;
52923  drflac_uint32 zeroCountPart1 = 0;
52924  drflac_uint32 zeroCountPart2 = 0;
52925  drflac_uint32 zeroCountPart3 = 0;
52926  drflac_uint32 riceParamPart0 = 0;
52927  drflac_uint32 riceParamPart1 = 0;
52928  drflac_uint32 riceParamPart2 = 0;
52929  drflac_uint32 riceParamPart3 = 0;
52930  drflac_uint32 riceParamMask;
52931  const drflac_int32* pSamplesOutEnd;
52932  drflac_uint32 i;
52933  DRFLAC_ASSERT(bs != NULL);
52934  DRFLAC_ASSERT(pSamplesOut != NULL);
52935  if (order == 0) {
52936  return drflac__decode_samples_with_residual__rice__scalar_zeroorder(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
52937  }
52938  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
52939  pSamplesOutEnd = pSamplesOut + (count & ~3);
52940  if (bitsPerSample+shift > 32) {
52941  while (pSamplesOut < pSamplesOutEnd) {
52942  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0) ||
52943  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart1, &riceParamPart1) ||
52944  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart2, &riceParamPart2) ||
52945  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart3, &riceParamPart3)) {
52946  return DRFLAC_FALSE;
52947  }
52948  riceParamPart0 &= riceParamMask;
52949  riceParamPart1 &= riceParamMask;
52950  riceParamPart2 &= riceParamMask;
52951  riceParamPart3 &= riceParamMask;
52952  riceParamPart0 |= (zeroCountPart0 << riceParam);
52953  riceParamPart1 |= (zeroCountPart1 << riceParam);
52954  riceParamPart2 |= (zeroCountPart2 << riceParam);
52955  riceParamPart3 |= (zeroCountPart3 << riceParam);
52956  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
52957  riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
52958  riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
52959  riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
52960  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
52961  pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 1);
52962  pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 2);
52963  pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 3);
52964  pSamplesOut += 4;
52965  }
52966  } else {
52967  while (pSamplesOut < pSamplesOutEnd) {
52968  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0) ||
52969  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart1, &riceParamPart1) ||
52970  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart2, &riceParamPart2) ||
52971  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart3, &riceParamPart3)) {
52972  return DRFLAC_FALSE;
52973  }
52974  riceParamPart0 &= riceParamMask;
52975  riceParamPart1 &= riceParamMask;
52976  riceParamPart2 &= riceParamMask;
52977  riceParamPart3 &= riceParamMask;
52978  riceParamPart0 |= (zeroCountPart0 << riceParam);
52979  riceParamPart1 |= (zeroCountPart1 << riceParam);
52980  riceParamPart2 |= (zeroCountPart2 << riceParam);
52981  riceParamPart3 |= (zeroCountPart3 << riceParam);
52982  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
52983  riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
52984  riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
52985  riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
52986  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
52987  pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 1);
52988  pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 2);
52989  pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 3);
52990  pSamplesOut += 4;
52991  }
52992  }
52993  i = (count & ~3);
52994  while (i < count) {
52995  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0)) {
52996  return DRFLAC_FALSE;
52997  }
52998  riceParamPart0 &= riceParamMask;
52999  riceParamPart0 |= (zeroCountPart0 << riceParam);
53000  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
53001  if (bitsPerSample+shift > 32) {
53002  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
53003  } else {
53004  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
53005  }
53006  i += 1;
53007  pSamplesOut += 1;
53008  }
53009  return DRFLAC_TRUE;
53010 }
53011 #if defined(DRFLAC_SUPPORT_SSE2)
53012 static DRFLAC_INLINE __m128i drflac__mm_packs_interleaved_epi32(__m128i a, __m128i b)
53013 {
53014  __m128i r;
53015  r = _mm_packs_epi32(a, b);
53016  r = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 1, 2, 0));
53017  r = _mm_shufflehi_epi16(r, _MM_SHUFFLE(3, 1, 2, 0));
53018  r = _mm_shufflelo_epi16(r, _MM_SHUFFLE(3, 1, 2, 0));
53019  return r;
53020 }
53021 #endif
53022 #if defined(DRFLAC_SUPPORT_SSE41)
53023 static DRFLAC_INLINE __m128i drflac__mm_not_si128(__m128i a)
53024 {
53025  return _mm_xor_si128(a, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
53026 }
53027 static DRFLAC_INLINE __m128i drflac__mm_hadd_epi32(__m128i x)
53028 {
53029  __m128i x64 = _mm_add_epi32(x, _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)));
53030  __m128i x32 = _mm_shufflelo_epi16(x64, _MM_SHUFFLE(1, 0, 3, 2));
53031  return _mm_add_epi32(x64, x32);
53032 }
53033 static DRFLAC_INLINE __m128i drflac__mm_hadd_epi64(__m128i x)
53034 {
53035  return _mm_add_epi64(x, _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)));
53036 }
53037 static DRFLAC_INLINE __m128i drflac__mm_srai_epi64(__m128i x, int count)
53038 {
53039  __m128i lo = _mm_srli_epi64(x, count);
53040  __m128i hi = _mm_srai_epi32(x, count);
53041  hi = _mm_and_si128(hi, _mm_set_epi32(0xFFFFFFFF, 0, 0xFFFFFFFF, 0));
53042  return _mm_or_si128(lo, hi);
53043 }
53044 static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_32(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53045 {
53046  int i;
53047  drflac_uint32 riceParamMask;
53048  drflac_int32* pDecodedSamples = pSamplesOut;
53049  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
53050  drflac_uint32 zeroCountParts0 = 0;
53051  drflac_uint32 zeroCountParts1 = 0;
53052  drflac_uint32 zeroCountParts2 = 0;
53053  drflac_uint32 zeroCountParts3 = 0;
53054  drflac_uint32 riceParamParts0 = 0;
53055  drflac_uint32 riceParamParts1 = 0;
53056  drflac_uint32 riceParamParts2 = 0;
53057  drflac_uint32 riceParamParts3 = 0;
53058  __m128i coefficients128_0;
53059  __m128i coefficients128_4;
53060  __m128i coefficients128_8;
53061  __m128i samples128_0;
53062  __m128i samples128_4;
53063  __m128i samples128_8;
53064  __m128i riceParamMask128;
53065  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
53066  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
53067  riceParamMask128 = _mm_set1_epi32(riceParamMask);
53068  coefficients128_0 = _mm_setzero_si128();
53069  coefficients128_4 = _mm_setzero_si128();
53070  coefficients128_8 = _mm_setzero_si128();
53071  samples128_0 = _mm_setzero_si128();
53072  samples128_4 = _mm_setzero_si128();
53073  samples128_8 = _mm_setzero_si128();
53074 #if 1
53075  {
53076  int runningOrder = order;
53077  if (runningOrder >= 4) {
53078  coefficients128_0 = _mm_loadu_si128((const __m128i*)(coefficients + 0));
53079  samples128_0 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 4));
53080  runningOrder -= 4;
53081  } else {
53082  switch (runningOrder) {
53083  case 3: coefficients128_0 = _mm_set_epi32(0, coefficients[2], coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], pSamplesOut[-3], 0); break;
53084  case 2: coefficients128_0 = _mm_set_epi32(0, 0, coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], 0, 0); break;
53085  case 1: coefficients128_0 = _mm_set_epi32(0, 0, 0, coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], 0, 0, 0); break;
53086  }
53087  runningOrder = 0;
53088  }
53089  if (runningOrder >= 4) {
53090  coefficients128_4 = _mm_loadu_si128((const __m128i*)(coefficients + 4));
53091  samples128_4 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 8));
53092  runningOrder -= 4;
53093  } else {
53094  switch (runningOrder) {
53095  case 3: coefficients128_4 = _mm_set_epi32(0, coefficients[6], coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], pSamplesOut[-7], 0); break;
53096  case 2: coefficients128_4 = _mm_set_epi32(0, 0, coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], 0, 0); break;
53097  case 1: coefficients128_4 = _mm_set_epi32(0, 0, 0, coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], 0, 0, 0); break;
53098  }
53099  runningOrder = 0;
53100  }
53101  if (runningOrder == 4) {
53102  coefficients128_8 = _mm_loadu_si128((const __m128i*)(coefficients + 8));
53103  samples128_8 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 12));
53104  runningOrder -= 4;
53105  } else {
53106  switch (runningOrder) {
53107  case 3: coefficients128_8 = _mm_set_epi32(0, coefficients[10], coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], pSamplesOut[-11], 0); break;
53108  case 2: coefficients128_8 = _mm_set_epi32(0, 0, coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], 0, 0); break;
53109  case 1: coefficients128_8 = _mm_set_epi32(0, 0, 0, coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], 0, 0, 0); break;
53110  }
53111  runningOrder = 0;
53112  }
53113  coefficients128_0 = _mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(0, 1, 2, 3));
53114  coefficients128_4 = _mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(0, 1, 2, 3));
53115  coefficients128_8 = _mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(0, 1, 2, 3));
53116  }
53117 #else
53118  switch (order)
53119  {
53120  case 12: ((drflac_int32*)&coefficients128_8)[0] = coefficients[11]; ((drflac_int32*)&samples128_8)[0] = pDecodedSamples[-12];
53121  case 11: ((drflac_int32*)&coefficients128_8)[1] = coefficients[10]; ((drflac_int32*)&samples128_8)[1] = pDecodedSamples[-11];
53122  case 10: ((drflac_int32*)&coefficients128_8)[2] = coefficients[ 9]; ((drflac_int32*)&samples128_8)[2] = pDecodedSamples[-10];
53123  case 9: ((drflac_int32*)&coefficients128_8)[3] = coefficients[ 8]; ((drflac_int32*)&samples128_8)[3] = pDecodedSamples[- 9];
53124  case 8: ((drflac_int32*)&coefficients128_4)[0] = coefficients[ 7]; ((drflac_int32*)&samples128_4)[0] = pDecodedSamples[- 8];
53125  case 7: ((drflac_int32*)&coefficients128_4)[1] = coefficients[ 6]; ((drflac_int32*)&samples128_4)[1] = pDecodedSamples[- 7];
53126  case 6: ((drflac_int32*)&coefficients128_4)[2] = coefficients[ 5]; ((drflac_int32*)&samples128_4)[2] = pDecodedSamples[- 6];
53127  case 5: ((drflac_int32*)&coefficients128_4)[3] = coefficients[ 4]; ((drflac_int32*)&samples128_4)[3] = pDecodedSamples[- 5];
53128  case 4: ((drflac_int32*)&coefficients128_0)[0] = coefficients[ 3]; ((drflac_int32*)&samples128_0)[0] = pDecodedSamples[- 4];
53129  case 3: ((drflac_int32*)&coefficients128_0)[1] = coefficients[ 2]; ((drflac_int32*)&samples128_0)[1] = pDecodedSamples[- 3];
53130  case 2: ((drflac_int32*)&coefficients128_0)[2] = coefficients[ 1]; ((drflac_int32*)&samples128_0)[2] = pDecodedSamples[- 2];
53131  case 1: ((drflac_int32*)&coefficients128_0)[3] = coefficients[ 0]; ((drflac_int32*)&samples128_0)[3] = pDecodedSamples[- 1];
53132  }
53133 #endif
53134  while (pDecodedSamples < pDecodedSamplesEnd) {
53135  __m128i prediction128;
53136  __m128i zeroCountPart128;
53137  __m128i riceParamPart128;
53138  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0) ||
53139  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts1, &riceParamParts1) ||
53140  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts2, &riceParamParts2) ||
53141  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts3, &riceParamParts3)) {
53142  return DRFLAC_FALSE;
53143  }
53144  zeroCountPart128 = _mm_set_epi32(zeroCountParts3, zeroCountParts2, zeroCountParts1, zeroCountParts0);
53145  riceParamPart128 = _mm_set_epi32(riceParamParts3, riceParamParts2, riceParamParts1, riceParamParts0);
53146  riceParamPart128 = _mm_and_si128(riceParamPart128, riceParamMask128);
53147  riceParamPart128 = _mm_or_si128(riceParamPart128, _mm_slli_epi32(zeroCountPart128, riceParam));
53148  riceParamPart128 = _mm_xor_si128(_mm_srli_epi32(riceParamPart128, 1), _mm_add_epi32(drflac__mm_not_si128(_mm_and_si128(riceParamPart128, _mm_set1_epi32(0x01))), _mm_set1_epi32(0x01)));
53149  if (order <= 4) {
53150  for (i = 0; i < 4; i += 1) {
53151  prediction128 = _mm_mullo_epi32(coefficients128_0, samples128_0);
53152  prediction128 = drflac__mm_hadd_epi32(prediction128);
53153  prediction128 = _mm_srai_epi32(prediction128, shift);
53154  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
53155  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
53156  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
53157  }
53158  } else if (order <= 8) {
53159  for (i = 0; i < 4; i += 1) {
53160  prediction128 = _mm_mullo_epi32(coefficients128_4, samples128_4);
53161  prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_0, samples128_0));
53162  prediction128 = drflac__mm_hadd_epi32(prediction128);
53163  prediction128 = _mm_srai_epi32(prediction128, shift);
53164  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
53165  samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
53166  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
53167  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
53168  }
53169  } else {
53170  for (i = 0; i < 4; i += 1) {
53171  prediction128 = _mm_mullo_epi32(coefficients128_8, samples128_8);
53172  prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_4, samples128_4));
53173  prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_0, samples128_0));
53174  prediction128 = drflac__mm_hadd_epi32(prediction128);
53175  prediction128 = _mm_srai_epi32(prediction128, shift);
53176  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
53177  samples128_8 = _mm_alignr_epi8(samples128_4, samples128_8, 4);
53178  samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
53179  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
53180  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
53181  }
53182  }
53183  _mm_storeu_si128((__m128i*)pDecodedSamples, samples128_0);
53184  pDecodedSamples += 4;
53185  }
53186  i = (count & ~3);
53187  while (i < (int)count) {
53188  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0)) {
53189  return DRFLAC_FALSE;
53190  }
53191  riceParamParts0 &= riceParamMask;
53192  riceParamParts0 |= (zeroCountParts0 << riceParam);
53193  riceParamParts0 = (riceParamParts0 >> 1) ^ t[riceParamParts0 & 0x01];
53194  pDecodedSamples[0] = riceParamParts0 + drflac__calculate_prediction_32(order, shift, coefficients, pDecodedSamples);
53195  i += 1;
53196  pDecodedSamples += 1;
53197  }
53198  return DRFLAC_TRUE;
53199 }
53200 static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_64(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53201 {
53202  int i;
53203  drflac_uint32 riceParamMask;
53204  drflac_int32* pDecodedSamples = pSamplesOut;
53205  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
53206  drflac_uint32 zeroCountParts0 = 0;
53207  drflac_uint32 zeroCountParts1 = 0;
53208  drflac_uint32 zeroCountParts2 = 0;
53209  drflac_uint32 zeroCountParts3 = 0;
53210  drflac_uint32 riceParamParts0 = 0;
53211  drflac_uint32 riceParamParts1 = 0;
53212  drflac_uint32 riceParamParts2 = 0;
53213  drflac_uint32 riceParamParts3 = 0;
53214  __m128i coefficients128_0;
53215  __m128i coefficients128_4;
53216  __m128i coefficients128_8;
53217  __m128i samples128_0;
53218  __m128i samples128_4;
53219  __m128i samples128_8;
53220  __m128i prediction128;
53221  __m128i riceParamMask128;
53222  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
53223  DRFLAC_ASSERT(order <= 12);
53224  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
53225  riceParamMask128 = _mm_set1_epi32(riceParamMask);
53226  prediction128 = _mm_setzero_si128();
53227  coefficients128_0 = _mm_setzero_si128();
53228  coefficients128_4 = _mm_setzero_si128();
53229  coefficients128_8 = _mm_setzero_si128();
53230  samples128_0 = _mm_setzero_si128();
53231  samples128_4 = _mm_setzero_si128();
53232  samples128_8 = _mm_setzero_si128();
53233 #if 1
53234  {
53235  int runningOrder = order;
53236  if (runningOrder >= 4) {
53237  coefficients128_0 = _mm_loadu_si128((const __m128i*)(coefficients + 0));
53238  samples128_0 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 4));
53239  runningOrder -= 4;
53240  } else {
53241  switch (runningOrder) {
53242  case 3: coefficients128_0 = _mm_set_epi32(0, coefficients[2], coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], pSamplesOut[-3], 0); break;
53243  case 2: coefficients128_0 = _mm_set_epi32(0, 0, coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], 0, 0); break;
53244  case 1: coefficients128_0 = _mm_set_epi32(0, 0, 0, coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], 0, 0, 0); break;
53245  }
53246  runningOrder = 0;
53247  }
53248  if (runningOrder >= 4) {
53249  coefficients128_4 = _mm_loadu_si128((const __m128i*)(coefficients + 4));
53250  samples128_4 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 8));
53251  runningOrder -= 4;
53252  } else {
53253  switch (runningOrder) {
53254  case 3: coefficients128_4 = _mm_set_epi32(0, coefficients[6], coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], pSamplesOut[-7], 0); break;
53255  case 2: coefficients128_4 = _mm_set_epi32(0, 0, coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], 0, 0); break;
53256  case 1: coefficients128_4 = _mm_set_epi32(0, 0, 0, coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], 0, 0, 0); break;
53257  }
53258  runningOrder = 0;
53259  }
53260  if (runningOrder == 4) {
53261  coefficients128_8 = _mm_loadu_si128((const __m128i*)(coefficients + 8));
53262  samples128_8 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 12));
53263  runningOrder -= 4;
53264  } else {
53265  switch (runningOrder) {
53266  case 3: coefficients128_8 = _mm_set_epi32(0, coefficients[10], coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], pSamplesOut[-11], 0); break;
53267  case 2: coefficients128_8 = _mm_set_epi32(0, 0, coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], 0, 0); break;
53268  case 1: coefficients128_8 = _mm_set_epi32(0, 0, 0, coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], 0, 0, 0); break;
53269  }
53270  runningOrder = 0;
53271  }
53272  coefficients128_0 = _mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(0, 1, 2, 3));
53273  coefficients128_4 = _mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(0, 1, 2, 3));
53274  coefficients128_8 = _mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(0, 1, 2, 3));
53275  }
53276 #else
53277  switch (order)
53278  {
53279  case 12: ((drflac_int32*)&coefficients128_8)[0] = coefficients[11]; ((drflac_int32*)&samples128_8)[0] = pDecodedSamples[-12];
53280  case 11: ((drflac_int32*)&coefficients128_8)[1] = coefficients[10]; ((drflac_int32*)&samples128_8)[1] = pDecodedSamples[-11];
53281  case 10: ((drflac_int32*)&coefficients128_8)[2] = coefficients[ 9]; ((drflac_int32*)&samples128_8)[2] = pDecodedSamples[-10];
53282  case 9: ((drflac_int32*)&coefficients128_8)[3] = coefficients[ 8]; ((drflac_int32*)&samples128_8)[3] = pDecodedSamples[- 9];
53283  case 8: ((drflac_int32*)&coefficients128_4)[0] = coefficients[ 7]; ((drflac_int32*)&samples128_4)[0] = pDecodedSamples[- 8];
53284  case 7: ((drflac_int32*)&coefficients128_4)[1] = coefficients[ 6]; ((drflac_int32*)&samples128_4)[1] = pDecodedSamples[- 7];
53285  case 6: ((drflac_int32*)&coefficients128_4)[2] = coefficients[ 5]; ((drflac_int32*)&samples128_4)[2] = pDecodedSamples[- 6];
53286  case 5: ((drflac_int32*)&coefficients128_4)[3] = coefficients[ 4]; ((drflac_int32*)&samples128_4)[3] = pDecodedSamples[- 5];
53287  case 4: ((drflac_int32*)&coefficients128_0)[0] = coefficients[ 3]; ((drflac_int32*)&samples128_0)[0] = pDecodedSamples[- 4];
53288  case 3: ((drflac_int32*)&coefficients128_0)[1] = coefficients[ 2]; ((drflac_int32*)&samples128_0)[1] = pDecodedSamples[- 3];
53289  case 2: ((drflac_int32*)&coefficients128_0)[2] = coefficients[ 1]; ((drflac_int32*)&samples128_0)[2] = pDecodedSamples[- 2];
53290  case 1: ((drflac_int32*)&coefficients128_0)[3] = coefficients[ 0]; ((drflac_int32*)&samples128_0)[3] = pDecodedSamples[- 1];
53291  }
53292 #endif
53293  while (pDecodedSamples < pDecodedSamplesEnd) {
53294  __m128i zeroCountPart128;
53295  __m128i riceParamPart128;
53296  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0) ||
53297  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts1, &riceParamParts1) ||
53298  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts2, &riceParamParts2) ||
53299  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts3, &riceParamParts3)) {
53300  return DRFLAC_FALSE;
53301  }
53302  zeroCountPart128 = _mm_set_epi32(zeroCountParts3, zeroCountParts2, zeroCountParts1, zeroCountParts0);
53303  riceParamPart128 = _mm_set_epi32(riceParamParts3, riceParamParts2, riceParamParts1, riceParamParts0);
53304  riceParamPart128 = _mm_and_si128(riceParamPart128, riceParamMask128);
53305  riceParamPart128 = _mm_or_si128(riceParamPart128, _mm_slli_epi32(zeroCountPart128, riceParam));
53306  riceParamPart128 = _mm_xor_si128(_mm_srli_epi32(riceParamPart128, 1), _mm_add_epi32(drflac__mm_not_si128(_mm_and_si128(riceParamPart128, _mm_set1_epi32(1))), _mm_set1_epi32(1)));
53307  for (i = 0; i < 4; i += 1) {
53308  prediction128 = _mm_xor_si128(prediction128, prediction128);
53309  switch (order)
53310  {
53311  case 12:
53312  case 11: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(1, 1, 0, 0)), _mm_shuffle_epi32(samples128_8, _MM_SHUFFLE(1, 1, 0, 0))));
53313  case 10:
53314  case 9: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(3, 3, 2, 2)), _mm_shuffle_epi32(samples128_8, _MM_SHUFFLE(3, 3, 2, 2))));
53315  case 8:
53316  case 7: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(1, 1, 0, 0)), _mm_shuffle_epi32(samples128_4, _MM_SHUFFLE(1, 1, 0, 0))));
53317  case 6:
53318  case 5: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(3, 3, 2, 2)), _mm_shuffle_epi32(samples128_4, _MM_SHUFFLE(3, 3, 2, 2))));
53319  case 4:
53320  case 3: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(1, 1, 0, 0)), _mm_shuffle_epi32(samples128_0, _MM_SHUFFLE(1, 1, 0, 0))));
53321  case 2:
53322  case 1: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(3, 3, 2, 2)), _mm_shuffle_epi32(samples128_0, _MM_SHUFFLE(3, 3, 2, 2))));
53323  }
53324  prediction128 = drflac__mm_hadd_epi64(prediction128);
53325  prediction128 = drflac__mm_srai_epi64(prediction128, shift);
53326  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
53327  samples128_8 = _mm_alignr_epi8(samples128_4, samples128_8, 4);
53328  samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
53329  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
53330  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
53331  }
53332  _mm_storeu_si128((__m128i*)pDecodedSamples, samples128_0);
53333  pDecodedSamples += 4;
53334  }
53335  i = (count & ~3);
53336  while (i < (int)count) {
53337  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0)) {
53338  return DRFLAC_FALSE;
53339  }
53340  riceParamParts0 &= riceParamMask;
53341  riceParamParts0 |= (zeroCountParts0 << riceParam);
53342  riceParamParts0 = (riceParamParts0 >> 1) ^ t[riceParamParts0 & 0x01];
53343  pDecodedSamples[0] = riceParamParts0 + drflac__calculate_prediction_64(order, shift, coefficients, pDecodedSamples);
53344  i += 1;
53345  pDecodedSamples += 1;
53346  }
53347  return DRFLAC_TRUE;
53348 }
53349 static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53350 {
53351  DRFLAC_ASSERT(bs != NULL);
53352  DRFLAC_ASSERT(pSamplesOut != NULL);
53353  if (order > 0 && order <= 12) {
53354  if (bitsPerSample+shift > 32) {
53355  return drflac__decode_samples_with_residual__rice__sse41_64(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
53356  } else {
53357  return drflac__decode_samples_with_residual__rice__sse41_32(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
53358  }
53359  } else {
53360  return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
53361  }
53362 }
53363 #endif
53364 #if defined(DRFLAC_SUPPORT_NEON)
53365 static DRFLAC_INLINE void drflac__vst2q_s32(drflac_int32* p, int32x4x2_t x)
53366 {
53367  vst1q_s32(p+0, x.val[0]);
53368  vst1q_s32(p+4, x.val[1]);
53369 }
53370 static DRFLAC_INLINE void drflac__vst2q_u32(drflac_uint32* p, uint32x4x2_t x)
53371 {
53372  vst1q_u32(p+0, x.val[0]);
53373  vst1q_u32(p+4, x.val[1]);
53374 }
53375 static DRFLAC_INLINE void drflac__vst2q_f32(float* p, float32x4x2_t x)
53376 {
53377  vst1q_f32(p+0, x.val[0]);
53378  vst1q_f32(p+4, x.val[1]);
53379 }
53380 static DRFLAC_INLINE void drflac__vst2q_s16(drflac_int16* p, int16x4x2_t x)
53381 {
53382  vst1q_s16(p, vcombine_s16(x.val[0], x.val[1]));
53383 }
53384 static DRFLAC_INLINE void drflac__vst2q_u16(drflac_uint16* p, uint16x4x2_t x)
53385 {
53386  vst1q_u16(p, vcombine_u16(x.val[0], x.val[1]));
53387 }
53388 static DRFLAC_INLINE int32x4_t drflac__vdupq_n_s32x4(drflac_int32 x3, drflac_int32 x2, drflac_int32 x1, drflac_int32 x0)
53389 {
53390  drflac_int32 x[4];
53391  x[3] = x3;
53392  x[2] = x2;
53393  x[1] = x1;
53394  x[0] = x0;
53395  return vld1q_s32(x);
53396 }
53397 static DRFLAC_INLINE int32x4_t drflac__valignrq_s32_1(int32x4_t a, int32x4_t b)
53398 {
53399  return vextq_s32(b, a, 1);
53400 }
53401 static DRFLAC_INLINE uint32x4_t drflac__valignrq_u32_1(uint32x4_t a, uint32x4_t b)
53402 {
53403  return vextq_u32(b, a, 1);
53404 }
53405 static DRFLAC_INLINE int32x2_t drflac__vhaddq_s32(int32x4_t x)
53406 {
53407  int32x2_t r = vadd_s32(vget_high_s32(x), vget_low_s32(x));
53408  return vpadd_s32(r, r);
53409 }
53410 static DRFLAC_INLINE int64x1_t drflac__vhaddq_s64(int64x2_t x)
53411 {
53412  return vadd_s64(vget_high_s64(x), vget_low_s64(x));
53413 }
53414 static DRFLAC_INLINE int32x4_t drflac__vrevq_s32(int32x4_t x)
53415 {
53416  return vrev64q_s32(vcombine_s32(vget_high_s32(x), vget_low_s32(x)));
53417 }
53418 static DRFLAC_INLINE int32x4_t drflac__vnotq_s32(int32x4_t x)
53419 {
53420  return veorq_s32(x, vdupq_n_s32(0xFFFFFFFF));
53421 }
53422 static DRFLAC_INLINE uint32x4_t drflac__vnotq_u32(uint32x4_t x)
53423 {
53424  return veorq_u32(x, vdupq_n_u32(0xFFFFFFFF));
53425 }
53426 static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_32(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53427 {
53428  int i;
53429  drflac_uint32 riceParamMask;
53430  drflac_int32* pDecodedSamples = pSamplesOut;
53431  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
53432  drflac_uint32 zeroCountParts[4];
53433  drflac_uint32 riceParamParts[4];
53434  int32x4_t coefficients128_0;
53435  int32x4_t coefficients128_4;
53436  int32x4_t coefficients128_8;
53437  int32x4_t samples128_0;
53438  int32x4_t samples128_4;
53439  int32x4_t samples128_8;
53440  uint32x4_t riceParamMask128;
53441  int32x4_t riceParam128;
53442  int32x2_t shift64;
53443  uint32x4_t one128;
53444  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
53445  riceParamMask = ~((~0UL) << riceParam);
53446  riceParamMask128 = vdupq_n_u32(riceParamMask);
53447  riceParam128 = vdupq_n_s32(riceParam);
53448  shift64 = vdup_n_s32(-shift);
53449  one128 = vdupq_n_u32(1);
53450  {
53451  int runningOrder = order;
53452  drflac_int32 tempC[4] = {0, 0, 0, 0};
53453  drflac_int32 tempS[4] = {0, 0, 0, 0};
53454  if (runningOrder >= 4) {
53455  coefficients128_0 = vld1q_s32(coefficients + 0);
53456  samples128_0 = vld1q_s32(pSamplesOut - 4);
53457  runningOrder -= 4;
53458  } else {
53459  switch (runningOrder) {
53460  case 3: tempC[2] = coefficients[2]; tempS[1] = pSamplesOut[-3];
53461  case 2: tempC[1] = coefficients[1]; tempS[2] = pSamplesOut[-2];
53462  case 1: tempC[0] = coefficients[0]; tempS[3] = pSamplesOut[-1];
53463  }
53464  coefficients128_0 = vld1q_s32(tempC);
53465  samples128_0 = vld1q_s32(tempS);
53466  runningOrder = 0;
53467  }
53468  if (runningOrder >= 4) {
53469  coefficients128_4 = vld1q_s32(coefficients + 4);
53470  samples128_4 = vld1q_s32(pSamplesOut - 8);
53471  runningOrder -= 4;
53472  } else {
53473  switch (runningOrder) {
53474  case 3: tempC[2] = coefficients[6]; tempS[1] = pSamplesOut[-7];
53475  case 2: tempC[1] = coefficients[5]; tempS[2] = pSamplesOut[-6];
53476  case 1: tempC[0] = coefficients[4]; tempS[3] = pSamplesOut[-5];
53477  }
53478  coefficients128_4 = vld1q_s32(tempC);
53479  samples128_4 = vld1q_s32(tempS);
53480  runningOrder = 0;
53481  }
53482  if (runningOrder == 4) {
53483  coefficients128_8 = vld1q_s32(coefficients + 8);
53484  samples128_8 = vld1q_s32(pSamplesOut - 12);
53485  runningOrder -= 4;
53486  } else {
53487  switch (runningOrder) {
53488  case 3: tempC[2] = coefficients[10]; tempS[1] = pSamplesOut[-11];
53489  case 2: tempC[1] = coefficients[ 9]; tempS[2] = pSamplesOut[-10];
53490  case 1: tempC[0] = coefficients[ 8]; tempS[3] = pSamplesOut[- 9];
53491  }
53492  coefficients128_8 = vld1q_s32(tempC);
53493  samples128_8 = vld1q_s32(tempS);
53494  runningOrder = 0;
53495  }
53496  coefficients128_0 = drflac__vrevq_s32(coefficients128_0);
53497  coefficients128_4 = drflac__vrevq_s32(coefficients128_4);
53498  coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
53499  }
53500  while (pDecodedSamples < pDecodedSamplesEnd) {
53501  int32x4_t prediction128;
53502  int32x2_t prediction64;
53503  uint32x4_t zeroCountPart128;
53504  uint32x4_t riceParamPart128;
53505  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
53506  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
53507  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
53508  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
53509  return DRFLAC_FALSE;
53510  }
53511  zeroCountPart128 = vld1q_u32(zeroCountParts);
53512  riceParamPart128 = vld1q_u32(riceParamParts);
53513  riceParamPart128 = vandq_u32(riceParamPart128, riceParamMask128);
53514  riceParamPart128 = vorrq_u32(riceParamPart128, vshlq_u32(zeroCountPart128, riceParam128));
53515  riceParamPart128 = veorq_u32(vshrq_n_u32(riceParamPart128, 1), vaddq_u32(drflac__vnotq_u32(vandq_u32(riceParamPart128, one128)), one128));
53516  if (order <= 4) {
53517  for (i = 0; i < 4; i += 1) {
53518  prediction128 = vmulq_s32(coefficients128_0, samples128_0);
53519  prediction64 = drflac__vhaddq_s32(prediction128);
53520  prediction64 = vshl_s32(prediction64, shift64);
53521  prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
53522  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
53523  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
53524  }
53525  } else if (order <= 8) {
53526  for (i = 0; i < 4; i += 1) {
53527  prediction128 = vmulq_s32(coefficients128_4, samples128_4);
53528  prediction128 = vmlaq_s32(prediction128, coefficients128_0, samples128_0);
53529  prediction64 = drflac__vhaddq_s32(prediction128);
53530  prediction64 = vshl_s32(prediction64, shift64);
53531  prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
53532  samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
53533  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
53534  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
53535  }
53536  } else {
53537  for (i = 0; i < 4; i += 1) {
53538  prediction128 = vmulq_s32(coefficients128_8, samples128_8);
53539  prediction128 = vmlaq_s32(prediction128, coefficients128_4, samples128_4);
53540  prediction128 = vmlaq_s32(prediction128, coefficients128_0, samples128_0);
53541  prediction64 = drflac__vhaddq_s32(prediction128);
53542  prediction64 = vshl_s32(prediction64, shift64);
53543  prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
53544  samples128_8 = drflac__valignrq_s32_1(samples128_4, samples128_8);
53545  samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
53546  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
53547  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
53548  }
53549  }
53550  vst1q_s32(pDecodedSamples, samples128_0);
53551  pDecodedSamples += 4;
53552  }
53553  i = (count & ~3);
53554  while (i < (int)count) {
53555  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0])) {
53556  return DRFLAC_FALSE;
53557  }
53558  riceParamParts[0] &= riceParamMask;
53559  riceParamParts[0] |= (zeroCountParts[0] << riceParam);
53560  riceParamParts[0] = (riceParamParts[0] >> 1) ^ t[riceParamParts[0] & 0x01];
53561  pDecodedSamples[0] = riceParamParts[0] + drflac__calculate_prediction_32(order, shift, coefficients, pDecodedSamples);
53562  i += 1;
53563  pDecodedSamples += 1;
53564  }
53565  return DRFLAC_TRUE;
53566 }
53567 static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_64(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53568 {
53569  int i;
53570  drflac_uint32 riceParamMask;
53571  drflac_int32* pDecodedSamples = pSamplesOut;
53572  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
53573  drflac_uint32 zeroCountParts[4];
53574  drflac_uint32 riceParamParts[4];
53575  int32x4_t coefficients128_0;
53576  int32x4_t coefficients128_4;
53577  int32x4_t coefficients128_8;
53578  int32x4_t samples128_0;
53579  int32x4_t samples128_4;
53580  int32x4_t samples128_8;
53581  uint32x4_t riceParamMask128;
53582  int32x4_t riceParam128;
53583  int64x1_t shift64;
53584  uint32x4_t one128;
53585  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
53586  riceParamMask = ~((~0UL) << riceParam);
53587  riceParamMask128 = vdupq_n_u32(riceParamMask);
53588  riceParam128 = vdupq_n_s32(riceParam);
53589  shift64 = vdup_n_s64(-shift);
53590  one128 = vdupq_n_u32(1);
53591  {
53592  int runningOrder = order;
53593  drflac_int32 tempC[4] = {0, 0, 0, 0};
53594  drflac_int32 tempS[4] = {0, 0, 0, 0};
53595  if (runningOrder >= 4) {
53596  coefficients128_0 = vld1q_s32(coefficients + 0);
53597  samples128_0 = vld1q_s32(pSamplesOut - 4);
53598  runningOrder -= 4;
53599  } else {
53600  switch (runningOrder) {
53601  case 3: tempC[2] = coefficients[2]; tempS[1] = pSamplesOut[-3];
53602  case 2: tempC[1] = coefficients[1]; tempS[2] = pSamplesOut[-2];
53603  case 1: tempC[0] = coefficients[0]; tempS[3] = pSamplesOut[-1];
53604  }
53605  coefficients128_0 = vld1q_s32(tempC);
53606  samples128_0 = vld1q_s32(tempS);
53607  runningOrder = 0;
53608  }
53609  if (runningOrder >= 4) {
53610  coefficients128_4 = vld1q_s32(coefficients + 4);
53611  samples128_4 = vld1q_s32(pSamplesOut - 8);
53612  runningOrder -= 4;
53613  } else {
53614  switch (runningOrder) {
53615  case 3: tempC[2] = coefficients[6]; tempS[1] = pSamplesOut[-7];
53616  case 2: tempC[1] = coefficients[5]; tempS[2] = pSamplesOut[-6];
53617  case 1: tempC[0] = coefficients[4]; tempS[3] = pSamplesOut[-5];
53618  }
53619  coefficients128_4 = vld1q_s32(tempC);
53620  samples128_4 = vld1q_s32(tempS);
53621  runningOrder = 0;
53622  }
53623  if (runningOrder == 4) {
53624  coefficients128_8 = vld1q_s32(coefficients + 8);
53625  samples128_8 = vld1q_s32(pSamplesOut - 12);
53626  runningOrder -= 4;
53627  } else {
53628  switch (runningOrder) {
53629  case 3: tempC[2] = coefficients[10]; tempS[1] = pSamplesOut[-11];
53630  case 2: tempC[1] = coefficients[ 9]; tempS[2] = pSamplesOut[-10];
53631  case 1: tempC[0] = coefficients[ 8]; tempS[3] = pSamplesOut[- 9];
53632  }
53633  coefficients128_8 = vld1q_s32(tempC);
53634  samples128_8 = vld1q_s32(tempS);
53635  runningOrder = 0;
53636  }
53637  coefficients128_0 = drflac__vrevq_s32(coefficients128_0);
53638  coefficients128_4 = drflac__vrevq_s32(coefficients128_4);
53639  coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
53640  }
53641  while (pDecodedSamples < pDecodedSamplesEnd) {
53642  int64x2_t prediction128;
53643  uint32x4_t zeroCountPart128;
53644  uint32x4_t riceParamPart128;
53645  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
53646  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
53647  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
53648  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
53649  return DRFLAC_FALSE;
53650  }
53651  zeroCountPart128 = vld1q_u32(zeroCountParts);
53652  riceParamPart128 = vld1q_u32(riceParamParts);
53653  riceParamPart128 = vandq_u32(riceParamPart128, riceParamMask128);
53654  riceParamPart128 = vorrq_u32(riceParamPart128, vshlq_u32(zeroCountPart128, riceParam128));
53655  riceParamPart128 = veorq_u32(vshrq_n_u32(riceParamPart128, 1), vaddq_u32(drflac__vnotq_u32(vandq_u32(riceParamPart128, one128)), one128));
53656  for (i = 0; i < 4; i += 1) {
53657  int64x1_t prediction64;
53658  prediction128 = veorq_s64(prediction128, prediction128);
53659  switch (order)
53660  {
53661  case 12:
53662  case 11: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_8), vget_low_s32(samples128_8)));
53663  case 10:
53664  case 9: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_8), vget_high_s32(samples128_8)));
53665  case 8:
53666  case 7: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_4), vget_low_s32(samples128_4)));
53667  case 6:
53668  case 5: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_4), vget_high_s32(samples128_4)));
53669  case 4:
53670  case 3: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_0), vget_low_s32(samples128_0)));
53671  case 2:
53672  case 1: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_0), vget_high_s32(samples128_0)));
53673  }
53674  prediction64 = drflac__vhaddq_s64(prediction128);
53675  prediction64 = vshl_s64(prediction64, shift64);
53676  prediction64 = vadd_s64(prediction64, vdup_n_s64(vgetq_lane_u32(riceParamPart128, 0)));
53677  samples128_8 = drflac__valignrq_s32_1(samples128_4, samples128_8);
53678  samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
53679  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(vreinterpret_s32_s64(prediction64), vdup_n_s32(0)), samples128_0);
53680  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
53681  }
53682  vst1q_s32(pDecodedSamples, samples128_0);
53683  pDecodedSamples += 4;
53684  }
53685  i = (count & ~3);
53686  while (i < (int)count) {
53687  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0])) {
53688  return DRFLAC_FALSE;
53689  }
53690  riceParamParts[0] &= riceParamMask;
53691  riceParamParts[0] |= (zeroCountParts[0] << riceParam);
53692  riceParamParts[0] = (riceParamParts[0] >> 1) ^ t[riceParamParts[0] & 0x01];
53693  pDecodedSamples[0] = riceParamParts[0] + drflac__calculate_prediction_64(order, shift, coefficients, pDecodedSamples);
53694  i += 1;
53695  pDecodedSamples += 1;
53696  }
53697  return DRFLAC_TRUE;
53698 }
53699 static drflac_bool32 drflac__decode_samples_with_residual__rice__neon(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53700 {
53701  DRFLAC_ASSERT(bs != NULL);
53702  DRFLAC_ASSERT(pSamplesOut != NULL);
53703  if (order > 0 && order <= 12) {
53704  if (bitsPerSample+shift > 32) {
53705  return drflac__decode_samples_with_residual__rice__neon_64(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
53706  } else {
53707  return drflac__decode_samples_with_residual__rice__neon_32(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
53708  }
53709  } else {
53710  return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
53711  }
53712 }
53713 #endif
53715 {
53716 #if defined(DRFLAC_SUPPORT_SSE41)
53717  if (drflac__gIsSSE41Supported) {
53718  return drflac__decode_samples_with_residual__rice__sse41(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
53719  } else
53720 #elif defined(DRFLAC_SUPPORT_NEON)
53722  return drflac__decode_samples_with_residual__rice__neon(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
53723  } else
53724 #endif
53725  {
53726  #if 0
53727  return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
53728  #else
53729  return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
53730  #endif
53731  }
53732 }
53734 {
53735  drflac_uint32 i;
53736  DRFLAC_ASSERT(bs != NULL);
53737  for (i = 0; i < count; ++i) {
53738  if (!drflac__seek_rice_parts(bs, riceParam)) {
53739  return DRFLAC_FALSE;
53740  }
53741  }
53742  return DRFLAC_TRUE;
53743 }
53744 static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 unencodedBitsPerSample, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
53745 {
53746  drflac_uint32 i;
53747  DRFLAC_ASSERT(bs != NULL);
53748  DRFLAC_ASSERT(unencodedBitsPerSample <= 31);
53749  DRFLAC_ASSERT(pSamplesOut != NULL);
53750  for (i = 0; i < count; ++i) {
53751  if (unencodedBitsPerSample > 0) {
53752  if (!drflac__read_int32(bs, unencodedBitsPerSample, pSamplesOut + i)) {
53753  return DRFLAC_FALSE;
53754  }
53755  } else {
53756  pSamplesOut[i] = 0;
53757  }
53758  if (bitsPerSample >= 24) {
53759  pSamplesOut[i] += drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
53760  } else {
53761  pSamplesOut[i] += drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i);
53762  }
53763  }
53764  return DRFLAC_TRUE;
53765 }
53766 static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 blockSize, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
53767 {
53768  drflac_uint8 residualMethod;
53769  drflac_uint8 partitionOrder;
53770  drflac_uint32 samplesInPartition;
53771  drflac_uint32 partitionsRemaining;
53772  DRFLAC_ASSERT(bs != NULL);
53773  DRFLAC_ASSERT(blockSize != 0);
53774  DRFLAC_ASSERT(pDecodedSamples != NULL);
53775  if (!drflac__read_uint8(bs, 2, &residualMethod)) {
53776  return DRFLAC_FALSE;
53777  }
53779  return DRFLAC_FALSE;
53780  }
53781  pDecodedSamples += order;
53782  if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
53783  return DRFLAC_FALSE;
53784  }
53785  if (partitionOrder > 8) {
53786  return DRFLAC_FALSE;
53787  }
53788  if ((blockSize / (1 << partitionOrder)) < order) {
53789  return DRFLAC_FALSE;
53790  }
53791  samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
53792  partitionsRemaining = (1 << partitionOrder);
53793  for (;;) {
53794  drflac_uint8 riceParam = 0;
53795  if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) {
53796  if (!drflac__read_uint8(bs, 4, &riceParam)) {
53797  return DRFLAC_FALSE;
53798  }
53799  if (riceParam == 15) {
53800  riceParam = 0xFF;
53801  }
53802  } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
53803  if (!drflac__read_uint8(bs, 5, &riceParam)) {
53804  return DRFLAC_FALSE;
53805  }
53806  if (riceParam == 31) {
53807  riceParam = 0xFF;
53808  }
53809  }
53810  if (riceParam != 0xFF) {
53811  if (!drflac__decode_samples_with_residual__rice(bs, bitsPerSample, samplesInPartition, riceParam, order, shift, coefficients, pDecodedSamples)) {
53812  return DRFLAC_FALSE;
53813  }
53814  } else {
53815  drflac_uint8 unencodedBitsPerSample = 0;
53816  if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) {
53817  return DRFLAC_FALSE;
53818  }
53819  if (!drflac__decode_samples_with_residual__unencoded(bs, bitsPerSample, samplesInPartition, unencodedBitsPerSample, order, shift, coefficients, pDecodedSamples)) {
53820  return DRFLAC_FALSE;
53821  }
53822  }
53823  pDecodedSamples += samplesInPartition;
53824  if (partitionsRemaining == 1) {
53825  break;
53826  }
53827  partitionsRemaining -= 1;
53828  if (partitionOrder != 0) {
53829  samplesInPartition = blockSize / (1 << partitionOrder);
53830  }
53831  }
53832  return DRFLAC_TRUE;
53833 }
53835 {
53836  drflac_uint8 residualMethod;
53837  drflac_uint8 partitionOrder;
53838  drflac_uint32 samplesInPartition;
53839  drflac_uint32 partitionsRemaining;
53840  DRFLAC_ASSERT(bs != NULL);
53841  DRFLAC_ASSERT(blockSize != 0);
53842  if (!drflac__read_uint8(bs, 2, &residualMethod)) {
53843  return DRFLAC_FALSE;
53844  }
53846  return DRFLAC_FALSE;
53847  }
53848  if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
53849  return DRFLAC_FALSE;
53850  }
53851  if (partitionOrder > 8) {
53852  return DRFLAC_FALSE;
53853  }
53854  if ((blockSize / (1 << partitionOrder)) <= order) {
53855  return DRFLAC_FALSE;
53856  }
53857  samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
53858  partitionsRemaining = (1 << partitionOrder);
53859  for (;;)
53860  {
53861  drflac_uint8 riceParam = 0;
53862  if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) {
53863  if (!drflac__read_uint8(bs, 4, &riceParam)) {
53864  return DRFLAC_FALSE;
53865  }
53866  if (riceParam == 15) {
53867  riceParam = 0xFF;
53868  }
53869  } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
53870  if (!drflac__read_uint8(bs, 5, &riceParam)) {
53871  return DRFLAC_FALSE;
53872  }
53873  if (riceParam == 31) {
53874  riceParam = 0xFF;
53875  }
53876  }
53877  if (riceParam != 0xFF) {
53878  if (!drflac__read_and_seek_residual__rice(bs, samplesInPartition, riceParam)) {
53879  return DRFLAC_FALSE;
53880  }
53881  } else {
53882  drflac_uint8 unencodedBitsPerSample = 0;
53883  if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) {
53884  return DRFLAC_FALSE;
53885  }
53886  if (!drflac__seek_bits(bs, unencodedBitsPerSample * samplesInPartition)) {
53887  return DRFLAC_FALSE;
53888  }
53889  }
53890  if (partitionsRemaining == 1) {
53891  break;
53892  }
53893  partitionsRemaining -= 1;
53894  samplesInPartition = blockSize / (1 << partitionOrder);
53895  }
53896  return DRFLAC_TRUE;
53897 }
53898 static drflac_bool32 drflac__decode_samples__constant(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32* pDecodedSamples)
53899 {
53900  drflac_uint32 i;
53901  drflac_int32 sample;
53902  if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
53903  return DRFLAC_FALSE;
53904  }
53905  for (i = 0; i < blockSize; ++i) {
53906  pDecodedSamples[i] = sample;
53907  }
53908  return DRFLAC_TRUE;
53909 }
53910 static drflac_bool32 drflac__decode_samples__verbatim(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32* pDecodedSamples)
53911 {
53912  drflac_uint32 i;
53913  for (i = 0; i < blockSize; ++i) {
53914  drflac_int32 sample;
53915  if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
53916  return DRFLAC_FALSE;
53917  }
53918  pDecodedSamples[i] = sample;
53919  }
53920  return DRFLAC_TRUE;
53921 }
53922 static drflac_bool32 drflac__decode_samples__fixed(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples)
53923 {
53924  drflac_uint32 i;
53925  static drflac_int32 lpcCoefficientsTable[5][4] = {
53926  {0, 0, 0, 0},
53927  {1, 0, 0, 0},
53928  {2, -1, 0, 0},
53929  {3, -3, 1, 0},
53930  {4, -6, 4, -1}
53931  };
53932  for (i = 0; i < lpcOrder; ++i) {
53933  drflac_int32 sample;
53934  if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
53935  return DRFLAC_FALSE;
53936  }
53937  pDecodedSamples[i] = sample;
53938  }
53939  if (!drflac__decode_samples_with_residual(bs, subframeBitsPerSample, blockSize, lpcOrder, 0, lpcCoefficientsTable[lpcOrder], pDecodedSamples)) {
53940  return DRFLAC_FALSE;
53941  }
53942  return DRFLAC_TRUE;
53943 }
53944 static drflac_bool32 drflac__decode_samples__lpc(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples)
53945 {
53946  drflac_uint8 i;
53947  drflac_uint8 lpcPrecision;
53948  drflac_int8 lpcShift;
53949  drflac_int32 coefficients[32];
53950  for (i = 0; i < lpcOrder; ++i) {
53951  drflac_int32 sample;
53952  if (!drflac__read_int32(bs, bitsPerSample, &sample)) {
53953  return DRFLAC_FALSE;
53954  }
53955  pDecodedSamples[i] = sample;
53956  }
53957  if (!drflac__read_uint8(bs, 4, &lpcPrecision)) {
53958  return DRFLAC_FALSE;
53959  }
53960  if (lpcPrecision == 15) {
53961  return DRFLAC_FALSE;
53962  }
53963  lpcPrecision += 1;
53964  if (!drflac__read_int8(bs, 5, &lpcShift)) {
53965  return DRFLAC_FALSE;
53966  }
53967  if (lpcShift < 0) {
53968  return DRFLAC_FALSE;
53969  }
53970  DRFLAC_ZERO_MEMORY(coefficients, sizeof(coefficients));
53971  for (i = 0; i < lpcOrder; ++i) {
53972  if (!drflac__read_int32(bs, lpcPrecision, coefficients + i)) {
53973  return DRFLAC_FALSE;
53974  }
53975  }
53976  if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, lpcShift, coefficients, pDecodedSamples)) {
53977  return DRFLAC_FALSE;
53978  }
53979  return DRFLAC_TRUE;
53980 }
53982 {
53983  const drflac_uint32 sampleRateTable[12] = {0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
53984  const drflac_uint8 bitsPerSampleTable[8] = {0, 8, 12, (drflac_uint8)-1, 16, 20, 24, (drflac_uint8)-1};
53985  DRFLAC_ASSERT(bs != NULL);
53987  for (;;) {
53988  drflac_uint8 crc8 = 0xCE;
53989  drflac_uint8 reserved = 0;
53990  drflac_uint8 blockingStrategy = 0;
53991  drflac_uint8 blockSize = 0;
53992  drflac_uint8 sampleRate = 0;
53993  drflac_uint8 channelAssignment = 0;
53994  drflac_uint8 bitsPerSample = 0;
53995  drflac_bool32 isVariableBlockSize;
53997  return DRFLAC_FALSE;
53998  }
53999  if (!drflac__read_uint8(bs, 1, &reserved)) {
54000  return DRFLAC_FALSE;
54001  }
54002  if (reserved == 1) {
54003  continue;
54004  }
54005  crc8 = drflac_crc8(crc8, reserved, 1);
54006  if (!drflac__read_uint8(bs, 1, &blockingStrategy)) {
54007  return DRFLAC_FALSE;
54008  }
54009  crc8 = drflac_crc8(crc8, blockingStrategy, 1);
54010  if (!drflac__read_uint8(bs, 4, &blockSize)) {
54011  return DRFLAC_FALSE;
54012  }
54013  if (blockSize == 0) {
54014  continue;
54015  }
54016  crc8 = drflac_crc8(crc8, blockSize, 4);
54017  if (!drflac__read_uint8(bs, 4, &sampleRate)) {
54018  return DRFLAC_FALSE;
54019  }
54020  crc8 = drflac_crc8(crc8, sampleRate, 4);
54021  if (!drflac__read_uint8(bs, 4, &channelAssignment)) {
54022  return DRFLAC_FALSE;
54023  }
54024  if (channelAssignment > 10) {
54025  continue;
54026  }
54027  crc8 = drflac_crc8(crc8, channelAssignment, 4);
54028  if (!drflac__read_uint8(bs, 3, &bitsPerSample)) {
54029  return DRFLAC_FALSE;
54030  }
54031  if (bitsPerSample == 3 || bitsPerSample == 7) {
54032  continue;
54033  }
54034  crc8 = drflac_crc8(crc8, bitsPerSample, 3);
54035  if (!drflac__read_uint8(bs, 1, &reserved)) {
54036  return DRFLAC_FALSE;
54037  }
54038  if (reserved == 1) {
54039  continue;
54040  }
54041  crc8 = drflac_crc8(crc8, reserved, 1);
54042  isVariableBlockSize = blockingStrategy == 1;
54043  if (isVariableBlockSize) {
54044  drflac_uint64 pcmFrameNumber;
54045  drflac_result result = drflac__read_utf8_coded_number(bs, &pcmFrameNumber, &crc8);
54046  if (result != DRFLAC_SUCCESS) {
54047  if (result == DRFLAC_AT_END) {
54048  return DRFLAC_FALSE;
54049  } else {
54050  continue;
54051  }
54052  }
54053  header->flacFrameNumber = 0;
54054  header->pcmFrameNumber = pcmFrameNumber;
54055  } else {
54056  drflac_uint64 flacFrameNumber = 0;
54057  drflac_result result = drflac__read_utf8_coded_number(bs, &flacFrameNumber, &crc8);
54058  if (result != DRFLAC_SUCCESS) {
54059  if (result == DRFLAC_AT_END) {
54060  return DRFLAC_FALSE;
54061  } else {
54062  continue;
54063  }
54064  }
54065  header->flacFrameNumber = (drflac_uint32)flacFrameNumber;
54066  header->pcmFrameNumber = 0;
54067  }
54068  DRFLAC_ASSERT(blockSize > 0);
54069  if (blockSize == 1) {
54070  header->blockSizeInPCMFrames = 192;
54071  } else if (blockSize <= 5) {
54072  DRFLAC_ASSERT(blockSize >= 2);
54073  header->blockSizeInPCMFrames = 576 * (1 << (blockSize - 2));
54074  } else if (blockSize == 6) {
54075  if (!drflac__read_uint16(bs, 8, &header->blockSizeInPCMFrames)) {
54076  return DRFLAC_FALSE;
54077  }
54078  crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 8);
54079  header->blockSizeInPCMFrames += 1;
54080  } else if (blockSize == 7) {
54081  if (!drflac__read_uint16(bs, 16, &header->blockSizeInPCMFrames)) {
54082  return DRFLAC_FALSE;
54083  }
54084  crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 16);
54085  header->blockSizeInPCMFrames += 1;
54086  } else {
54087  DRFLAC_ASSERT(blockSize >= 8);
54088  header->blockSizeInPCMFrames = 256 * (1 << (blockSize - 8));
54089  }
54090  if (sampleRate <= 11) {
54091  header->sampleRate = sampleRateTable[sampleRate];
54092  } else if (sampleRate == 12) {
54093  if (!drflac__read_uint32(bs, 8, &header->sampleRate)) {
54094  return DRFLAC_FALSE;
54095  }
54096  crc8 = drflac_crc8(crc8, header->sampleRate, 8);
54097  header->sampleRate *= 1000;
54098  } else if (sampleRate == 13) {
54099  if (!drflac__read_uint32(bs, 16, &header->sampleRate)) {
54100  return DRFLAC_FALSE;
54101  }
54102  crc8 = drflac_crc8(crc8, header->sampleRate, 16);
54103  } else if (sampleRate == 14) {
54104  if (!drflac__read_uint32(bs, 16, &header->sampleRate)) {
54105  return DRFLAC_FALSE;
54106  }
54107  crc8 = drflac_crc8(crc8, header->sampleRate, 16);
54108  header->sampleRate *= 10;
54109  } else {
54110  continue;
54111  }
54112  header->channelAssignment = channelAssignment;
54113  header->bitsPerSample = bitsPerSampleTable[bitsPerSample];
54114  if (header->bitsPerSample == 0) {
54115  header->bitsPerSample = streaminfoBitsPerSample;
54116  }
54117  if (!drflac__read_uint8(bs, 8, &header->crc8)) {
54118  return DRFLAC_FALSE;
54119  }
54120 #ifndef DR_FLAC_NO_CRC
54121  if (header->crc8 != crc8) {
54122  continue;
54123  }
54124 #endif
54125  return DRFLAC_TRUE;
54126  }
54127 }
54129 {
54131  int type;
54132  if (!drflac__read_uint8(bs, 8, &header)) {
54133  return DRFLAC_FALSE;
54134  }
54135  if ((header & 0x80) != 0) {
54136  return DRFLAC_FALSE;
54137  }
54138  type = (header & 0x7E) >> 1;
54139  if (type == 0) {
54141  } else if (type == 1) {
54143  } else {
54144  if ((type & 0x20) != 0) {
54145  pSubframe->subframeType = DRFLAC_SUBFRAME_LPC;
54146  pSubframe->lpcOrder = (drflac_uint8)(type & 0x1F) + 1;
54147  } else if ((type & 0x08) != 0) {
54148  pSubframe->subframeType = DRFLAC_SUBFRAME_FIXED;
54149  pSubframe->lpcOrder = (drflac_uint8)(type & 0x07);
54150  if (pSubframe->lpcOrder > 4) {
54152  pSubframe->lpcOrder = 0;
54153  }
54154  } else {
54156  }
54157  }
54158  if (pSubframe->subframeType == DRFLAC_SUBFRAME_RESERVED) {
54159  return DRFLAC_FALSE;
54160  }
54161  pSubframe->wastedBitsPerSample = 0;
54162  if ((header & 0x01) == 1) {
54163  unsigned int wastedBitsPerSample;
54164  if (!drflac__seek_past_next_set_bit(bs, &wastedBitsPerSample)) {
54165  return DRFLAC_FALSE;
54166  }
54167  pSubframe->wastedBitsPerSample = (drflac_uint8)wastedBitsPerSample + 1;
54168  }
54169  return DRFLAC_TRUE;
54170 }
54171 static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex, drflac_int32* pDecodedSamplesOut)
54172 {
54173  drflac_subframe* pSubframe;
54174  drflac_uint32 subframeBitsPerSample;
54175  DRFLAC_ASSERT(bs != NULL);
54176  DRFLAC_ASSERT(frame != NULL);
54177  pSubframe = frame->subframes + subframeIndex;
54178  if (!drflac__read_subframe_header(bs, pSubframe)) {
54179  return DRFLAC_FALSE;
54180  }
54181  subframeBitsPerSample = frame->header.bitsPerSample;
54183  subframeBitsPerSample += 1;
54184  } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) {
54185  subframeBitsPerSample += 1;
54186  }
54187  if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
54188  return DRFLAC_FALSE;
54189  }
54190  subframeBitsPerSample -= pSubframe->wastedBitsPerSample;
54191  pSubframe->pSamplesS32 = pDecodedSamplesOut;
54192  switch (pSubframe->subframeType)
54193  {
54195  {
54196  drflac__decode_samples__constant(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
54197  } break;
54199  {
54200  drflac__decode_samples__verbatim(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
54201  } break;
54202  case DRFLAC_SUBFRAME_FIXED:
54203  {
54204  drflac__decode_samples__fixed(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
54205  } break;
54206  case DRFLAC_SUBFRAME_LPC:
54207  {
54208  drflac__decode_samples__lpc(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
54209  } break;
54210  default: return DRFLAC_FALSE;
54211  }
54212  return DRFLAC_TRUE;
54213 }
54214 static drflac_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex)
54215 {
54216  drflac_subframe* pSubframe;
54217  drflac_uint32 subframeBitsPerSample;
54218  DRFLAC_ASSERT(bs != NULL);
54219  DRFLAC_ASSERT(frame != NULL);
54220  pSubframe = frame->subframes + subframeIndex;
54221  if (!drflac__read_subframe_header(bs, pSubframe)) {
54222  return DRFLAC_FALSE;
54223  }
54224  subframeBitsPerSample = frame->header.bitsPerSample;
54226  subframeBitsPerSample += 1;
54227  } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) {
54228  subframeBitsPerSample += 1;
54229  }
54230  if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
54231  return DRFLAC_FALSE;
54232  }
54233  subframeBitsPerSample -= pSubframe->wastedBitsPerSample;
54234  pSubframe->pSamplesS32 = NULL;
54235  switch (pSubframe->subframeType)
54236  {
54238  {
54239  if (!drflac__seek_bits(bs, subframeBitsPerSample)) {
54240  return DRFLAC_FALSE;
54241  }
54242  } break;
54244  {
54245  unsigned int bitsToSeek = frame->header.blockSizeInPCMFrames * subframeBitsPerSample;
54246  if (!drflac__seek_bits(bs, bitsToSeek)) {
54247  return DRFLAC_FALSE;
54248  }
54249  } break;
54250  case DRFLAC_SUBFRAME_FIXED:
54251  {
54252  unsigned int bitsToSeek = pSubframe->lpcOrder * subframeBitsPerSample;
54253  if (!drflac__seek_bits(bs, bitsToSeek)) {
54254  return DRFLAC_FALSE;
54255  }
54256  if (!drflac__read_and_seek_residual(bs, frame->header.blockSizeInPCMFrames, pSubframe->lpcOrder)) {
54257  return DRFLAC_FALSE;
54258  }
54259  } break;
54260  case DRFLAC_SUBFRAME_LPC:
54261  {
54262  drflac_uint8 lpcPrecision;
54263  unsigned int bitsToSeek = pSubframe->lpcOrder * subframeBitsPerSample;
54264  if (!drflac__seek_bits(bs, bitsToSeek)) {
54265  return DRFLAC_FALSE;
54266  }
54267  if (!drflac__read_uint8(bs, 4, &lpcPrecision)) {
54268  return DRFLAC_FALSE;
54269  }
54270  if (lpcPrecision == 15) {
54271  return DRFLAC_FALSE;
54272  }
54273  lpcPrecision += 1;
54274  bitsToSeek = (pSubframe->lpcOrder * lpcPrecision) + 5;
54275  if (!drflac__seek_bits(bs, bitsToSeek)) {
54276  return DRFLAC_FALSE;
54277  }
54278  if (!drflac__read_and_seek_residual(bs, frame->header.blockSizeInPCMFrames, pSubframe->lpcOrder)) {
54279  return DRFLAC_FALSE;
54280  }
54281  } break;
54282  default: return DRFLAC_FALSE;
54283  }
54284  return DRFLAC_TRUE;
54285 }
54287 {
54288  drflac_uint8 lookup[] = {1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2};
54289  DRFLAC_ASSERT(channelAssignment <= 10);
54290  return lookup[channelAssignment];
54291 }
54293 {
54294  int channelCount;
54295  int i;
54296  drflac_uint8 paddingSizeInBits;
54297  drflac_uint16 desiredCRC16;
54298 #ifndef DR_FLAC_NO_CRC
54299  drflac_uint16 actualCRC16;
54300 #endif
54303  return DRFLAC_ERROR;
54304  }
54306  if (channelCount != (int)pFlac->channels) {
54307  return DRFLAC_ERROR;
54308  }
54309  for (i = 0; i < channelCount; ++i) {
54310  if (!drflac__decode_subframe(&pFlac->bs, &pFlac->currentFLACFrame, i, pFlac->pDecodedSamples + (pFlac->currentFLACFrame.header.blockSizeInPCMFrames * i))) {
54311  return DRFLAC_ERROR;
54312  }
54313  }
54314  paddingSizeInBits = (drflac_uint8)(DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7);
54315  if (paddingSizeInBits > 0) {
54316  drflac_uint8 padding = 0;
54317  if (!drflac__read_uint8(&pFlac->bs, paddingSizeInBits, &padding)) {
54318  return DRFLAC_AT_END;
54319  }
54320  }
54321 #ifndef DR_FLAC_NO_CRC
54322  actualCRC16 = drflac__flush_crc16(&pFlac->bs);
54323 #endif
54324  if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) {
54325  return DRFLAC_AT_END;
54326  }
54327 #ifndef DR_FLAC_NO_CRC
54328  if (actualCRC16 != desiredCRC16) {
54329  return DRFLAC_CRC_MISMATCH;
54330  }
54331 #endif
54333  return DRFLAC_SUCCESS;
54334 }
54336 {
54337  int channelCount;
54338  int i;
54339  drflac_uint16 desiredCRC16;
54340 #ifndef DR_FLAC_NO_CRC
54341  drflac_uint16 actualCRC16;
54342 #endif
54344  for (i = 0; i < channelCount; ++i) {
54345  if (!drflac__seek_subframe(&pFlac->bs, &pFlac->currentFLACFrame, i)) {
54346  return DRFLAC_ERROR;
54347  }
54348  }
54349  if (!drflac__seek_bits(&pFlac->bs, DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7)) {
54350  return DRFLAC_ERROR;
54351  }
54352 #ifndef DR_FLAC_NO_CRC
54353  actualCRC16 = drflac__flush_crc16(&pFlac->bs);
54354 #endif
54355  if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) {
54356  return DRFLAC_AT_END;
54357  }
54358 #ifndef DR_FLAC_NO_CRC
54359  if (actualCRC16 != desiredCRC16) {
54360  return DRFLAC_CRC_MISMATCH;
54361  }
54362 #endif
54363  return DRFLAC_SUCCESS;
54364 }
54366 {
54367  DRFLAC_ASSERT(pFlac != NULL);
54368  for (;;) {
54369  drflac_result result;
54371  return DRFLAC_FALSE;
54372  }
54373  result = drflac__decode_flac_frame(pFlac);
54374  if (result != DRFLAC_SUCCESS) {
54375  if (result == DRFLAC_CRC_MISMATCH) {
54376  continue;
54377  } else {
54378  return DRFLAC_FALSE;
54379  }
54380  }
54381  return DRFLAC_TRUE;
54382  }
54383 }
54384 static void drflac__get_pcm_frame_range_of_current_flac_frame(drflac* pFlac, drflac_uint64* pFirstPCMFrame, drflac_uint64* pLastPCMFrame)
54385 {
54386  drflac_uint64 firstPCMFrame;
54387  drflac_uint64 lastPCMFrame;
54388  DRFLAC_ASSERT(pFlac != NULL);
54389  firstPCMFrame = pFlac->currentFLACFrame.header.pcmFrameNumber;
54390  if (firstPCMFrame == 0) {
54392  }
54393  lastPCMFrame = firstPCMFrame + pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
54394  if (lastPCMFrame > 0) {
54395  lastPCMFrame -= 1;
54396  }
54397  if (pFirstPCMFrame) {
54398  *pFirstPCMFrame = firstPCMFrame;
54399  }
54400  if (pLastPCMFrame) {
54401  *pLastPCMFrame = lastPCMFrame;
54402  }
54403 }
54405 {
54406  drflac_bool32 result;
54407  DRFLAC_ASSERT(pFlac != NULL);
54408  result = drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes);
54409  DRFLAC_ZERO_MEMORY(&pFlac->currentFLACFrame, sizeof(pFlac->currentFLACFrame));
54410  pFlac->currentPCMFrame = 0;
54411  return result;
54412 }
54414 {
54415  DRFLAC_ASSERT(pFlac != NULL);
54416  return drflac__seek_flac_frame(pFlac);
54417 }
54419 {
54420  drflac_uint64 pcmFramesRead = 0;
54421  while (pcmFramesToSeek > 0) {
54422  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
54424  break;
54425  }
54426  } else {
54427  if (pFlac->currentFLACFrame.pcmFramesRemaining > pcmFramesToSeek) {
54428  pcmFramesRead += pcmFramesToSeek;
54429  pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)pcmFramesToSeek;
54430  pcmFramesToSeek = 0;
54431  } else {
54432  pcmFramesRead += pFlac->currentFLACFrame.pcmFramesRemaining;
54433  pcmFramesToSeek -= pFlac->currentFLACFrame.pcmFramesRemaining;
54435  }
54436  }
54437  }
54438  pFlac->currentPCMFrame += pcmFramesRead;
54439  return pcmFramesRead;
54440 }
54442 {
54443  drflac_bool32 isMidFrame = DRFLAC_FALSE;
54444  drflac_uint64 runningPCMFrameCount;
54445  DRFLAC_ASSERT(pFlac != NULL);
54446  if (pcmFrameIndex >= pFlac->currentPCMFrame) {
54447  runningPCMFrameCount = pFlac->currentPCMFrame;
54448  if (pFlac->currentPCMFrame == 0 && pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
54450  return DRFLAC_FALSE;
54451  }
54452  } else {
54453  isMidFrame = DRFLAC_TRUE;
54454  }
54455  } else {
54456  runningPCMFrameCount = 0;
54457  if (!drflac__seek_to_first_frame(pFlac)) {
54458  return DRFLAC_FALSE;
54459  }
54461  return DRFLAC_FALSE;
54462  }
54463  }
54464  for (;;) {
54465  drflac_uint64 pcmFrameCountInThisFLACFrame;
54466  drflac_uint64 firstPCMFrameInFLACFrame = 0;
54467  drflac_uint64 lastPCMFrameInFLACFrame = 0;
54468  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
54469  pcmFrameCountInThisFLACFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
54470  if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFLACFrame)) {
54471  drflac_uint64 pcmFramesToDecode = pcmFrameIndex - runningPCMFrameCount;
54472  if (!isMidFrame) {
54473  drflac_result result = drflac__decode_flac_frame(pFlac);
54474  if (result == DRFLAC_SUCCESS) {
54475  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
54476  } else {
54477  if (result == DRFLAC_CRC_MISMATCH) {
54478  goto next_iteration;
54479  } else {
54480  return DRFLAC_FALSE;
54481  }
54482  }
54483  } else {
54484  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
54485  }
54486  } else {
54487  if (!isMidFrame) {
54489  if (result == DRFLAC_SUCCESS) {
54490  runningPCMFrameCount += pcmFrameCountInThisFLACFrame;
54491  } else {
54492  if (result == DRFLAC_CRC_MISMATCH) {
54493  goto next_iteration;
54494  } else {
54495  return DRFLAC_FALSE;
54496  }
54497  }
54498  } else {
54499  runningPCMFrameCount += pFlac->currentFLACFrame.pcmFramesRemaining;
54501  isMidFrame = DRFLAC_FALSE;
54502  }
54503  if (pcmFrameIndex == pFlac->totalPCMFrameCount && runningPCMFrameCount == pFlac->totalPCMFrameCount) {
54504  return DRFLAC_TRUE;
54505  }
54506  }
54507  next_iteration:
54509  return DRFLAC_FALSE;
54510  }
54511  }
54512 }
54513 #if !defined(DR_FLAC_NO_CRC)
54514 #define DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO 0.6f
54516 {
54517  DRFLAC_ASSERT(pFlac != NULL);
54518  DRFLAC_ASSERT(pLastSuccessfulSeekOffset != NULL);
54519  DRFLAC_ASSERT(targetByte >= rangeLo);
54520  DRFLAC_ASSERT(targetByte <= rangeHi);
54521  *pLastSuccessfulSeekOffset = pFlac->firstFLACFramePosInBytes;
54522  for (;;) {
54523  drflac_uint64 lastTargetByte = targetByte;
54524  if (!drflac__seek_to_byte(&pFlac->bs, targetByte)) {
54525  if (targetByte == 0) {
54527  return DRFLAC_FALSE;
54528  }
54529  targetByte = rangeLo + ((rangeHi - rangeLo)/2);
54530  rangeHi = targetByte;
54531  } else {
54532  DRFLAC_ZERO_MEMORY(&pFlac->currentFLACFrame, sizeof(pFlac->currentFLACFrame));
54533 #if 1
54535  targetByte = rangeLo + ((rangeHi - rangeLo)/2);
54536  rangeHi = targetByte;
54537  } else {
54538  break;
54539  }
54540 #else
54542  targetByte = rangeLo + ((rangeHi - rangeLo)/2);
54543  rangeHi = targetByte;
54544  } else {
54545  break;
54546  }
54547 #endif
54548  }
54549  if(targetByte == lastTargetByte) {
54550  return DRFLAC_FALSE;
54551  }
54552  }
54554  DRFLAC_ASSERT(targetByte <= rangeHi);
54555  *pLastSuccessfulSeekOffset = targetByte;
54556  return DRFLAC_TRUE;
54557 }
54559 {
54560 #if 0
54561  if (drflac__decode_flac_frame(pFlac) != DRFLAC_SUCCESS) {
54563  return DRFLAC_FALSE;
54564  }
54565  }
54566 #endif
54567  return drflac__seek_forward_by_pcm_frames(pFlac, offset) == offset;
54568 }
54570 {
54571  drflac_uint64 targetByte;
54572  drflac_uint64 pcmRangeLo = pFlac->totalPCMFrameCount;
54573  drflac_uint64 pcmRangeHi = 0;
54574  drflac_uint64 lastSuccessfulSeekOffset = (drflac_uint64)-1;
54575  drflac_uint64 closestSeekOffsetBeforeTargetPCMFrame = byteRangeLo;
54576  drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
54577  targetByte = byteRangeLo + (drflac_uint64)(((drflac_int64)((pcmFrameIndex - pFlac->currentPCMFrame) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO);
54578  if (targetByte > byteRangeHi) {
54579  targetByte = byteRangeHi;
54580  }
54581  for (;;) {
54582  if (drflac__seek_to_approximate_flac_frame_to_byte(pFlac, targetByte, byteRangeLo, byteRangeHi, &lastSuccessfulSeekOffset)) {
54583  drflac_uint64 newPCMRangeLo;
54584  drflac_uint64 newPCMRangeHi;
54585  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &newPCMRangeLo, &newPCMRangeHi);
54586  if (pcmRangeLo == newPCMRangeLo) {
54587  if (!drflac__seek_to_approximate_flac_frame_to_byte(pFlac, closestSeekOffsetBeforeTargetPCMFrame, closestSeekOffsetBeforeTargetPCMFrame, byteRangeHi, &lastSuccessfulSeekOffset)) {
54588  break;
54589  }
54591  return DRFLAC_TRUE;
54592  } else {
54593  break;
54594  }
54595  }
54596  pcmRangeLo = newPCMRangeLo;
54597  pcmRangeHi = newPCMRangeHi;
54598  if (pcmRangeLo <= pcmFrameIndex && pcmRangeHi >= pcmFrameIndex) {
54599  if (drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(pFlac, pcmFrameIndex - pFlac->currentPCMFrame) ) {
54600  return DRFLAC_TRUE;
54601  } else {
54602  break;
54603  }
54604  } else {
54605  const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
54606  if (pcmRangeLo > pcmFrameIndex) {
54607  byteRangeHi = lastSuccessfulSeekOffset;
54608  if (byteRangeLo > byteRangeHi) {
54609  byteRangeLo = byteRangeHi;
54610  }
54611  targetByte = byteRangeLo + ((byteRangeHi - byteRangeLo) / 2);
54612  if (targetByte < byteRangeLo) {
54613  targetByte = byteRangeLo;
54614  }
54615  } else {
54616  if ((pcmFrameIndex - pcmRangeLo) < seekForwardThreshold) {
54618  return DRFLAC_TRUE;
54619  } else {
54620  break;
54621  }
54622  } else {
54623  byteRangeLo = lastSuccessfulSeekOffset;
54624  if (byteRangeHi < byteRangeLo) {
54625  byteRangeHi = byteRangeLo;
54626  }
54627  targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio);
54628  if (targetByte > byteRangeHi) {
54629  targetByte = byteRangeHi;
54630  }
54631  if (closestSeekOffsetBeforeTargetPCMFrame < lastSuccessfulSeekOffset) {
54632  closestSeekOffsetBeforeTargetPCMFrame = lastSuccessfulSeekOffset;
54633  }
54634  }
54635  }
54636  }
54637  } else {
54638  break;
54639  }
54640  }
54642  return DRFLAC_FALSE;
54643 }
54645 {
54646  drflac_uint64 byteRangeLo;
54647  drflac_uint64 byteRangeHi;
54648  drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
54649  if (drflac__seek_to_first_frame(pFlac) == DRFLAC_FALSE) {
54650  return DRFLAC_FALSE;
54651  }
54652  if (pcmFrameIndex < seekForwardThreshold) {
54653  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFrameIndex) == pcmFrameIndex;
54654  }
54655  byteRangeLo = pFlac->firstFLACFramePosInBytes;
54656  byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)((drflac_int64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample)/8.0f);
54657  return drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi);
54658 }
54659 #endif
54661 {
54662  drflac_uint32 iClosestSeekpoint = 0;
54663  drflac_bool32 isMidFrame = DRFLAC_FALSE;
54664  drflac_uint64 runningPCMFrameCount;
54665  drflac_uint32 iSeekpoint;
54666  DRFLAC_ASSERT(pFlac != NULL);
54667  if (pFlac->pSeekpoints == NULL || pFlac->seekpointCount == 0) {
54668  return DRFLAC_FALSE;
54669  }
54670  for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
54671  if (pFlac->pSeekpoints[iSeekpoint].firstPCMFrame >= pcmFrameIndex) {
54672  break;
54673  }
54674  iClosestSeekpoint = iSeekpoint;
54675  }
54676  if (pFlac->pSeekpoints[iClosestSeekpoint].pcmFrameCount == 0 || pFlac->pSeekpoints[iClosestSeekpoint].pcmFrameCount > pFlac->maxBlockSizeInPCMFrames) {
54677  return DRFLAC_FALSE;
54678  }
54679  if (pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame > pFlac->totalPCMFrameCount && pFlac->totalPCMFrameCount > 0) {
54680  return DRFLAC_FALSE;
54681  }
54682 #if !defined(DR_FLAC_NO_CRC)
54683  if (pFlac->totalPCMFrameCount > 0) {
54684  drflac_uint64 byteRangeLo;
54685  drflac_uint64 byteRangeHi;
54686  byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)((drflac_int64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample)/8.0f);
54687  byteRangeLo = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset;
54688  if (iClosestSeekpoint < pFlac->seekpointCount-1) {
54689  drflac_uint32 iNextSeekpoint = iClosestSeekpoint + 1;
54690  if (pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset >= pFlac->pSeekpoints[iNextSeekpoint].flacFrameOffset || pFlac->pSeekpoints[iNextSeekpoint].pcmFrameCount == 0) {
54691  return DRFLAC_FALSE;
54692  }
54693  if (pFlac->pSeekpoints[iNextSeekpoint].firstPCMFrame != (((drflac_uint64)0xFFFFFFFF << 32) | 0xFFFFFFFF)) {
54694  byteRangeHi = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iNextSeekpoint].flacFrameOffset - 1;
54695  }
54696  }
54697  if (drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset)) {
54700  if (drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi)) {
54701  return DRFLAC_TRUE;
54702  }
54703  }
54704  }
54705  }
54706 #endif
54707  if (pcmFrameIndex >= pFlac->currentPCMFrame && pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame <= pFlac->currentPCMFrame) {
54708  runningPCMFrameCount = pFlac->currentPCMFrame;
54709  if (pFlac->currentPCMFrame == 0 && pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
54711  return DRFLAC_FALSE;
54712  }
54713  } else {
54714  isMidFrame = DRFLAC_TRUE;
54715  }
54716  } else {
54717  runningPCMFrameCount = pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame;
54718  if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset)) {
54719  return DRFLAC_FALSE;
54720  }
54722  return DRFLAC_FALSE;
54723  }
54724  }
54725  for (;;) {
54726  drflac_uint64 pcmFrameCountInThisFLACFrame;
54727  drflac_uint64 firstPCMFrameInFLACFrame = 0;
54728  drflac_uint64 lastPCMFrameInFLACFrame = 0;
54729  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
54730  pcmFrameCountInThisFLACFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
54731  if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFLACFrame)) {
54732  drflac_uint64 pcmFramesToDecode = pcmFrameIndex - runningPCMFrameCount;
54733  if (!isMidFrame) {
54734  drflac_result result = drflac__decode_flac_frame(pFlac);
54735  if (result == DRFLAC_SUCCESS) {
54736  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
54737  } else {
54738  if (result == DRFLAC_CRC_MISMATCH) {
54739  goto next_iteration;
54740  } else {
54741  return DRFLAC_FALSE;
54742  }
54743  }
54744  } else {
54745  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
54746  }
54747  } else {
54748  if (!isMidFrame) {
54750  if (result == DRFLAC_SUCCESS) {
54751  runningPCMFrameCount += pcmFrameCountInThisFLACFrame;
54752  } else {
54753  if (result == DRFLAC_CRC_MISMATCH) {
54754  goto next_iteration;
54755  } else {
54756  return DRFLAC_FALSE;
54757  }
54758  }
54759  } else {
54760  runningPCMFrameCount += pFlac->currentFLACFrame.pcmFramesRemaining;
54762  isMidFrame = DRFLAC_FALSE;
54763  }
54764  if (pcmFrameIndex == pFlac->totalPCMFrameCount && runningPCMFrameCount == pFlac->totalPCMFrameCount) {
54765  return DRFLAC_TRUE;
54766  }
54767  }
54768  next_iteration:
54770  return DRFLAC_FALSE;
54771  }
54772  }
54773 }
54774 #ifndef DR_FLAC_NO_OGG
54775 typedef struct
54776 {
54777  drflac_uint8 capturePattern[4];
54785  drflac_uint8 segmentTable[255];
54787 #endif
54788 typedef struct
54789 {
54794  void* pUserData;
54806 #ifndef DR_FLAC_NO_OGG
54810 #endif
54812 static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize)
54813 {
54814  blockHeader = drflac__be2host_32(blockHeader);
54815  *isLastBlock = (drflac_uint8)((blockHeader & 0x80000000UL) >> 31);
54816  *blockType = (drflac_uint8)((blockHeader & 0x7F000000UL) >> 24);
54817  *blockSize = (blockHeader & 0x00FFFFFFUL);
54818 }
54820 {
54821  drflac_uint32 blockHeader;
54822  *blockSize = 0;
54823  if (onRead(pUserData, &blockHeader, 4) != 4) {
54824  return DRFLAC_FALSE;
54825  }
54826  drflac__decode_block_header(blockHeader, isLastBlock, blockType, blockSize);
54827  return DRFLAC_TRUE;
54828 }
54829 static drflac_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo)
54830 {
54831  drflac_uint32 blockSizes;
54832  drflac_uint64 frameSizes = 0;
54833  drflac_uint64 importantProps;
54834  drflac_uint8 md5[16];
54835  if (onRead(pUserData, &blockSizes, 4) != 4) {
54836  return DRFLAC_FALSE;
54837  }
54838  if (onRead(pUserData, &frameSizes, 6) != 6) {
54839  return DRFLAC_FALSE;
54840  }
54841  if (onRead(pUserData, &importantProps, 8) != 8) {
54842  return DRFLAC_FALSE;
54843  }
54844  if (onRead(pUserData, md5, sizeof(md5)) != sizeof(md5)) {
54845  return DRFLAC_FALSE;
54846  }
54847  blockSizes = drflac__be2host_32(blockSizes);
54848  frameSizes = drflac__be2host_64(frameSizes);
54849  importantProps = drflac__be2host_64(importantProps);
54850  pStreamInfo->minBlockSizeInPCMFrames = (drflac_uint16)((blockSizes & 0xFFFF0000) >> 16);
54851  pStreamInfo->maxBlockSizeInPCMFrames = (drflac_uint16) (blockSizes & 0x0000FFFF);
54852  pStreamInfo->minFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 24)) >> 40);
54853  pStreamInfo->maxFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 0)) >> 16);
54854  pStreamInfo->sampleRate = (drflac_uint32)((importantProps & (((drflac_uint64)0x000FFFFF << 16) << 28)) >> 44);
54855  pStreamInfo->channels = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000000E << 16) << 24)) >> 41) + 1;
54856  pStreamInfo->bitsPerSample = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000001F << 16) << 20)) >> 36) + 1;
54857  pStreamInfo->totalPCMFrameCount = ((importantProps & ((((drflac_uint64)0x0000000F << 16) << 16) | 0xFFFFFFFF)));
54858  DRFLAC_COPY_MEMORY(pStreamInfo->md5, md5, sizeof(md5));
54859  return DRFLAC_TRUE;
54860 }
54861 static void* drflac__malloc_default(size_t sz, void* pUserData)
54862 {
54863  (void)pUserData;
54864  return DRFLAC_MALLOC(sz);
54865 }
54866 static void* drflac__realloc_default(void* p, size_t sz, void* pUserData)
54867 {
54868  (void)pUserData;
54869  return DRFLAC_REALLOC(p, sz);
54870 }
54871 static void drflac__free_default(void* p, void* pUserData)
54872 {
54873  (void)pUserData;
54874  DRFLAC_FREE(p);
54875 }
54876 static void* drflac__malloc_from_callbacks(size_t sz, const drflac_allocation_callbacks* pAllocationCallbacks)
54877 {
54878  if (pAllocationCallbacks == NULL) {
54879  return NULL;
54880  }
54881  if (pAllocationCallbacks->onMalloc != NULL) {
54882  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
54883  }
54884  if (pAllocationCallbacks->onRealloc != NULL) {
54885  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
54886  }
54887  return NULL;
54888 }
54889 static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drflac_allocation_callbacks* pAllocationCallbacks)
54890 {
54891  if (pAllocationCallbacks == NULL) {
54892  return NULL;
54893  }
54894  if (pAllocationCallbacks->onRealloc != NULL) {
54895  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
54896  }
54897  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
54898  void* p2;
54899  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
54900  if (p2 == NULL) {
54901  return NULL;
54902  }
54903  if (p != NULL) {
54904  DRFLAC_COPY_MEMORY(p2, p, szOld);
54905  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
54906  }
54907  return p2;
54908  }
54909  return NULL;
54910 }
54911 static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
54912 {
54913  if (p == NULL || pAllocationCallbacks == NULL) {
54914  return;
54915  }
54916  if (pAllocationCallbacks->onFree != NULL) {
54917  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
54918  }
54919 }
54920 static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeektableSize, drflac_allocation_callbacks* pAllocationCallbacks)
54921 {
54922  drflac_uint64 runningFilePos = 42;
54923  drflac_uint64 seektablePos = 0;
54924  drflac_uint32 seektableSize = 0;
54925  for (;;) {
54926  drflac_metadata metadata;
54927  drflac_uint8 isLastBlock = 0;
54928  drflac_uint8 blockType;
54929  drflac_uint32 blockSize;
54930  if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
54931  return DRFLAC_FALSE;
54932  }
54933  runningFilePos += 4;
54934  metadata.type = blockType;
54935  metadata.pRawData = NULL;
54936  metadata.rawDataSize = 0;
54937  switch (blockType)
54938  {
54940  {
54941  if (blockSize < 4) {
54942  return DRFLAC_FALSE;
54943  }
54944  if (onMeta) {
54945  void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
54946  if (pRawData == NULL) {
54947  return DRFLAC_FALSE;
54948  }
54949  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
54950  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
54951  return DRFLAC_FALSE;
54952  }
54953  metadata.pRawData = pRawData;
54954  metadata.rawDataSize = blockSize;
54955  metadata.data.application.id = drflac__be2host_32(*(drflac_uint32*)pRawData);
54956  metadata.data.application.pData = (const void*)((drflac_uint8*)pRawData + sizeof(drflac_uint32));
54957  metadata.data.application.dataSize = blockSize - sizeof(drflac_uint32);
54958  onMeta(pUserDataMD, &metadata);
54959  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
54960  }
54961  } break;
54963  {
54964  seektablePos = runningFilePos;
54965  seektableSize = blockSize;
54966  if (onMeta) {
54967  drflac_uint32 iSeekpoint;
54968  void* pRawData;
54969  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
54970  if (pRawData == NULL) {
54971  return DRFLAC_FALSE;
54972  }
54973  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
54974  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
54975  return DRFLAC_FALSE;
54976  }
54977  metadata.pRawData = pRawData;
54978  metadata.rawDataSize = blockSize;
54979  metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
54980  metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
54981  for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
54982  drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
54983  pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
54984  pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
54985  pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
54986  }
54987  onMeta(pUserDataMD, &metadata);
54988  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
54989  }
54990  } break;
54992  {
54993  if (blockSize < 8) {
54994  return DRFLAC_FALSE;
54995  }
54996  if (onMeta) {
54997  void* pRawData;
54998  const char* pRunningData;
54999  const char* pRunningDataEnd;
55000  drflac_uint32 i;
55001  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
55002  if (pRawData == NULL) {
55003  return DRFLAC_FALSE;
55004  }
55005  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
55006  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55007  return DRFLAC_FALSE;
55008  }
55009  metadata.pRawData = pRawData;
55010  metadata.rawDataSize = blockSize;
55011  pRunningData = (const char*)pRawData;
55012  pRunningDataEnd = (const char*)pRawData + blockSize;
55013  metadata.data.vorbis_comment.vendorLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55014  if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) {
55015  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55016  return DRFLAC_FALSE;
55017  }
55018  metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
55019  metadata.data.vorbis_comment.commentCount = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55020  if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) {
55021  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55022  return DRFLAC_FALSE;
55023  }
55024  metadata.data.vorbis_comment.pComments = pRunningData;
55025  for (i = 0; i < metadata.data.vorbis_comment.commentCount; ++i) {
55026  drflac_uint32 commentLength;
55027  if (pRunningDataEnd - pRunningData < 4) {
55028  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55029  return DRFLAC_FALSE;
55030  }
55031  commentLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55032  if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) {
55033  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55034  return DRFLAC_FALSE;
55035  }
55036  pRunningData += commentLength;
55037  }
55038  onMeta(pUserDataMD, &metadata);
55039  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55040  }
55041  } break;
55043  {
55044  if (blockSize < 396) {
55045  return DRFLAC_FALSE;
55046  }
55047  if (onMeta) {
55048  void* pRawData;
55049  const char* pRunningData;
55050  const char* pRunningDataEnd;
55051  drflac_uint8 iTrack;
55052  drflac_uint8 iIndex;
55053  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
55054  if (pRawData == NULL) {
55055  return DRFLAC_FALSE;
55056  }
55057  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
55058  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55059  return DRFLAC_FALSE;
55060  }
55061  metadata.pRawData = pRawData;
55062  metadata.rawDataSize = blockSize;
55063  pRunningData = (const char*)pRawData;
55064  pRunningDataEnd = (const char*)pRawData + blockSize;
55065  DRFLAC_COPY_MEMORY(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
55066  metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
55067  metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
55068  metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
55069  metadata.data.cuesheet.pTrackData = pRunningData;
55070  for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
55071  drflac_uint8 indexCount;
55072  drflac_uint32 indexPointSize;
55073  if (pRunningDataEnd - pRunningData < 36) {
55074  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55075  return DRFLAC_FALSE;
55076  }
55077  pRunningData += 35;
55078  indexCount = pRunningData[0]; pRunningData += 1;
55079  indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
55080  if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
55081  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55082  return DRFLAC_FALSE;
55083  }
55084  for (iIndex = 0; iIndex < indexCount; ++iIndex) {
55086  pRunningData += sizeof(drflac_cuesheet_track_index);
55087  pTrack->offset = drflac__be2host_64(pTrack->offset);
55088  }
55089  }
55090  onMeta(pUserDataMD, &metadata);
55091  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55092  }
55093  } break;
55095  {
55096  if (blockSize < 32) {
55097  return DRFLAC_FALSE;
55098  }
55099  if (onMeta) {
55100  void* pRawData;
55101  const char* pRunningData;
55102  const char* pRunningDataEnd;
55103  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
55104  if (pRawData == NULL) {
55105  return DRFLAC_FALSE;
55106  }
55107  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
55108  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55109  return DRFLAC_FALSE;
55110  }
55111  metadata.pRawData = pRawData;
55112  metadata.rawDataSize = blockSize;
55113  pRunningData = (const char*)pRawData;
55114  pRunningDataEnd = (const char*)pRawData + blockSize;
55115  metadata.data.picture.type = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55116  metadata.data.picture.mimeLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55117  if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) {
55118  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55119  return DRFLAC_FALSE;
55120  }
55121  metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
55122  metadata.data.picture.descriptionLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55123  if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) {
55124  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55125  return DRFLAC_FALSE;
55126  }
55127  metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
55128  metadata.data.picture.width = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55129  metadata.data.picture.height = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55130  metadata.data.picture.colorDepth = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55131  metadata.data.picture.indexColorCount = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55132  metadata.data.picture.pictureDataSize = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
55133  metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
55134  if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) {
55135  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55136  return DRFLAC_FALSE;
55137  }
55138  onMeta(pUserDataMD, &metadata);
55139  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55140  }
55141  } break;
55143  {
55144  if (onMeta) {
55145  metadata.data.padding.unused = 0;
55146  if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
55147  isLastBlock = DRFLAC_TRUE;
55148  } else {
55149  onMeta(pUserDataMD, &metadata);
55150  }
55151  }
55152  } break;
55154  {
55155  if (onMeta) {
55156  if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
55157  isLastBlock = DRFLAC_TRUE;
55158  }
55159  }
55160  } break;
55161  default:
55162  {
55163  if (onMeta) {
55164  void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
55165  if (pRawData == NULL) {
55166  return DRFLAC_FALSE;
55167  }
55168  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
55169  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55170  return DRFLAC_FALSE;
55171  }
55172  metadata.pRawData = pRawData;
55173  metadata.rawDataSize = blockSize;
55174  onMeta(pUserDataMD, &metadata);
55175  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
55176  }
55177  } break;
55178  }
55179  if (onMeta == NULL && blockSize > 0) {
55180  if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
55181  isLastBlock = DRFLAC_TRUE;
55182  }
55183  }
55184  runningFilePos += blockSize;
55185  if (isLastBlock) {
55186  break;
55187  }
55188  }
55189  *pSeektablePos = seektablePos;
55190  *pSeektableSize = seektableSize;
55191  *pFirstFramePos = runningFilePos;
55192  return DRFLAC_TRUE;
55193 }
55194 static drflac_bool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed)
55195 {
55196  drflac_uint8 isLastBlock;
55197  drflac_uint8 blockType;
55198  drflac_uint32 blockSize;
55199  (void)onSeek;
55201  if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
55202  return DRFLAC_FALSE;
55203  }
55204  if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
55205  if (!relaxed) {
55206  return DRFLAC_FALSE;
55207  } else {
55210  if (!drflac__read_next_flac_frame_header(&pInit->bs, 0, &pInit->firstFrameHeader)) {
55211  return DRFLAC_FALSE;
55212  }
55213  if (pInit->firstFrameHeader.bitsPerSample == 0) {
55214  return DRFLAC_FALSE;
55215  }
55216  pInit->sampleRate = pInit->firstFrameHeader.sampleRate;
55219  pInit->maxBlockSizeInPCMFrames = 65535;
55220  return DRFLAC_TRUE;
55221  }
55222  } else {
55223  drflac_streaminfo streaminfo;
55224  if (!drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
55225  return DRFLAC_FALSE;
55226  }
55228  pInit->sampleRate = streaminfo.sampleRate;
55229  pInit->channels = streaminfo.channels;
55230  pInit->bitsPerSample = streaminfo.bitsPerSample;
55231  pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
55233  pInit->hasMetadataBlocks = !isLastBlock;
55234  if (onMeta) {
55235  drflac_metadata metadata;
55237  metadata.pRawData = NULL;
55238  metadata.rawDataSize = 0;
55239  metadata.data.streaminfo = streaminfo;
55240  onMeta(pUserDataMD, &metadata);
55241  }
55242  return DRFLAC_TRUE;
55243  }
55244 }
55245 #ifndef DR_FLAC_NO_OGG
55246 #define DRFLAC_OGG_MAX_PAGE_SIZE 65307
55247 #define DRFLAC_OGG_CAPTURE_PATTERN_CRC32 1605413199
55248 typedef enum
55249 {
55253 #ifndef DR_FLAC_NO_CRC
55255  0x00000000L, 0x04C11DB7L, 0x09823B6EL, 0x0D4326D9L,
55256  0x130476DCL, 0x17C56B6BL, 0x1A864DB2L, 0x1E475005L,
55257  0x2608EDB8L, 0x22C9F00FL, 0x2F8AD6D6L, 0x2B4BCB61L,
55258  0x350C9B64L, 0x31CD86D3L, 0x3C8EA00AL, 0x384FBDBDL,
55259  0x4C11DB70L, 0x48D0C6C7L, 0x4593E01EL, 0x4152FDA9L,
55260  0x5F15ADACL, 0x5BD4B01BL, 0x569796C2L, 0x52568B75L,
55261  0x6A1936C8L, 0x6ED82B7FL, 0x639B0DA6L, 0x675A1011L,
55262  0x791D4014L, 0x7DDC5DA3L, 0x709F7B7AL, 0x745E66CDL,
55263  0x9823B6E0L, 0x9CE2AB57L, 0x91A18D8EL, 0x95609039L,
55264  0x8B27C03CL, 0x8FE6DD8BL, 0x82A5FB52L, 0x8664E6E5L,
55265  0xBE2B5B58L, 0xBAEA46EFL, 0xB7A96036L, 0xB3687D81L,
55266  0xAD2F2D84L, 0xA9EE3033L, 0xA4AD16EAL, 0xA06C0B5DL,
55267  0xD4326D90L, 0xD0F37027L, 0xDDB056FEL, 0xD9714B49L,
55268  0xC7361B4CL, 0xC3F706FBL, 0xCEB42022L, 0xCA753D95L,
55269  0xF23A8028L, 0xF6FB9D9FL, 0xFBB8BB46L, 0xFF79A6F1L,
55270  0xE13EF6F4L, 0xE5FFEB43L, 0xE8BCCD9AL, 0xEC7DD02DL,
55271  0x34867077L, 0x30476DC0L, 0x3D044B19L, 0x39C556AEL,
55272  0x278206ABL, 0x23431B1CL, 0x2E003DC5L, 0x2AC12072L,
55273  0x128E9DCFL, 0x164F8078L, 0x1B0CA6A1L, 0x1FCDBB16L,
55274  0x018AEB13L, 0x054BF6A4L, 0x0808D07DL, 0x0CC9CDCAL,
55275  0x7897AB07L, 0x7C56B6B0L, 0x71159069L, 0x75D48DDEL,
55276  0x6B93DDDBL, 0x6F52C06CL, 0x6211E6B5L, 0x66D0FB02L,
55277  0x5E9F46BFL, 0x5A5E5B08L, 0x571D7DD1L, 0x53DC6066L,
55278  0x4D9B3063L, 0x495A2DD4L, 0x44190B0DL, 0x40D816BAL,
55279  0xACA5C697L, 0xA864DB20L, 0xA527FDF9L, 0xA1E6E04EL,
55280  0xBFA1B04BL, 0xBB60ADFCL, 0xB6238B25L, 0xB2E29692L,
55281  0x8AAD2B2FL, 0x8E6C3698L, 0x832F1041L, 0x87EE0DF6L,
55282  0x99A95DF3L, 0x9D684044L, 0x902B669DL, 0x94EA7B2AL,
55283  0xE0B41DE7L, 0xE4750050L, 0xE9362689L, 0xEDF73B3EL,
55284  0xF3B06B3BL, 0xF771768CL, 0xFA325055L, 0xFEF34DE2L,
55285  0xC6BCF05FL, 0xC27DEDE8L, 0xCF3ECB31L, 0xCBFFD686L,
55286  0xD5B88683L, 0xD1799B34L, 0xDC3ABDEDL, 0xD8FBA05AL,
55287  0x690CE0EEL, 0x6DCDFD59L, 0x608EDB80L, 0x644FC637L,
55288  0x7A089632L, 0x7EC98B85L, 0x738AAD5CL, 0x774BB0EBL,
55289  0x4F040D56L, 0x4BC510E1L, 0x46863638L, 0x42472B8FL,
55290  0x5C007B8AL, 0x58C1663DL, 0x558240E4L, 0x51435D53L,
55291  0x251D3B9EL, 0x21DC2629L, 0x2C9F00F0L, 0x285E1D47L,
55292  0x36194D42L, 0x32D850F5L, 0x3F9B762CL, 0x3B5A6B9BL,
55293  0x0315D626L, 0x07D4CB91L, 0x0A97ED48L, 0x0E56F0FFL,
55294  0x1011A0FAL, 0x14D0BD4DL, 0x19939B94L, 0x1D528623L,
55295  0xF12F560EL, 0xF5EE4BB9L, 0xF8AD6D60L, 0xFC6C70D7L,
55296  0xE22B20D2L, 0xE6EA3D65L, 0xEBA91BBCL, 0xEF68060BL,
55297  0xD727BBB6L, 0xD3E6A601L, 0xDEA580D8L, 0xDA649D6FL,
55298  0xC423CD6AL, 0xC0E2D0DDL, 0xCDA1F604L, 0xC960EBB3L,
55299  0xBD3E8D7EL, 0xB9FF90C9L, 0xB4BCB610L, 0xB07DABA7L,
55300  0xAE3AFBA2L, 0xAAFBE615L, 0xA7B8C0CCL, 0xA379DD7BL,
55301  0x9B3660C6L, 0x9FF77D71L, 0x92B45BA8L, 0x9675461FL,
55302  0x8832161AL, 0x8CF30BADL, 0x81B02D74L, 0x857130C3L,
55303  0x5D8A9099L, 0x594B8D2EL, 0x5408ABF7L, 0x50C9B640L,
55304  0x4E8EE645L, 0x4A4FFBF2L, 0x470CDD2BL, 0x43CDC09CL,
55305  0x7B827D21L, 0x7F436096L, 0x7200464FL, 0x76C15BF8L,
55306  0x68860BFDL, 0x6C47164AL, 0x61043093L, 0x65C52D24L,
55307  0x119B4BE9L, 0x155A565EL, 0x18197087L, 0x1CD86D30L,
55308  0x029F3D35L, 0x065E2082L, 0x0B1D065BL, 0x0FDC1BECL,
55309  0x3793A651L, 0x3352BBE6L, 0x3E119D3FL, 0x3AD08088L,
55310  0x2497D08DL, 0x2056CD3AL, 0x2D15EBE3L, 0x29D4F654L,
55311  0xC5A92679L, 0xC1683BCEL, 0xCC2B1D17L, 0xC8EA00A0L,
55312  0xD6AD50A5L, 0xD26C4D12L, 0xDF2F6BCBL, 0xDBEE767CL,
55313  0xE3A1CBC1L, 0xE760D676L, 0xEA23F0AFL, 0xEEE2ED18L,
55314  0xF0A5BD1DL, 0xF464A0AAL, 0xF9278673L, 0xFDE69BC4L,
55315  0x89B8FD09L, 0x8D79E0BEL, 0x803AC667L, 0x84FBDBD0L,
55316  0x9ABC8BD5L, 0x9E7D9662L, 0x933EB0BBL, 0x97FFAD0CL,
55317  0xAFB010B1L, 0xAB710D06L, 0xA6322BDFL, 0xA2F33668L,
55318  0xBCB4666DL, 0xB8757BDAL, 0xB5365D03L, 0xB1F740B4L
55319 };
55320 #endif
55322 {
55323 #ifndef DR_FLAC_NO_CRC
55324  return (crc32 << 8) ^ drflac__crc32_table[(drflac_uint8)((crc32 >> 24) & 0xFF) ^ data];
55325 #else
55326  (void)data;
55327  return crc32;
55328 #endif
55329 }
55330 #if 0
55331 static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint32(drflac_uint32 crc32, drflac_uint32 data)
55332 {
55333  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 24) & 0xFF));
55334  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 16) & 0xFF));
55335  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 8) & 0xFF));
55336  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 0) & 0xFF));
55337  return crc32;
55338 }
55339 static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint64(drflac_uint32 crc32, drflac_uint64 data)
55340 {
55341  crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 32) & 0xFFFFFFFF));
55342  crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 0) & 0xFFFFFFFF));
55343  return crc32;
55344 }
55345 #endif
55347 {
55348  drflac_uint32 i;
55349  for (i = 0; i < dataSize; ++i) {
55350  crc32 = drflac_crc32_byte(crc32, pData[i]);
55351  }
55352  return crc32;
55353 }
55355 {
55356  return pattern[0] == 'O' && pattern[1] == 'g' && pattern[2] == 'g' && pattern[3] == 'S';
55357 }
55359 {
55360  return 27 + pHeader->segmentCount;
55361 }
55363 {
55364  drflac_uint32 pageBodySize = 0;
55365  int i;
55366  for (i = 0; i < pHeader->segmentCount; ++i) {
55367  pageBodySize += pHeader->segmentTable[i];
55368  }
55369  return pageBodySize;
55370 }
55372 {
55373  drflac_uint8 data[23];
55374  drflac_uint32 i;
55376  if (onRead(pUserData, data, 23) != 23) {
55377  return DRFLAC_AT_END;
55378  }
55379  *pBytesRead += 23;
55380  pHeader->capturePattern[0] = 'O';
55381  pHeader->capturePattern[1] = 'g';
55382  pHeader->capturePattern[2] = 'g';
55383  pHeader->capturePattern[3] = 'S';
55384  pHeader->structureVersion = data[0];
55385  pHeader->headerType = data[1];
55386  DRFLAC_COPY_MEMORY(&pHeader->granulePosition, &data[ 2], 8);
55387  DRFLAC_COPY_MEMORY(&pHeader->serialNumber, &data[10], 4);
55388  DRFLAC_COPY_MEMORY(&pHeader->sequenceNumber, &data[14], 4);
55389  DRFLAC_COPY_MEMORY(&pHeader->checksum, &data[18], 4);
55390  pHeader->segmentCount = data[22];
55391  data[18] = 0;
55392  data[19] = 0;
55393  data[20] = 0;
55394  data[21] = 0;
55395  for (i = 0; i < 23; ++i) {
55396  *pCRC32 = drflac_crc32_byte(*pCRC32, data[i]);
55397  }
55398  if (onRead(pUserData, pHeader->segmentTable, pHeader->segmentCount) != pHeader->segmentCount) {
55399  return DRFLAC_AT_END;
55400  }
55401  *pBytesRead += pHeader->segmentCount;
55402  for (i = 0; i < pHeader->segmentCount; ++i) {
55403  *pCRC32 = drflac_crc32_byte(*pCRC32, pHeader->segmentTable[i]);
55404  }
55405  return DRFLAC_SUCCESS;
55406 }
55408 {
55409  drflac_uint8 id[4];
55410  *pBytesRead = 0;
55411  if (onRead(pUserData, id, 4) != 4) {
55412  return DRFLAC_AT_END;
55413  }
55414  *pBytesRead += 4;
55415  for (;;) {
55417  drflac_result result;
55419  result = drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, pHeader, pBytesRead, pCRC32);
55420  if (result == DRFLAC_SUCCESS) {
55421  return DRFLAC_SUCCESS;
55422  } else {
55423  if (result == DRFLAC_CRC_MISMATCH) {
55424  continue;
55425  } else {
55426  return result;
55427  }
55428  }
55429  } else {
55430  id[0] = id[1];
55431  id[1] = id[2];
55432  id[2] = id[3];
55433  if (onRead(pUserData, &id[3], 1) != 1) {
55434  return DRFLAC_AT_END;
55435  }
55436  *pBytesRead += 1;
55437  }
55438  }
55439 }
55440 typedef struct
55441 {
55444  void* pUserData;
55452  drflac_uint8 pageData[DRFLAC_OGG_MAX_PAGE_SIZE];
55453 } drflac_oggbs;
55454 static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut, size_t bytesToRead)
55455 {
55456  size_t bytesActuallyRead = oggbs->onRead(oggbs->pUserData, bufferOut, bytesToRead);
55457  oggbs->currentBytePos += bytesActuallyRead;
55458  return bytesActuallyRead;
55459 }
55461 {
55462  if (origin == drflac_seek_origin_start) {
55463  if (offset <= 0x7FFFFFFF) {
55464  if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
55465  return DRFLAC_FALSE;
55466  }
55467  oggbs->currentBytePos = offset;
55468  return DRFLAC_TRUE;
55469  } else {
55470  if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
55471  return DRFLAC_FALSE;
55472  }
55473  oggbs->currentBytePos = offset;
55474  return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
55475  }
55476  } else {
55477  while (offset > 0x7FFFFFFF) {
55478  if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
55479  return DRFLAC_FALSE;
55480  }
55481  oggbs->currentBytePos += 0x7FFFFFFF;
55482  offset -= 0x7FFFFFFF;
55483  }
55484  if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) {
55485  return DRFLAC_FALSE;
55486  }
55487  oggbs->currentBytePos += offset;
55488  return DRFLAC_TRUE;
55489  }
55490 }
55492 {
55494  for (;;) {
55495  drflac_uint32 crc32 = 0;
55496  drflac_uint32 bytesRead;
55497  drflac_uint32 pageBodySize;
55498 #ifndef DR_FLAC_NO_CRC
55499  drflac_uint32 actualCRC32;
55500 #endif
55501  if (drflac_ogg__read_page_header(oggbs->onRead, oggbs->pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
55502  return DRFLAC_FALSE;
55503  }
55504  oggbs->currentBytePos += bytesRead;
55505  pageBodySize = drflac_ogg__get_page_body_size(&header);
55506  if (pageBodySize > DRFLAC_OGG_MAX_PAGE_SIZE) {
55507  continue;
55508  }
55509  if (header.serialNumber != oggbs->serialNumber) {
55510  if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) {
55511  return DRFLAC_FALSE;
55512  }
55513  continue;
55514  }
55515  if (drflac_oggbs__read_physical(oggbs, oggbs->pageData, pageBodySize) != pageBodySize) {
55516  return DRFLAC_FALSE;
55517  }
55518  oggbs->pageDataSize = pageBodySize;
55519 #ifndef DR_FLAC_NO_CRC
55520  actualCRC32 = drflac_crc32_buffer(crc32, oggbs->pageData, oggbs->pageDataSize);
55521  if (actualCRC32 != header.checksum) {
55522  if (recoveryMethod == drflac_ogg_recover_on_crc_mismatch) {
55523  continue;
55524  } else {
55526  return DRFLAC_FALSE;
55527  }
55528  }
55529 #else
55530  (void)recoveryMethod;
55531 #endif
55532  oggbs->currentPageHeader = header;
55533  oggbs->bytesRemainingInPage = pageBodySize;
55534  return DRFLAC_TRUE;
55535  }
55536 }
55537 #if 0
55538 static drflac_uint8 drflac_oggbs__get_current_segment_index(drflac_oggbs* oggbs, drflac_uint8* pBytesRemainingInSeg)
55539 {
55540  drflac_uint32 bytesConsumedInPage = drflac_ogg__get_page_body_size(&oggbs->currentPageHeader) - oggbs->bytesRemainingInPage;
55541  drflac_uint8 iSeg = 0;
55542  drflac_uint32 iByte = 0;
55543  while (iByte < bytesConsumedInPage) {
55544  drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg];
55545  if (iByte + segmentSize > bytesConsumedInPage) {
55546  break;
55547  } else {
55548  iSeg += 1;
55549  iByte += segmentSize;
55550  }
55551  }
55552  *pBytesRemainingInSeg = oggbs->currentPageHeader.segmentTable[iSeg] - (drflac_uint8)(bytesConsumedInPage - iByte);
55553  return iSeg;
55554 }
55555 static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs)
55556 {
55557  for (;;) {
55558  drflac_bool32 atEndOfPage = DRFLAC_FALSE;
55559  drflac_uint8 bytesRemainingInSeg;
55560  drflac_uint8 iFirstSeg = drflac_oggbs__get_current_segment_index(oggbs, &bytesRemainingInSeg);
55561  drflac_uint32 bytesToEndOfPacketOrPage = bytesRemainingInSeg;
55562  for (drflac_uint8 iSeg = iFirstSeg; iSeg < oggbs->currentPageHeader.segmentCount; ++iSeg) {
55563  drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg];
55564  if (segmentSize < 255) {
55565  if (iSeg == oggbs->currentPageHeader.segmentCount-1) {
55566  atEndOfPage = DRFLAC_TRUE;
55567  }
55568  break;
55569  }
55570  bytesToEndOfPacketOrPage += segmentSize;
55571  }
55572  drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current);
55573  oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
55574  if (atEndOfPage) {
55575  if (!drflac_oggbs__goto_next_page(oggbs)) {
55576  return DRFLAC_FALSE;
55577  }
55578  if ((oggbs->currentPageHeader.headerType & 0x01) == 0) {
55579  return DRFLAC_TRUE;
55580  }
55581  } else {
55582  return DRFLAC_TRUE;
55583  }
55584  }
55585 }
55586 static drflac_bool32 drflac_oggbs__seek_to_next_frame(drflac_oggbs* oggbs)
55587 {
55588  return drflac_oggbs__seek_to_next_packet(oggbs);
55589 }
55590 #endif
55591 static size_t drflac__on_read_ogg(void* pUserData, void* bufferOut, size_t bytesToRead)
55592 {
55593  drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
55594  drflac_uint8* pRunningBufferOut = (drflac_uint8*)bufferOut;
55595  size_t bytesRead = 0;
55596  DRFLAC_ASSERT(oggbs != NULL);
55597  DRFLAC_ASSERT(pRunningBufferOut != NULL);
55598  while (bytesRead < bytesToRead) {
55599  size_t bytesRemainingToRead = bytesToRead - bytesRead;
55600  if (oggbs->bytesRemainingInPage >= bytesRemainingToRead) {
55601  DRFLAC_COPY_MEMORY(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), bytesRemainingToRead);
55602  bytesRead += bytesRemainingToRead;
55603  oggbs->bytesRemainingInPage -= (drflac_uint32)bytesRemainingToRead;
55604  break;
55605  }
55606  if (oggbs->bytesRemainingInPage > 0) {
55607  DRFLAC_COPY_MEMORY(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), oggbs->bytesRemainingInPage);
55608  bytesRead += oggbs->bytesRemainingInPage;
55609  pRunningBufferOut += oggbs->bytesRemainingInPage;
55610  oggbs->bytesRemainingInPage = 0;
55611  }
55612  DRFLAC_ASSERT(bytesRemainingToRead > 0);
55614  break;
55615  }
55616  }
55617  return bytesRead;
55618 }
55619 static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_origin origin)
55620 {
55621  drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
55622  int bytesSeeked = 0;
55623  DRFLAC_ASSERT(oggbs != NULL);
55624  DRFLAC_ASSERT(offset >= 0);
55625  if (origin == drflac_seek_origin_start) {
55627  return DRFLAC_FALSE;
55628  }
55630  return DRFLAC_FALSE;
55631  }
55632  return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current);
55633  }
55635  while (bytesSeeked < offset) {
55636  int bytesRemainingToSeek = offset - bytesSeeked;
55637  DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
55638  if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
55639  bytesSeeked += bytesRemainingToSeek;
55640  (void)bytesSeeked;
55641  oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
55642  break;
55643  }
55644  if (oggbs->bytesRemainingInPage > 0) {
55645  bytesSeeked += (int)oggbs->bytesRemainingInPage;
55646  oggbs->bytesRemainingInPage = 0;
55647  }
55648  DRFLAC_ASSERT(bytesRemainingToSeek > 0);
55650  return DRFLAC_FALSE;
55651  }
55652  }
55653  return DRFLAC_TRUE;
55654 }
55656 {
55657  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
55658  drflac_uint64 originalBytePos;
55659  drflac_uint64 runningGranulePosition;
55660  drflac_uint64 runningFrameBytePos;
55661  drflac_uint64 runningPCMFrameCount;
55662  DRFLAC_ASSERT(oggbs != NULL);
55663  originalBytePos = oggbs->currentBytePos;
55664  if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes)) {
55665  return DRFLAC_FALSE;
55666  }
55667  oggbs->bytesRemainingInPage = 0;
55668  runningGranulePosition = 0;
55669  for (;;) {
55671  drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start);
55672  return DRFLAC_FALSE;
55673  }
55674  runningFrameBytePos = oggbs->currentBytePos - drflac_ogg__get_page_header_size(&oggbs->currentPageHeader) - oggbs->pageDataSize;
55675  if (oggbs->currentPageHeader.granulePosition >= pcmFrameIndex) {
55676  break;
55677  }
55678  if ((oggbs->currentPageHeader.headerType & 0x01) == 0) {
55679  if (oggbs->currentPageHeader.segmentTable[0] >= 2) {
55680  drflac_uint8 firstBytesInPage[2];
55681  firstBytesInPage[0] = oggbs->pageData[0];
55682  firstBytesInPage[1] = oggbs->pageData[1];
55683  if ((firstBytesInPage[0] == 0xFF) && (firstBytesInPage[1] & 0xFC) == 0xF8) {
55684  runningGranulePosition = oggbs->currentPageHeader.granulePosition;
55685  }
55686  continue;
55687  }
55688  }
55689  }
55690  if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) {
55691  return DRFLAC_FALSE;
55692  }
55694  return DRFLAC_FALSE;
55695  }
55696  runningPCMFrameCount = runningGranulePosition;
55697  for (;;) {
55698  drflac_uint64 firstPCMFrameInFLACFrame = 0;
55699  drflac_uint64 lastPCMFrameInFLACFrame = 0;
55700  drflac_uint64 pcmFrameCountInThisFrame;
55702  return DRFLAC_FALSE;
55703  }
55704  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
55705  pcmFrameCountInThisFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
55706  if (pcmFrameIndex == pFlac->totalPCMFrameCount && (runningPCMFrameCount + pcmFrameCountInThisFrame) == pFlac->totalPCMFrameCount) {
55707  drflac_result result = drflac__decode_flac_frame(pFlac);
55708  if (result == DRFLAC_SUCCESS) {
55709  pFlac->currentPCMFrame = pcmFrameIndex;
55711  return DRFLAC_TRUE;
55712  } else {
55713  return DRFLAC_FALSE;
55714  }
55715  }
55716  if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFrame)) {
55717  drflac_result result = drflac__decode_flac_frame(pFlac);
55718  if (result == DRFLAC_SUCCESS) {
55719  drflac_uint64 pcmFramesToDecode = (size_t)(pcmFrameIndex - runningPCMFrameCount);
55720  if (pcmFramesToDecode == 0) {
55721  return DRFLAC_TRUE;
55722  }
55723  pFlac->currentPCMFrame = runningPCMFrameCount;
55724  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
55725  } else {
55726  if (result == DRFLAC_CRC_MISMATCH) {
55727  continue;
55728  } else {
55729  return DRFLAC_FALSE;
55730  }
55731  }
55732  } else {
55734  if (result == DRFLAC_SUCCESS) {
55735  runningPCMFrameCount += pcmFrameCountInThisFrame;
55736  } else {
55737  if (result == DRFLAC_CRC_MISMATCH) {
55738  continue;
55739  } else {
55740  return DRFLAC_FALSE;
55741  }
55742  }
55743  }
55744  }
55745 }
55746 static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed)
55747 {
55750  drflac_uint32 bytesRead = 0;
55751  (void)relaxed;
55753  pInit->oggFirstBytePos = 0;
55754  if (drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
55755  return DRFLAC_FALSE;
55756  }
55757  pInit->runningFilePos += bytesRead;
55758  for (;;) {
55759  int pageBodySize;
55760  if ((header.headerType & 0x02) == 0) {
55761  return DRFLAC_FALSE;
55762  }
55763  pageBodySize = drflac_ogg__get_page_body_size(&header);
55764  if (pageBodySize == 51) {
55765  drflac_uint32 bytesRemainingInPage = pageBodySize;
55766  drflac_uint8 packetType;
55767  if (onRead(pUserData, &packetType, 1) != 1) {
55768  return DRFLAC_FALSE;
55769  }
55770  bytesRemainingInPage -= 1;
55771  if (packetType == 0x7F) {
55772  drflac_uint8 sig[4];
55773  if (onRead(pUserData, sig, 4) != 4) {
55774  return DRFLAC_FALSE;
55775  }
55776  bytesRemainingInPage -= 4;
55777  if (sig[0] == 'F' && sig[1] == 'L' && sig[2] == 'A' && sig[3] == 'C') {
55778  drflac_uint8 mappingVersion[2];
55779  if (onRead(pUserData, mappingVersion, 2) != 2) {
55780  return DRFLAC_FALSE;
55781  }
55782  if (mappingVersion[0] != 1) {
55783  return DRFLAC_FALSE;
55784  }
55785  if (!onSeek(pUserData, 2, drflac_seek_origin_current)) {
55786  return DRFLAC_FALSE;
55787  }
55788  if (onRead(pUserData, sig, 4) != 4) {
55789  return DRFLAC_FALSE;
55790  }
55791  if (sig[0] == 'f' && sig[1] == 'L' && sig[2] == 'a' && sig[3] == 'C') {
55792  drflac_streaminfo streaminfo;
55793  drflac_uint8 isLastBlock;
55794  drflac_uint8 blockType;
55795  drflac_uint32 blockSize;
55796  if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
55797  return DRFLAC_FALSE;
55798  }
55799  if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
55800  return DRFLAC_FALSE;
55801  }
55802  if (drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
55804  pInit->sampleRate = streaminfo.sampleRate;
55805  pInit->channels = streaminfo.channels;
55806  pInit->bitsPerSample = streaminfo.bitsPerSample;
55807  pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
55809  pInit->hasMetadataBlocks = !isLastBlock;
55810  if (onMeta) {
55811  drflac_metadata metadata;
55813  metadata.pRawData = NULL;
55814  metadata.rawDataSize = 0;
55815  metadata.data.streaminfo = streaminfo;
55816  onMeta(pUserDataMD, &metadata);
55817  }
55818  pInit->runningFilePos += pageBodySize;
55819  pInit->oggFirstBytePos = pInit->runningFilePos - 79;
55820  pInit->oggSerial = header.serialNumber;
55821  pInit->oggBosHeader = header;
55822  break;
55823  } else {
55824  return DRFLAC_FALSE;
55825  }
55826  } else {
55827  return DRFLAC_FALSE;
55828  }
55829  } else {
55830  if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
55831  return DRFLAC_FALSE;
55832  }
55833  }
55834  } else {
55835  if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
55836  return DRFLAC_FALSE;
55837  }
55838  }
55839  } else {
55840  if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) {
55841  return DRFLAC_FALSE;
55842  }
55843  }
55844  pInit->runningFilePos += pageBodySize;
55845  if (drflac_ogg__read_page_header(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
55846  return DRFLAC_FALSE;
55847  }
55848  pInit->runningFilePos += bytesRead;
55849  }
55850  pInit->hasMetadataBlocks = DRFLAC_TRUE;
55851  return DRFLAC_TRUE;
55852 }
55853 #endif
55854 static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
55855 {
55856  drflac_bool32 relaxed;
55857  drflac_uint8 id[4];
55858  if (pInit == NULL || onRead == NULL || onSeek == NULL) {
55859  return DRFLAC_FALSE;
55860  }
55861  DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
55862  pInit->onRead = onRead;
55863  pInit->onSeek = onSeek;
55864  pInit->onMeta = onMeta;
55865  pInit->container = container;
55866  pInit->pUserData = pUserData;
55867  pInit->pUserDataMD = pUserDataMD;
55868  pInit->bs.onRead = onRead;
55869  pInit->bs.onSeek = onSeek;
55870  pInit->bs.pUserData = pUserData;
55871  drflac__reset_cache(&pInit->bs);
55872  relaxed = container != drflac_container_unknown;
55873  for (;;) {
55874  if (onRead(pUserData, id, 4) != 4) {
55875  return DRFLAC_FALSE;
55876  }
55877  pInit->runningFilePos += 4;
55878  if (id[0] == 'I' && id[1] == 'D' && id[2] == '3') {
55879  drflac_uint8 header[6];
55880  drflac_uint8 flags;
55881  drflac_uint32 headerSize;
55882  if (onRead(pUserData, header, 6) != 6) {
55883  return DRFLAC_FALSE;
55884  }
55885  pInit->runningFilePos += 6;
55886  flags = header[1];
55887  DRFLAC_COPY_MEMORY(&headerSize, header+2, 4);
55888  headerSize = drflac__unsynchsafe_32(drflac__be2host_32(headerSize));
55889  if (flags & 0x10) {
55890  headerSize += 10;
55891  }
55892  if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
55893  return DRFLAC_FALSE;
55894  }
55895  pInit->runningFilePos += headerSize;
55896  } else {
55897  break;
55898  }
55899  }
55900  if (id[0] == 'f' && id[1] == 'L' && id[2] == 'a' && id[3] == 'C') {
55901  return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
55902  }
55903 #ifndef DR_FLAC_NO_OGG
55904  if (id[0] == 'O' && id[1] == 'g' && id[2] == 'g' && id[3] == 'S') {
55905  return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
55906  }
55907 #endif
55908  if (relaxed) {
55909  if (container == drflac_container_native) {
55910  return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
55911  }
55912 #ifndef DR_FLAC_NO_OGG
55913  if (container == drflac_container_ogg) {
55914  return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
55915  }
55916 #endif
55917  }
55918  return DRFLAC_FALSE;
55919 }
55920 static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
55921 {
55922  DRFLAC_ASSERT(pFlac != NULL);
55923  DRFLAC_ASSERT(pInit != NULL);
55924  DRFLAC_ZERO_MEMORY(pFlac, sizeof(*pFlac));
55925  pFlac->bs = pInit->bs;
55926  pFlac->onMeta = pInit->onMeta;
55927  pFlac->pUserDataMD = pInit->pUserDataMD;
55929  pFlac->sampleRate = pInit->sampleRate;
55930  pFlac->channels = (drflac_uint8)pInit->channels;
55931  pFlac->bitsPerSample = (drflac_uint8)pInit->bitsPerSample;
55932  pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount;
55933  pFlac->container = pInit->container;
55934 }
55935 static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
55936 {
55938  drflac_uint32 allocationSize;
55939  drflac_uint32 wholeSIMDVectorCountPerChannel;
55940  drflac_uint32 decodedSamplesAllocationSize;
55941 #ifndef DR_FLAC_NO_OGG
55942  drflac_oggbs oggbs;
55943 #endif
55944  drflac_uint64 firstFramePos;
55945  drflac_uint64 seektablePos;
55946  drflac_uint32 seektableSize;
55947  drflac_allocation_callbacks allocationCallbacks;
55948  drflac* pFlac;
55950  if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
55951  return NULL;
55952  }
55953  if (pAllocationCallbacks != NULL) {
55954  allocationCallbacks = *pAllocationCallbacks;
55955  if (allocationCallbacks.onFree == NULL || (allocationCallbacks.onMalloc == NULL && allocationCallbacks.onRealloc == NULL)) {
55956  return NULL;
55957  }
55958  } else {
55959  allocationCallbacks.pUserData = NULL;
55960  allocationCallbacks.onMalloc = drflac__malloc_default;
55961  allocationCallbacks.onRealloc = drflac__realloc_default;
55962  allocationCallbacks.onFree = drflac__free_default;
55963  }
55964  allocationSize = sizeof(drflac);
55965  if ((init.maxBlockSizeInPCMFrames % (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) == 0) {
55966  wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32)));
55967  } else {
55968  wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) + 1;
55969  }
55970  decodedSamplesAllocationSize = wholeSIMDVectorCountPerChannel * DRFLAC_MAX_SIMD_VECTOR_SIZE * init.channels;
55971  allocationSize += decodedSamplesAllocationSize;
55972  allocationSize += DRFLAC_MAX_SIMD_VECTOR_SIZE;
55973 #ifndef DR_FLAC_NO_OGG
55974  if (init.container == drflac_container_ogg) {
55975  allocationSize += sizeof(drflac_oggbs);
55976  }
55977  DRFLAC_ZERO_MEMORY(&oggbs, sizeof(oggbs));
55978  if (init.container == drflac_container_ogg) {
55979  oggbs.onRead = onRead;
55980  oggbs.onSeek = onSeek;
55981  oggbs.pUserData = pUserData;
55982  oggbs.currentBytePos = init.oggFirstBytePos;
55983  oggbs.firstBytePos = init.oggFirstBytePos;
55984  oggbs.serialNumber = init.oggSerial;
55985  oggbs.bosPageHeader = init.oggBosHeader;
55986  oggbs.bytesRemainingInPage = 0;
55987  }
55988 #endif
55989  firstFramePos = 42;
55990  seektablePos = 0;
55991  seektableSize = 0;
55992  if (init.hasMetadataBlocks) {
55993  drflac_read_proc onReadOverride = onRead;
55994  drflac_seek_proc onSeekOverride = onSeek;
55995  void* pUserDataOverride = pUserData;
55996 #ifndef DR_FLAC_NO_OGG
55997  if (init.container == drflac_container_ogg) {
55998  onReadOverride = drflac__on_read_ogg;
55999  onSeekOverride = drflac__on_seek_ogg;
56000  pUserDataOverride = (void*)&oggbs;
56001  }
56002 #endif
56003  if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
56004  return NULL;
56005  }
56006  allocationSize += seektableSize;
56007  }
56008  pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
56009  if (pFlac == NULL) {
56010  return NULL;
56011  }
56012  drflac__init_from_info(pFlac, &init);
56013  pFlac->allocationCallbacks = allocationCallbacks;
56015 #ifndef DR_FLAC_NO_OGG
56016  if (init.container == drflac_container_ogg) {
56017  drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + seektableSize);
56018  *pInternalOggbs = oggbs;
56019  pFlac->bs.onRead = drflac__on_read_ogg;
56020  pFlac->bs.onSeek = drflac__on_seek_ogg;
56021  pFlac->bs.pUserData = (void*)pInternalOggbs;
56022  pFlac->_oggbs = (void*)pInternalOggbs;
56023  }
56024 #endif
56025  pFlac->firstFLACFramePosInBytes = firstFramePos;
56026 #ifndef DR_FLAC_NO_OGG
56027  if (init.container == drflac_container_ogg)
56028  {
56029  pFlac->pSeekpoints = NULL;
56030  pFlac->seekpointCount = 0;
56031  }
56032  else
56033 #endif
56034  {
56035  if (seektablePos != 0) {
56036  pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
56037  pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
56038  DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
56039  DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
56040  if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
56041  if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
56042  drflac_uint32 iSeekpoint;
56043  for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
56044  pFlac->pSeekpoints[iSeekpoint].firstPCMFrame = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
56045  pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
56046  pFlac->pSeekpoints[iSeekpoint].pcmFrameCount = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
56047  }
56048  } else {
56049  pFlac->pSeekpoints = NULL;
56050  pFlac->seekpointCount = 0;
56051  }
56052  if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
56053  drflac__free_from_callbacks(pFlac, &allocationCallbacks);
56054  return NULL;
56055  }
56056  } else {
56057  pFlac->pSeekpoints = NULL;
56058  pFlac->seekpointCount = 0;
56059  }
56060  }
56061  }
56062  if (!init.hasStreamInfoBlock) {
56063  pFlac->currentFLACFrame.header = init.firstFrameHeader;
56064  for (;;) {
56065  drflac_result result = drflac__decode_flac_frame(pFlac);
56066  if (result == DRFLAC_SUCCESS) {
56067  break;
56068  } else {
56069  if (result == DRFLAC_CRC_MISMATCH) {
56071  drflac__free_from_callbacks(pFlac, &allocationCallbacks);
56072  return NULL;
56073  }
56074  continue;
56075  } else {
56076  drflac__free_from_callbacks(pFlac, &allocationCallbacks);
56077  return NULL;
56078  }
56079  }
56080  }
56081  }
56082  return pFlac;
56083 }
56084 #ifndef DR_FLAC_NO_STDIO
56085 #include <stdio.h>
56086 #include <wchar.h>
56087 #include <errno.h>
56089 {
56090  switch (e)
56091  {
56092  case 0: return DRFLAC_SUCCESS;
56093  #ifdef EPERM
56094  case EPERM: return DRFLAC_INVALID_OPERATION;
56095  #endif
56096  #ifdef ENOENT
56097  case ENOENT: return DRFLAC_DOES_NOT_EXIST;
56098  #endif
56099  #ifdef ESRCH
56100  case ESRCH: return DRFLAC_DOES_NOT_EXIST;
56101  #endif
56102  #ifdef EINTR
56103  case EINTR: return DRFLAC_INTERRUPT;
56104  #endif
56105  #ifdef EIO
56106  case EIO: return DRFLAC_IO_ERROR;
56107  #endif
56108  #ifdef ENXIO
56109  case ENXIO: return DRFLAC_DOES_NOT_EXIST;
56110  #endif
56111  #ifdef E2BIG
56112  case E2BIG: return DRFLAC_INVALID_ARGS;
56113  #endif
56114  #ifdef ENOEXEC
56115  case ENOEXEC: return DRFLAC_INVALID_FILE;
56116  #endif
56117  #ifdef EBADF
56118  case EBADF: return DRFLAC_INVALID_FILE;
56119  #endif
56120  #ifdef ECHILD
56121  case ECHILD: return DRFLAC_ERROR;
56122  #endif
56123  #ifdef EAGAIN
56124  case EAGAIN: return DRFLAC_UNAVAILABLE;
56125  #endif
56126  #ifdef ENOMEM
56127  case ENOMEM: return DRFLAC_OUT_OF_MEMORY;
56128  #endif
56129  #ifdef EACCES
56130  case EACCES: return DRFLAC_ACCESS_DENIED;
56131  #endif
56132  #ifdef EFAULT
56133  case EFAULT: return DRFLAC_BAD_ADDRESS;
56134  #endif
56135  #ifdef ENOTBLK
56136  case ENOTBLK: return DRFLAC_ERROR;
56137  #endif
56138  #ifdef EBUSY
56139  case EBUSY: return DRFLAC_BUSY;
56140  #endif
56141  #ifdef EEXIST
56142  case EEXIST: return DRFLAC_ALREADY_EXISTS;
56143  #endif
56144  #ifdef EXDEV
56145  case EXDEV: return DRFLAC_ERROR;
56146  #endif
56147  #ifdef ENODEV
56148  case ENODEV: return DRFLAC_DOES_NOT_EXIST;
56149  #endif
56150  #ifdef ENOTDIR
56151  case ENOTDIR: return DRFLAC_NOT_DIRECTORY;
56152  #endif
56153  #ifdef EISDIR
56154  case EISDIR: return DRFLAC_IS_DIRECTORY;
56155  #endif
56156  #ifdef EINVAL
56157  case EINVAL: return DRFLAC_INVALID_ARGS;
56158  #endif
56159  #ifdef ENFILE
56160  case ENFILE: return DRFLAC_TOO_MANY_OPEN_FILES;
56161  #endif
56162  #ifdef EMFILE
56163  case EMFILE: return DRFLAC_TOO_MANY_OPEN_FILES;
56164  #endif
56165  #ifdef ENOTTY
56166  case ENOTTY: return DRFLAC_INVALID_OPERATION;
56167  #endif
56168  #ifdef ETXTBSY
56169  case ETXTBSY: return DRFLAC_BUSY;
56170  #endif
56171  #ifdef EFBIG
56172  case EFBIG: return DRFLAC_TOO_BIG;
56173  #endif
56174  #ifdef ENOSPC
56175  case ENOSPC: return DRFLAC_NO_SPACE;
56176  #endif
56177  #ifdef ESPIPE
56178  case ESPIPE: return DRFLAC_BAD_SEEK;
56179  #endif
56180  #ifdef EROFS
56181  case EROFS: return DRFLAC_ACCESS_DENIED;
56182  #endif
56183  #ifdef EMLINK
56184  case EMLINK: return DRFLAC_TOO_MANY_LINKS;
56185  #endif
56186  #ifdef EPIPE
56187  case EPIPE: return DRFLAC_BAD_PIPE;
56188  #endif
56189  #ifdef EDOM
56190  case EDOM: return DRFLAC_OUT_OF_RANGE;
56191  #endif
56192  #ifdef ERANGE
56193  case ERANGE: return DRFLAC_OUT_OF_RANGE;
56194  #endif
56195  #ifdef EDEADLK
56196  case EDEADLK: return DRFLAC_DEADLOCK;
56197  #endif
56198  #ifdef ENAMETOOLONG
56199  case ENAMETOOLONG: return DRFLAC_PATH_TOO_LONG;
56200  #endif
56201  #ifdef ENOLCK
56202  case ENOLCK: return DRFLAC_ERROR;
56203  #endif
56204  #ifdef ENOSYS
56205  case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
56206  #endif
56207  #ifdef ENOTEMPTY
56208  case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
56209  #endif
56210  #ifdef ELOOP
56211  case ELOOP: return DRFLAC_TOO_MANY_LINKS;
56212  #endif
56213  #ifdef ENOMSG
56214  case ENOMSG: return DRFLAC_NO_MESSAGE;
56215  #endif
56216  #ifdef EIDRM
56217  case EIDRM: return DRFLAC_ERROR;
56218  #endif
56219  #ifdef ECHRNG
56220  case ECHRNG: return DRFLAC_ERROR;
56221  #endif
56222  #ifdef EL2NSYNC
56223  case EL2NSYNC: return DRFLAC_ERROR;
56224  #endif
56225  #ifdef EL3HLT
56226  case EL3HLT: return DRFLAC_ERROR;
56227  #endif
56228  #ifdef EL3RST
56229  case EL3RST: return DRFLAC_ERROR;
56230  #endif
56231  #ifdef ELNRNG
56232  case ELNRNG: return DRFLAC_OUT_OF_RANGE;
56233  #endif
56234  #ifdef EUNATCH
56235  case EUNATCH: return DRFLAC_ERROR;
56236  #endif
56237  #ifdef ENOCSI
56238  case ENOCSI: return DRFLAC_ERROR;
56239  #endif
56240  #ifdef EL2HLT
56241  case EL2HLT: return DRFLAC_ERROR;
56242  #endif
56243  #ifdef EBADE
56244  case EBADE: return DRFLAC_ERROR;
56245  #endif
56246  #ifdef EBADR
56247  case EBADR: return DRFLAC_ERROR;
56248  #endif
56249  #ifdef EXFULL
56250  case EXFULL: return DRFLAC_ERROR;
56251  #endif
56252  #ifdef ENOANO
56253  case ENOANO: return DRFLAC_ERROR;
56254  #endif
56255  #ifdef EBADRQC
56256  case EBADRQC: return DRFLAC_ERROR;
56257  #endif
56258  #ifdef EBADSLT
56259  case EBADSLT: return DRFLAC_ERROR;
56260  #endif
56261  #ifdef EBFONT
56262  case EBFONT: return DRFLAC_INVALID_FILE;
56263  #endif
56264  #ifdef ENOSTR
56265  case ENOSTR: return DRFLAC_ERROR;
56266  #endif
56267  #ifdef ENODATA
56268  case ENODATA: return DRFLAC_NO_DATA_AVAILABLE;
56269  #endif
56270  #ifdef ETIME
56271  case ETIME: return DRFLAC_TIMEOUT;
56272  #endif
56273  #ifdef ENOSR
56274  case ENOSR: return DRFLAC_NO_DATA_AVAILABLE;
56275  #endif
56276  #ifdef ENONET
56277  case ENONET: return DRFLAC_NO_NETWORK;
56278  #endif
56279  #ifdef ENOPKG
56280  case ENOPKG: return DRFLAC_ERROR;
56281  #endif
56282  #ifdef EREMOTE
56283  case EREMOTE: return DRFLAC_ERROR;
56284  #endif
56285  #ifdef ENOLINK
56286  case ENOLINK: return DRFLAC_ERROR;
56287  #endif
56288  #ifdef EADV
56289  case EADV: return DRFLAC_ERROR;
56290  #endif
56291  #ifdef ESRMNT
56292  case ESRMNT: return DRFLAC_ERROR;
56293  #endif
56294  #ifdef ECOMM
56295  case ECOMM: return DRFLAC_ERROR;
56296  #endif
56297  #ifdef EPROTO
56298  case EPROTO: return DRFLAC_ERROR;
56299  #endif
56300  #ifdef EMULTIHOP
56301  case EMULTIHOP: return DRFLAC_ERROR;
56302  #endif
56303  #ifdef EDOTDOT
56304  case EDOTDOT: return DRFLAC_ERROR;
56305  #endif
56306  #ifdef EBADMSG
56307  case EBADMSG: return DRFLAC_BAD_MESSAGE;
56308  #endif
56309  #ifdef EOVERFLOW
56310  case EOVERFLOW: return DRFLAC_TOO_BIG;
56311  #endif
56312  #ifdef ENOTUNIQ
56313  case ENOTUNIQ: return DRFLAC_NOT_UNIQUE;
56314  #endif
56315  #ifdef EBADFD
56316  case EBADFD: return DRFLAC_ERROR;
56317  #endif
56318  #ifdef EREMCHG
56319  case EREMCHG: return DRFLAC_ERROR;
56320  #endif
56321  #ifdef ELIBACC
56322  case ELIBACC: return DRFLAC_ACCESS_DENIED;
56323  #endif
56324  #ifdef ELIBBAD
56325  case ELIBBAD: return DRFLAC_INVALID_FILE;
56326  #endif
56327  #ifdef ELIBSCN
56328  case ELIBSCN: return DRFLAC_INVALID_FILE;
56329  #endif
56330  #ifdef ELIBMAX
56331  case ELIBMAX: return DRFLAC_ERROR;
56332  #endif
56333  #ifdef ELIBEXEC
56334  case ELIBEXEC: return DRFLAC_ERROR;
56335  #endif
56336  #ifdef EILSEQ
56337  case EILSEQ: return DRFLAC_INVALID_DATA;
56338  #endif
56339  #ifdef ERESTART
56340  case ERESTART: return DRFLAC_ERROR;
56341  #endif
56342  #ifdef ESTRPIPE
56343  case ESTRPIPE: return DRFLAC_ERROR;
56344  #endif
56345  #ifdef EUSERS
56346  case EUSERS: return DRFLAC_ERROR;
56347  #endif
56348  #ifdef ENOTSOCK
56349  case ENOTSOCK: return DRFLAC_NOT_SOCKET;
56350  #endif
56351  #ifdef EDESTADDRREQ
56352  case EDESTADDRREQ: return DRFLAC_NO_ADDRESS;
56353  #endif
56354  #ifdef EMSGSIZE
56355  case EMSGSIZE: return DRFLAC_TOO_BIG;
56356  #endif
56357  #ifdef EPROTOTYPE
56358  case EPROTOTYPE: return DRFLAC_BAD_PROTOCOL;
56359  #endif
56360  #ifdef ENOPROTOOPT
56361  case ENOPROTOOPT: return DRFLAC_PROTOCOL_UNAVAILABLE;
56362  #endif
56363  #ifdef EPROTONOSUPPORT
56364  case EPROTONOSUPPORT: return DRFLAC_PROTOCOL_NOT_SUPPORTED;
56365  #endif
56366  #ifdef ESOCKTNOSUPPORT
56367  case ESOCKTNOSUPPORT: return DRFLAC_SOCKET_NOT_SUPPORTED;
56368  #endif
56369  #ifdef EOPNOTSUPP
56370  case EOPNOTSUPP: return DRFLAC_INVALID_OPERATION;
56371  #endif
56372  #ifdef EPFNOSUPPORT
56373  case EPFNOSUPPORT: return DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED;
56374  #endif
56375  #ifdef EAFNOSUPPORT
56376  case EAFNOSUPPORT: return DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED;
56377  #endif
56378  #ifdef EADDRINUSE
56379  case EADDRINUSE: return DRFLAC_ALREADY_IN_USE;
56380  #endif
56381  #ifdef EADDRNOTAVAIL
56382  case EADDRNOTAVAIL: return DRFLAC_ERROR;
56383  #endif
56384  #ifdef ENETDOWN
56385  case ENETDOWN: return DRFLAC_NO_NETWORK;
56386  #endif
56387  #ifdef ENETUNREACH
56388  case ENETUNREACH: return DRFLAC_NO_NETWORK;
56389  #endif
56390  #ifdef ENETRESET
56391  case ENETRESET: return DRFLAC_NO_NETWORK;
56392  #endif
56393  #ifdef ECONNABORTED
56394  case ECONNABORTED: return DRFLAC_NO_NETWORK;
56395  #endif
56396  #ifdef ECONNRESET
56397  case ECONNRESET: return DRFLAC_CONNECTION_RESET;
56398  #endif
56399  #ifdef ENOBUFS
56400  case ENOBUFS: return DRFLAC_NO_SPACE;
56401  #endif
56402  #ifdef EISCONN
56403  case EISCONN: return DRFLAC_ALREADY_CONNECTED;
56404  #endif
56405  #ifdef ENOTCONN
56406  case ENOTCONN: return DRFLAC_NOT_CONNECTED;
56407  #endif
56408  #ifdef ESHUTDOWN
56409  case ESHUTDOWN: return DRFLAC_ERROR;
56410  #endif
56411  #ifdef ETOOMANYREFS
56412  case ETOOMANYREFS: return DRFLAC_ERROR;
56413  #endif
56414  #ifdef ETIMEDOUT
56415  case ETIMEDOUT: return DRFLAC_TIMEOUT;
56416  #endif
56417  #ifdef ECONNREFUSED
56418  case ECONNREFUSED: return DRFLAC_CONNECTION_REFUSED;
56419  #endif
56420  #ifdef EHOSTDOWN
56421  case EHOSTDOWN: return DRFLAC_NO_HOST;
56422  #endif
56423  #ifdef EHOSTUNREACH
56424  case EHOSTUNREACH: return DRFLAC_NO_HOST;
56425  #endif
56426  #ifdef EALREADY
56427  case EALREADY: return DRFLAC_IN_PROGRESS;
56428  #endif
56429  #ifdef EINPROGRESS
56430  case EINPROGRESS: return DRFLAC_IN_PROGRESS;
56431  #endif
56432  #ifdef ESTALE
56433  case ESTALE: return DRFLAC_INVALID_FILE;
56434  #endif
56435  #ifdef EUCLEAN
56436  case EUCLEAN: return DRFLAC_ERROR;
56437  #endif
56438  #ifdef ENOTNAM
56439  case ENOTNAM: return DRFLAC_ERROR;
56440  #endif
56441  #ifdef ENAVAIL
56442  case ENAVAIL: return DRFLAC_ERROR;
56443  #endif
56444  #ifdef EISNAM
56445  case EISNAM: return DRFLAC_ERROR;
56446  #endif
56447  #ifdef EREMOTEIO
56448  case EREMOTEIO: return DRFLAC_IO_ERROR;
56449  #endif
56450  #ifdef EDQUOT
56451  case EDQUOT: return DRFLAC_NO_SPACE;
56452  #endif
56453  #ifdef ENOMEDIUM
56454  case ENOMEDIUM: return DRFLAC_DOES_NOT_EXIST;
56455  #endif
56456  #ifdef EMEDIUMTYPE
56457  case EMEDIUMTYPE: return DRFLAC_ERROR;
56458  #endif
56459  #ifdef ECANCELED
56460  case ECANCELED: return DRFLAC_CANCELLED;
56461  #endif
56462  #ifdef ENOKEY
56463  case ENOKEY: return DRFLAC_ERROR;
56464  #endif
56465  #ifdef EKEYEXPIRED
56466  case EKEYEXPIRED: return DRFLAC_ERROR;
56467  #endif
56468  #ifdef EKEYREVOKED
56469  case EKEYREVOKED: return DRFLAC_ERROR;
56470  #endif
56471  #ifdef EKEYREJECTED
56472  case EKEYREJECTED: return DRFLAC_ERROR;
56473  #endif
56474  #ifdef EOWNERDEAD
56475  case EOWNERDEAD: return DRFLAC_ERROR;
56476  #endif
56477  #ifdef ENOTRECOVERABLE
56478  case ENOTRECOVERABLE: return DRFLAC_ERROR;
56479  #endif
56480  #ifdef ERFKILL
56481  case ERFKILL: return DRFLAC_ERROR;
56482  #endif
56483  #ifdef EHWPOISON
56484  case EHWPOISON: return DRFLAC_ERROR;
56485  #endif
56486  default: return DRFLAC_ERROR;
56487  }
56488 }
56489 static drflac_result drflac_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
56490 {
56491 #if defined(_MSC_VER) && _MSC_VER >= 1400
56492  errno_t err;
56493 #endif
56494  if (ppFile != NULL) {
56495  *ppFile = NULL;
56496  }
56497  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
56498  return DRFLAC_INVALID_ARGS;
56499  }
56500 #if defined(_MSC_VER) && _MSC_VER >= 1400
56501  err = fopen_s(ppFile, pFilePath, pOpenMode);
56502  if (err != 0) {
56503  return drflac_result_from_errno(err);
56504  }
56505 #else
56506 #if defined(_WIN32) || defined(__APPLE__)
56507  *ppFile = fopen(pFilePath, pOpenMode);
56508 #else
56509  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
56510  *ppFile = fopen64(pFilePath, pOpenMode);
56511  #else
56512  *ppFile = fopen(pFilePath, pOpenMode);
56513  #endif
56514 #endif
56515  if (*ppFile == NULL) {
56517  if (result == DRFLAC_SUCCESS) {
56518  result = DRFLAC_ERROR;
56519  }
56520  return result;
56521  }
56522 #endif
56523  return DRFLAC_SUCCESS;
56524 }
56525 #if defined(_WIN32)
56526  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
56527  #define DRFLAC_HAS_WFOPEN
56528  #endif
56529 #endif
56530 static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
56531 {
56532  if (ppFile != NULL) {
56533  *ppFile = NULL;
56534  }
56535  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
56536  return DRFLAC_INVALID_ARGS;
56537  }
56538 #if defined(DRFLAC_HAS_WFOPEN)
56539  {
56540  #if defined(_MSC_VER) && _MSC_VER >= 1400
56541  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
56542  if (err != 0) {
56543  return drflac_result_from_errno(err);
56544  }
56545  #else
56546  *ppFile = _wfopen(pFilePath, pOpenMode);
56547  if (*ppFile == NULL) {
56549  }
56550  #endif
56551  (void)pAllocationCallbacks;
56552  }
56553 #else
56554  {
56555  mbstate_t mbs;
56556  size_t lenMB;
56557  const wchar_t* pFilePathTemp = pFilePath;
56558  char* pFilePathMB = NULL;
56559  char pOpenModeMB[32] = {0};
56560  DRFLAC_ZERO_OBJECT(&mbs);
56561  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
56562  if (lenMB == (size_t)-1) {
56564  }
56565  pFilePathMB = (char*)drflac__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
56566  if (pFilePathMB == NULL) {
56567  return DRFLAC_OUT_OF_MEMORY;
56568  }
56569  pFilePathTemp = pFilePath;
56570  DRFLAC_ZERO_OBJECT(&mbs);
56571  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
56572  {
56573  size_t i = 0;
56574  for (;;) {
56575  if (pOpenMode[i] == 0) {
56576  pOpenModeMB[i] = '\0';
56577  break;
56578  }
56579  pOpenModeMB[i] = (char)pOpenMode[i];
56580  i += 1;
56581  }
56582  }
56583  *ppFile = fopen(pFilePathMB, pOpenModeMB);
56584  drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
56585  }
56586  if (*ppFile == NULL) {
56587  return DRFLAC_ERROR;
56588  }
56589 #endif
56590  return DRFLAC_SUCCESS;
56591 }
56592 static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
56593 {
56594  return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
56595 }
56596 static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
56597 {
56598  DRFLAC_ASSERT(offset >= 0);
56599  return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
56600 }
56601 DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
56602 {
56603  drflac* pFlac;
56604  FILE* pFile;
56605  if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
56606  return NULL;
56607  }
56608  pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
56609  if (pFlac == NULL) {
56610  fclose(pFile);
56611  return NULL;
56612  }
56613  return pFlac;
56614 }
56615 DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
56616 {
56617  drflac* pFlac;
56618  FILE* pFile;
56619  if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
56620  return NULL;
56621  }
56622  pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
56623  if (pFlac == NULL) {
56624  fclose(pFile);
56625  return NULL;
56626  }
56627  return pFlac;
56628 }
56629 DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
56630 {
56631  drflac* pFlac;
56632  FILE* pFile;
56633  if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
56634  return NULL;
56635  }
56636  pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
56637  if (pFlac == NULL) {
56638  fclose(pFile);
56639  return pFlac;
56640  }
56641  return pFlac;
56642 }
56643 DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
56644 {
56645  drflac* pFlac;
56646  FILE* pFile;
56647  if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
56648  return NULL;
56649  }
56650  pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
56651  if (pFlac == NULL) {
56652  fclose(pFile);
56653  return pFlac;
56654  }
56655  return pFlac;
56656 }
56657 #endif
56658 static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
56659 {
56660  drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
56661  size_t bytesRemaining;
56662  DRFLAC_ASSERT(memoryStream != NULL);
56663  DRFLAC_ASSERT(memoryStream->dataSize >= memoryStream->currentReadPos);
56664  bytesRemaining = memoryStream->dataSize - memoryStream->currentReadPos;
56665  if (bytesToRead > bytesRemaining) {
56666  bytesToRead = bytesRemaining;
56667  }
56668  if (bytesToRead > 0) {
56669  DRFLAC_COPY_MEMORY(bufferOut, memoryStream->data + memoryStream->currentReadPos, bytesToRead);
56670  memoryStream->currentReadPos += bytesToRead;
56671  }
56672  return bytesToRead;
56673 }
56674 static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
56675 {
56676  drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
56677  DRFLAC_ASSERT(memoryStream != NULL);
56678  DRFLAC_ASSERT(offset >= 0);
56679  if (offset > (drflac_int64)memoryStream->dataSize) {
56680  return DRFLAC_FALSE;
56681  }
56682  if (origin == drflac_seek_origin_current) {
56683  if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
56684  memoryStream->currentReadPos += offset;
56685  } else {
56686  return DRFLAC_FALSE;
56687  }
56688  } else {
56689  if ((drflac_uint32)offset <= memoryStream->dataSize) {
56690  memoryStream->currentReadPos = offset;
56691  } else {
56692  return DRFLAC_FALSE;
56693  }
56694  }
56695  return DRFLAC_TRUE;
56696 }
56697 DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks)
56698 {
56699  drflac__memory_stream memoryStream;
56700  drflac* pFlac;
56701  memoryStream.data = (const drflac_uint8*)pData;
56702  memoryStream.dataSize = dataSize;
56703  memoryStream.currentReadPos = 0;
56704  pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
56705  if (pFlac == NULL) {
56706  return NULL;
56707  }
56708  pFlac->memoryStream = memoryStream;
56709 #ifndef DR_FLAC_NO_OGG
56710  if (pFlac->container == drflac_container_ogg)
56711  {
56712  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
56713  oggbs->pUserData = &pFlac->memoryStream;
56714  }
56715  else
56716 #endif
56717  {
56718  pFlac->bs.pUserData = &pFlac->memoryStream;
56719  }
56720  return pFlac;
56721 }
56722 DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t dataSize, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
56723 {
56724  drflac__memory_stream memoryStream;
56725  drflac* pFlac;
56726  memoryStream.data = (const drflac_uint8*)pData;
56727  memoryStream.dataSize = dataSize;
56728  memoryStream.currentReadPos = 0;
56729  pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
56730  if (pFlac == NULL) {
56731  return NULL;
56732  }
56733  pFlac->memoryStream = memoryStream;
56734 #ifndef DR_FLAC_NO_OGG
56735  if (pFlac->container == drflac_container_ogg)
56736  {
56737  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
56738  oggbs->pUserData = &pFlac->memoryStream;
56739  }
56740  else
56741 #endif
56742  {
56743  pFlac->bs.pUserData = &pFlac->memoryStream;
56744  }
56745  return pFlac;
56746 }
56747 DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
56748 {
56749  return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
56750 }
56751 DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
56752 {
56753  return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
56754 }
56756 {
56757  return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
56758 }
56760 {
56761  return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
56762 }
56764 {
56765  if (pFlac == NULL) {
56766  return;
56767  }
56768 #ifndef DR_FLAC_NO_STDIO
56769  if (pFlac->bs.onRead == drflac__on_read_stdio) {
56770  fclose((FILE*)pFlac->bs.pUserData);
56771  }
56772 #ifndef DR_FLAC_NO_OGG
56773  if (pFlac->container == drflac_container_ogg) {
56774  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
56776  if (oggbs->onRead == drflac__on_read_stdio) {
56777  fclose((FILE*)oggbs->pUserData);
56778  }
56779  }
56780 #endif
56781 #endif
56783 }
56784 #if 0
56785 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56786 {
56787  drflac_uint64 i;
56788  for (i = 0; i < frameCount; ++i) {
56789  drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
56790  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
56791  drflac_uint32 right = left - side;
56792  pOutputSamples[i*2+0] = (drflac_int32)left;
56793  pOutputSamples[i*2+1] = (drflac_int32)right;
56794  }
56795 }
56796 #endif
56797 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56798 {
56799  drflac_uint64 i;
56800  drflac_uint64 frameCount4 = frameCount >> 2;
56801  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
56802  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
56803  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
56804  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
56805  for (i = 0; i < frameCount4; ++i) {
56806  drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
56807  drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
56808  drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
56809  drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
56810  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
56811  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
56812  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
56813  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
56814  drflac_uint32 right0 = left0 - side0;
56815  drflac_uint32 right1 = left1 - side1;
56816  drflac_uint32 right2 = left2 - side2;
56817  drflac_uint32 right3 = left3 - side3;
56818  pOutputSamples[i*8+0] = (drflac_int32)left0;
56819  pOutputSamples[i*8+1] = (drflac_int32)right0;
56820  pOutputSamples[i*8+2] = (drflac_int32)left1;
56821  pOutputSamples[i*8+3] = (drflac_int32)right1;
56822  pOutputSamples[i*8+4] = (drflac_int32)left2;
56823  pOutputSamples[i*8+5] = (drflac_int32)right2;
56824  pOutputSamples[i*8+6] = (drflac_int32)left3;
56825  pOutputSamples[i*8+7] = (drflac_int32)right3;
56826  }
56827  for (i = (frameCount4 << 2); i < frameCount; ++i) {
56828  drflac_uint32 left = pInputSamples0U32[i] << shift0;
56829  drflac_uint32 side = pInputSamples1U32[i] << shift1;
56830  drflac_uint32 right = left - side;
56831  pOutputSamples[i*2+0] = (drflac_int32)left;
56832  pOutputSamples[i*2+1] = (drflac_int32)right;
56833  }
56834 }
56835 #if defined(DRFLAC_SUPPORT_SSE2)
56836 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56837 {
56838  drflac_uint64 i;
56839  drflac_uint64 frameCount4 = frameCount >> 2;
56840  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
56841  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
56842  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
56843  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
56844  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
56845  for (i = 0; i < frameCount4; ++i) {
56846  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
56847  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
56848  __m128i right = _mm_sub_epi32(left, side);
56849  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
56850  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
56851  }
56852  for (i = (frameCount4 << 2); i < frameCount; ++i) {
56853  drflac_uint32 left = pInputSamples0U32[i] << shift0;
56854  drflac_uint32 side = pInputSamples1U32[i] << shift1;
56855  drflac_uint32 right = left - side;
56856  pOutputSamples[i*2+0] = (drflac_int32)left;
56857  pOutputSamples[i*2+1] = (drflac_int32)right;
56858  }
56859 }
56860 #endif
56861 #if defined(DRFLAC_SUPPORT_NEON)
56862 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56863 {
56864  drflac_uint64 i;
56865  drflac_uint64 frameCount4 = frameCount >> 2;
56866  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
56867  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
56868  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
56869  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
56870  int32x4_t shift0_4;
56871  int32x4_t shift1_4;
56872  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
56873  shift0_4 = vdupq_n_s32(shift0);
56874  shift1_4 = vdupq_n_s32(shift1);
56875  for (i = 0; i < frameCount4; ++i) {
56876  uint32x4_t left;
56877  uint32x4_t side;
56878  uint32x4_t right;
56879  left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
56880  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
56881  right = vsubq_u32(left, side);
56882  drflac__vst2q_u32((drflac_uint32*)pOutputSamples + i*8, vzipq_u32(left, right));
56883  }
56884  for (i = (frameCount4 << 2); i < frameCount; ++i) {
56885  drflac_uint32 left = pInputSamples0U32[i] << shift0;
56886  drflac_uint32 side = pInputSamples1U32[i] << shift1;
56887  drflac_uint32 right = left - side;
56888  pOutputSamples[i*2+0] = (drflac_int32)left;
56889  pOutputSamples[i*2+1] = (drflac_int32)right;
56890  }
56891 }
56892 #endif
56893 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56894 {
56895 #if defined(DRFLAC_SUPPORT_SSE2)
56896  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
56897  drflac_read_pcm_frames_s32__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
56898  } else
56899 #elif defined(DRFLAC_SUPPORT_NEON)
56900  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
56901  drflac_read_pcm_frames_s32__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
56902  } else
56903 #endif
56904  {
56905 #if 0
56906  drflac_read_pcm_frames_s32__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
56907 #else
56908  drflac_read_pcm_frames_s32__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
56909 #endif
56910  }
56911 }
56912 #if 0
56913 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56914 {
56915  drflac_uint64 i;
56916  for (i = 0; i < frameCount; ++i) {
56917  drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
56918  drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
56919  drflac_uint32 left = right + side;
56920  pOutputSamples[i*2+0] = (drflac_int32)left;
56921  pOutputSamples[i*2+1] = (drflac_int32)right;
56922  }
56923 }
56924 #endif
56925 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56926 {
56927  drflac_uint64 i;
56928  drflac_uint64 frameCount4 = frameCount >> 2;
56929  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
56930  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
56931  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
56932  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
56933  for (i = 0; i < frameCount4; ++i) {
56934  drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
56935  drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
56936  drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
56937  drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
56938  drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
56939  drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
56940  drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
56941  drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
56942  drflac_uint32 left0 = right0 + side0;
56943  drflac_uint32 left1 = right1 + side1;
56944  drflac_uint32 left2 = right2 + side2;
56945  drflac_uint32 left3 = right3 + side3;
56946  pOutputSamples[i*8+0] = (drflac_int32)left0;
56947  pOutputSamples[i*8+1] = (drflac_int32)right0;
56948  pOutputSamples[i*8+2] = (drflac_int32)left1;
56949  pOutputSamples[i*8+3] = (drflac_int32)right1;
56950  pOutputSamples[i*8+4] = (drflac_int32)left2;
56951  pOutputSamples[i*8+5] = (drflac_int32)right2;
56952  pOutputSamples[i*8+6] = (drflac_int32)left3;
56953  pOutputSamples[i*8+7] = (drflac_int32)right3;
56954  }
56955  for (i = (frameCount4 << 2); i < frameCount; ++i) {
56956  drflac_uint32 side = pInputSamples0U32[i] << shift0;
56957  drflac_uint32 right = pInputSamples1U32[i] << shift1;
56958  drflac_uint32 left = right + side;
56959  pOutputSamples[i*2+0] = (drflac_int32)left;
56960  pOutputSamples[i*2+1] = (drflac_int32)right;
56961  }
56962 }
56963 #if defined(DRFLAC_SUPPORT_SSE2)
56964 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56965 {
56966  drflac_uint64 i;
56967  drflac_uint64 frameCount4 = frameCount >> 2;
56968  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
56969  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
56970  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
56971  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
56972  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
56973  for (i = 0; i < frameCount4; ++i) {
56974  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
56975  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
56976  __m128i left = _mm_add_epi32(right, side);
56977  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
56978  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
56979  }
56980  for (i = (frameCount4 << 2); i < frameCount; ++i) {
56981  drflac_uint32 side = pInputSamples0U32[i] << shift0;
56982  drflac_uint32 right = pInputSamples1U32[i] << shift1;
56983  drflac_uint32 left = right + side;
56984  pOutputSamples[i*2+0] = (drflac_int32)left;
56985  pOutputSamples[i*2+1] = (drflac_int32)right;
56986  }
56987 }
56988 #endif
56989 #if defined(DRFLAC_SUPPORT_NEON)
56990 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
56991 {
56992  drflac_uint64 i;
56993  drflac_uint64 frameCount4 = frameCount >> 2;
56994  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
56995  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
56996  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
56997  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
56998  int32x4_t shift0_4;
56999  int32x4_t shift1_4;
57000  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57001  shift0_4 = vdupq_n_s32(shift0);
57002  shift1_4 = vdupq_n_s32(shift1);
57003  for (i = 0; i < frameCount4; ++i) {
57004  uint32x4_t side;
57005  uint32x4_t right;
57006  uint32x4_t left;
57007  side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
57008  right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
57009  left = vaddq_u32(right, side);
57010  drflac__vst2q_u32((drflac_uint32*)pOutputSamples + i*8, vzipq_u32(left, right));
57011  }
57012  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57013  drflac_uint32 side = pInputSamples0U32[i] << shift0;
57014  drflac_uint32 right = pInputSamples1U32[i] << shift1;
57015  drflac_uint32 left = right + side;
57016  pOutputSamples[i*2+0] = (drflac_int32)left;
57017  pOutputSamples[i*2+1] = (drflac_int32)right;
57018  }
57019 }
57020 #endif
57021 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57022 {
57023 #if defined(DRFLAC_SUPPORT_SSE2)
57024  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
57025  drflac_read_pcm_frames_s32__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57026  } else
57027 #elif defined(DRFLAC_SUPPORT_NEON)
57028  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
57029  drflac_read_pcm_frames_s32__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57030  } else
57031 #endif
57032  {
57033 #if 0
57034  drflac_read_pcm_frames_s32__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57035 #else
57036  drflac_read_pcm_frames_s32__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57037 #endif
57038  }
57039 }
57040 #if 0
57041 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57042 {
57043  for (drflac_uint64 i = 0; i < frameCount; ++i) {
57044  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57045  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57046  mid = (mid << 1) | (side & 0x01);
57047  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample);
57048  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample);
57049  }
57050 }
57051 #endif
57052 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57053 {
57054  drflac_uint64 i;
57055  drflac_uint64 frameCount4 = frameCount >> 2;
57056  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57057  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57058  drflac_int32 shift = unusedBitsPerSample;
57059  if (shift > 0) {
57060  shift -= 1;
57061  for (i = 0; i < frameCount4; ++i) {
57062  drflac_uint32 temp0L;
57063  drflac_uint32 temp1L;
57064  drflac_uint32 temp2L;
57065  drflac_uint32 temp3L;
57066  drflac_uint32 temp0R;
57067  drflac_uint32 temp1R;
57068  drflac_uint32 temp2R;
57069  drflac_uint32 temp3R;
57070  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57071  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57072  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57073  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57074  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57075  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57076  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57077  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57078  mid0 = (mid0 << 1) | (side0 & 0x01);
57079  mid1 = (mid1 << 1) | (side1 & 0x01);
57080  mid2 = (mid2 << 1) | (side2 & 0x01);
57081  mid3 = (mid3 << 1) | (side3 & 0x01);
57082  temp0L = (mid0 + side0) << shift;
57083  temp1L = (mid1 + side1) << shift;
57084  temp2L = (mid2 + side2) << shift;
57085  temp3L = (mid3 + side3) << shift;
57086  temp0R = (mid0 - side0) << shift;
57087  temp1R = (mid1 - side1) << shift;
57088  temp2R = (mid2 - side2) << shift;
57089  temp3R = (mid3 - side3) << shift;
57090  pOutputSamples[i*8+0] = (drflac_int32)temp0L;
57091  pOutputSamples[i*8+1] = (drflac_int32)temp0R;
57092  pOutputSamples[i*8+2] = (drflac_int32)temp1L;
57093  pOutputSamples[i*8+3] = (drflac_int32)temp1R;
57094  pOutputSamples[i*8+4] = (drflac_int32)temp2L;
57095  pOutputSamples[i*8+5] = (drflac_int32)temp2R;
57096  pOutputSamples[i*8+6] = (drflac_int32)temp3L;
57097  pOutputSamples[i*8+7] = (drflac_int32)temp3R;
57098  }
57099  } else {
57100  for (i = 0; i < frameCount4; ++i) {
57101  drflac_uint32 temp0L;
57102  drflac_uint32 temp1L;
57103  drflac_uint32 temp2L;
57104  drflac_uint32 temp3L;
57105  drflac_uint32 temp0R;
57106  drflac_uint32 temp1R;
57107  drflac_uint32 temp2R;
57108  drflac_uint32 temp3R;
57109  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57110  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57111  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57112  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57113  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57114  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57115  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57116  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57117  mid0 = (mid0 << 1) | (side0 & 0x01);
57118  mid1 = (mid1 << 1) | (side1 & 0x01);
57119  mid2 = (mid2 << 1) | (side2 & 0x01);
57120  mid3 = (mid3 << 1) | (side3 & 0x01);
57121  temp0L = (drflac_uint32)((drflac_int32)(mid0 + side0) >> 1);
57122  temp1L = (drflac_uint32)((drflac_int32)(mid1 + side1) >> 1);
57123  temp2L = (drflac_uint32)((drflac_int32)(mid2 + side2) >> 1);
57124  temp3L = (drflac_uint32)((drflac_int32)(mid3 + side3) >> 1);
57125  temp0R = (drflac_uint32)((drflac_int32)(mid0 - side0) >> 1);
57126  temp1R = (drflac_uint32)((drflac_int32)(mid1 - side1) >> 1);
57127  temp2R = (drflac_uint32)((drflac_int32)(mid2 - side2) >> 1);
57128  temp3R = (drflac_uint32)((drflac_int32)(mid3 - side3) >> 1);
57129  pOutputSamples[i*8+0] = (drflac_int32)temp0L;
57130  pOutputSamples[i*8+1] = (drflac_int32)temp0R;
57131  pOutputSamples[i*8+2] = (drflac_int32)temp1L;
57132  pOutputSamples[i*8+3] = (drflac_int32)temp1R;
57133  pOutputSamples[i*8+4] = (drflac_int32)temp2L;
57134  pOutputSamples[i*8+5] = (drflac_int32)temp2R;
57135  pOutputSamples[i*8+6] = (drflac_int32)temp3L;
57136  pOutputSamples[i*8+7] = (drflac_int32)temp3R;
57137  }
57138  }
57139  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57140  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57141  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57142  mid = (mid << 1) | (side & 0x01);
57143  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample);
57144  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample);
57145  }
57146 }
57147 #if defined(DRFLAC_SUPPORT_SSE2)
57148 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57149 {
57150  drflac_uint64 i;
57151  drflac_uint64 frameCount4 = frameCount >> 2;
57152  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57153  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57154  drflac_int32 shift = unusedBitsPerSample;
57155  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57156  if (shift == 0) {
57157  for (i = 0; i < frameCount4; ++i) {
57158  __m128i mid;
57159  __m128i side;
57160  __m128i left;
57161  __m128i right;
57162  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57163  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57164  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
57165  left = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
57166  right = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
57167  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
57168  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
57169  }
57170  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57171  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57172  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57173  mid = (mid << 1) | (side & 0x01);
57174  pOutputSamples[i*2+0] = (drflac_int32)(mid + side) >> 1;
57175  pOutputSamples[i*2+1] = (drflac_int32)(mid - side) >> 1;
57176  }
57177  } else {
57178  shift -= 1;
57179  for (i = 0; i < frameCount4; ++i) {
57180  __m128i mid;
57181  __m128i side;
57182  __m128i left;
57183  __m128i right;
57184  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57185  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57186  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
57187  left = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
57188  right = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
57189  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
57190  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
57191  }
57192  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57193  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57194  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57195  mid = (mid << 1) | (side & 0x01);
57196  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift);
57197  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift);
57198  }
57199  }
57200 }
57201 #endif
57202 #if defined(DRFLAC_SUPPORT_NEON)
57203 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57204 {
57205  drflac_uint64 i;
57206  drflac_uint64 frameCount4 = frameCount >> 2;
57207  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57208  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57209  drflac_int32 shift = unusedBitsPerSample;
57210  int32x4_t wbpsShift0_4;
57211  int32x4_t wbpsShift1_4;
57212  uint32x4_t one4;
57213  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57214  wbpsShift0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57215  wbpsShift1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57216  one4 = vdupq_n_u32(1);
57217  if (shift == 0) {
57218  for (i = 0; i < frameCount4; ++i) {
57219  uint32x4_t mid;
57220  uint32x4_t side;
57221  int32x4_t left;
57222  int32x4_t right;
57223  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
57224  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
57225  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, one4));
57226  left = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
57227  right = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
57228  drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
57229  }
57230  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57231  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57232  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57233  mid = (mid << 1) | (side & 0x01);
57234  pOutputSamples[i*2+0] = (drflac_int32)(mid + side) >> 1;
57235  pOutputSamples[i*2+1] = (drflac_int32)(mid - side) >> 1;
57236  }
57237  } else {
57238  int32x4_t shift4;
57239  shift -= 1;
57240  shift4 = vdupq_n_s32(shift);
57241  for (i = 0; i < frameCount4; ++i) {
57242  uint32x4_t mid;
57243  uint32x4_t side;
57244  int32x4_t left;
57245  int32x4_t right;
57246  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
57247  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
57248  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, one4));
57249  left = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
57250  right = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
57251  drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
57252  }
57253  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57254  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57255  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57256  mid = (mid << 1) | (side & 0x01);
57257  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift);
57258  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift);
57259  }
57260  }
57261 }
57262 #endif
57263 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57264 {
57265 #if defined(DRFLAC_SUPPORT_SSE2)
57266  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
57267  drflac_read_pcm_frames_s32__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57268  } else
57269 #elif defined(DRFLAC_SUPPORT_NEON)
57270  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
57271  drflac_read_pcm_frames_s32__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57272  } else
57273 #endif
57274  {
57275 #if 0
57276  drflac_read_pcm_frames_s32__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57277 #else
57278  drflac_read_pcm_frames_s32__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57279 #endif
57280  }
57281 }
57282 #if 0
57283 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57284 {
57285  for (drflac_uint64 i = 0; i < frameCount; ++i) {
57286  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample));
57287  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample));
57288  }
57289 }
57290 #endif
57291 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57292 {
57293  drflac_uint64 i;
57294  drflac_uint64 frameCount4 = frameCount >> 2;
57295  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57296  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57297  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57298  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57299  for (i = 0; i < frameCount4; ++i) {
57300  drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
57301  drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
57302  drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
57303  drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
57304  drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
57305  drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
57306  drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
57307  drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
57308  pOutputSamples[i*8+0] = (drflac_int32)tempL0;
57309  pOutputSamples[i*8+1] = (drflac_int32)tempR0;
57310  pOutputSamples[i*8+2] = (drflac_int32)tempL1;
57311  pOutputSamples[i*8+3] = (drflac_int32)tempR1;
57312  pOutputSamples[i*8+4] = (drflac_int32)tempL2;
57313  pOutputSamples[i*8+5] = (drflac_int32)tempR2;
57314  pOutputSamples[i*8+6] = (drflac_int32)tempL3;
57315  pOutputSamples[i*8+7] = (drflac_int32)tempR3;
57316  }
57317  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57318  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
57319  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
57320  }
57321 }
57322 #if defined(DRFLAC_SUPPORT_SSE2)
57323 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57324 {
57325  drflac_uint64 i;
57326  drflac_uint64 frameCount4 = frameCount >> 2;
57327  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57328  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57329  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57330  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57331  for (i = 0; i < frameCount4; ++i) {
57332  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
57333  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
57334  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
57335  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
57336  }
57337  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57338  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
57339  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
57340  }
57341 }
57342 #endif
57343 #if defined(DRFLAC_SUPPORT_NEON)
57344 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57345 {
57346  drflac_uint64 i;
57347  drflac_uint64 frameCount4 = frameCount >> 2;
57348  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57349  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57350  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57351  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57352  int32x4_t shift4_0 = vdupq_n_s32(shift0);
57353  int32x4_t shift4_1 = vdupq_n_s32(shift1);
57354  for (i = 0; i < frameCount4; ++i) {
57355  int32x4_t left;
57356  int32x4_t right;
57357  left = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift4_0));
57358  right = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift4_1));
57359  drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
57360  }
57361  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57362  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
57363  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
57364  }
57365 }
57366 #endif
57367 static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
57368 {
57369 #if defined(DRFLAC_SUPPORT_SSE2)
57370  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
57371  drflac_read_pcm_frames_s32__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57372  } else
57373 #elif defined(DRFLAC_SUPPORT_NEON)
57374  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
57375  drflac_read_pcm_frames_s32__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57376  } else
57377 #endif
57378  {
57379 #if 0
57380  drflac_read_pcm_frames_s32__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57381 #else
57382  drflac_read_pcm_frames_s32__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57383 #endif
57384  }
57385 }
57387 {
57388  drflac_uint64 framesRead;
57389  drflac_uint32 unusedBitsPerSample;
57390  if (pFlac == NULL || framesToRead == 0) {
57391  return 0;
57392  }
57393  if (pBufferOut == NULL) {
57394  return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
57395  }
57396  DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
57397  unusedBitsPerSample = 32 - pFlac->bitsPerSample;
57398  framesRead = 0;
57399  while (framesToRead > 0) {
57400  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
57402  break;
57403  }
57404  } else {
57407  drflac_uint64 frameCountThisIteration = framesToRead;
57408  if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
57409  frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
57410  }
57411  if (channelCount == 2) {
57412  const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
57413  const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
57414  switch (pFlac->currentFLACFrame.header.channelAssignment)
57415  {
57417  {
57418  drflac_read_pcm_frames_s32__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
57419  } break;
57421  {
57422  drflac_read_pcm_frames_s32__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
57423  } break;
57425  {
57426  drflac_read_pcm_frames_s32__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
57427  } break;
57429  default:
57430  {
57431  drflac_read_pcm_frames_s32__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
57432  } break;
57433  }
57434  } else {
57435  drflac_uint64 i;
57436  for (i = 0; i < frameCountThisIteration; ++i) {
57437  unsigned int j;
57438  for (j = 0; j < channelCount; ++j) {
57439  pBufferOut[(i*channelCount)+j] = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
57440  }
57441  }
57442  }
57443  framesRead += frameCountThisIteration;
57444  pBufferOut += frameCountThisIteration * channelCount;
57445  framesToRead -= frameCountThisIteration;
57446  pFlac->currentPCMFrame += frameCountThisIteration;
57447  pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)frameCountThisIteration;
57448  }
57449  }
57450  return framesRead;
57451 }
57452 #if 0
57453 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57454 {
57455  drflac_uint64 i;
57456  for (i = 0; i < frameCount; ++i) {
57457  drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57458  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57459  drflac_uint32 right = left - side;
57460  left >>= 16;
57461  right >>= 16;
57462  pOutputSamples[i*2+0] = (drflac_int16)left;
57463  pOutputSamples[i*2+1] = (drflac_int16)right;
57464  }
57465 }
57466 #endif
57467 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57468 {
57469  drflac_uint64 i;
57470  drflac_uint64 frameCount4 = frameCount >> 2;
57471  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57472  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57473  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57474  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57475  for (i = 0; i < frameCount4; ++i) {
57476  drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
57477  drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
57478  drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
57479  drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
57480  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
57481  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
57482  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
57483  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
57484  drflac_uint32 right0 = left0 - side0;
57485  drflac_uint32 right1 = left1 - side1;
57486  drflac_uint32 right2 = left2 - side2;
57487  drflac_uint32 right3 = left3 - side3;
57488  left0 >>= 16;
57489  left1 >>= 16;
57490  left2 >>= 16;
57491  left3 >>= 16;
57492  right0 >>= 16;
57493  right1 >>= 16;
57494  right2 >>= 16;
57495  right3 >>= 16;
57496  pOutputSamples[i*8+0] = (drflac_int16)left0;
57497  pOutputSamples[i*8+1] = (drflac_int16)right0;
57498  pOutputSamples[i*8+2] = (drflac_int16)left1;
57499  pOutputSamples[i*8+3] = (drflac_int16)right1;
57500  pOutputSamples[i*8+4] = (drflac_int16)left2;
57501  pOutputSamples[i*8+5] = (drflac_int16)right2;
57502  pOutputSamples[i*8+6] = (drflac_int16)left3;
57503  pOutputSamples[i*8+7] = (drflac_int16)right3;
57504  }
57505  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57506  drflac_uint32 left = pInputSamples0U32[i] << shift0;
57507  drflac_uint32 side = pInputSamples1U32[i] << shift1;
57508  drflac_uint32 right = left - side;
57509  left >>= 16;
57510  right >>= 16;
57511  pOutputSamples[i*2+0] = (drflac_int16)left;
57512  pOutputSamples[i*2+1] = (drflac_int16)right;
57513  }
57514 }
57515 #if defined(DRFLAC_SUPPORT_SSE2)
57516 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57517 {
57518  drflac_uint64 i;
57519  drflac_uint64 frameCount4 = frameCount >> 2;
57520  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57521  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57522  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57523  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57524  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57525  for (i = 0; i < frameCount4; ++i) {
57526  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
57527  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
57528  __m128i right = _mm_sub_epi32(left, side);
57529  left = _mm_srai_epi32(left, 16);
57530  right = _mm_srai_epi32(right, 16);
57531  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
57532  }
57533  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57534  drflac_uint32 left = pInputSamples0U32[i] << shift0;
57535  drflac_uint32 side = pInputSamples1U32[i] << shift1;
57536  drflac_uint32 right = left - side;
57537  left >>= 16;
57538  right >>= 16;
57539  pOutputSamples[i*2+0] = (drflac_int16)left;
57540  pOutputSamples[i*2+1] = (drflac_int16)right;
57541  }
57542 }
57543 #endif
57544 #if defined(DRFLAC_SUPPORT_NEON)
57545 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57546 {
57547  drflac_uint64 i;
57548  drflac_uint64 frameCount4 = frameCount >> 2;
57549  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57550  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57551  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57552  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57553  int32x4_t shift0_4;
57554  int32x4_t shift1_4;
57555  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57556  shift0_4 = vdupq_n_s32(shift0);
57557  shift1_4 = vdupq_n_s32(shift1);
57558  for (i = 0; i < frameCount4; ++i) {
57559  uint32x4_t left;
57560  uint32x4_t side;
57561  uint32x4_t right;
57562  left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
57563  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
57564  right = vsubq_u32(left, side);
57565  left = vshrq_n_u32(left, 16);
57566  right = vshrq_n_u32(right, 16);
57567  drflac__vst2q_u16((drflac_uint16*)pOutputSamples + i*8, vzip_u16(vmovn_u32(left), vmovn_u32(right)));
57568  }
57569  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57570  drflac_uint32 left = pInputSamples0U32[i] << shift0;
57571  drflac_uint32 side = pInputSamples1U32[i] << shift1;
57572  drflac_uint32 right = left - side;
57573  left >>= 16;
57574  right >>= 16;
57575  pOutputSamples[i*2+0] = (drflac_int16)left;
57576  pOutputSamples[i*2+1] = (drflac_int16)right;
57577  }
57578 }
57579 #endif
57580 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57581 {
57582 #if defined(DRFLAC_SUPPORT_SSE2)
57583  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
57584  drflac_read_pcm_frames_s16__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57585  } else
57586 #elif defined(DRFLAC_SUPPORT_NEON)
57587  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
57588  drflac_read_pcm_frames_s16__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57589  } else
57590 #endif
57591  {
57592 #if 0
57593  drflac_read_pcm_frames_s16__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57594 #else
57595  drflac_read_pcm_frames_s16__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57596 #endif
57597  }
57598 }
57599 #if 0
57600 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57601 {
57602  drflac_uint64 i;
57603  for (i = 0; i < frameCount; ++i) {
57604  drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57605  drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57606  drflac_uint32 left = right + side;
57607  left >>= 16;
57608  right >>= 16;
57609  pOutputSamples[i*2+0] = (drflac_int16)left;
57610  pOutputSamples[i*2+1] = (drflac_int16)right;
57611  }
57612 }
57613 #endif
57614 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57615 {
57616  drflac_uint64 i;
57617  drflac_uint64 frameCount4 = frameCount >> 2;
57618  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57619  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57620  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57621  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57622  for (i = 0; i < frameCount4; ++i) {
57623  drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
57624  drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
57625  drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
57626  drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
57627  drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
57628  drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
57629  drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
57630  drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
57631  drflac_uint32 left0 = right0 + side0;
57632  drflac_uint32 left1 = right1 + side1;
57633  drflac_uint32 left2 = right2 + side2;
57634  drflac_uint32 left3 = right3 + side3;
57635  left0 >>= 16;
57636  left1 >>= 16;
57637  left2 >>= 16;
57638  left3 >>= 16;
57639  right0 >>= 16;
57640  right1 >>= 16;
57641  right2 >>= 16;
57642  right3 >>= 16;
57643  pOutputSamples[i*8+0] = (drflac_int16)left0;
57644  pOutputSamples[i*8+1] = (drflac_int16)right0;
57645  pOutputSamples[i*8+2] = (drflac_int16)left1;
57646  pOutputSamples[i*8+3] = (drflac_int16)right1;
57647  pOutputSamples[i*8+4] = (drflac_int16)left2;
57648  pOutputSamples[i*8+5] = (drflac_int16)right2;
57649  pOutputSamples[i*8+6] = (drflac_int16)left3;
57650  pOutputSamples[i*8+7] = (drflac_int16)right3;
57651  }
57652  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57653  drflac_uint32 side = pInputSamples0U32[i] << shift0;
57654  drflac_uint32 right = pInputSamples1U32[i] << shift1;
57655  drflac_uint32 left = right + side;
57656  left >>= 16;
57657  right >>= 16;
57658  pOutputSamples[i*2+0] = (drflac_int16)left;
57659  pOutputSamples[i*2+1] = (drflac_int16)right;
57660  }
57661 }
57662 #if defined(DRFLAC_SUPPORT_SSE2)
57663 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57664 {
57665  drflac_uint64 i;
57666  drflac_uint64 frameCount4 = frameCount >> 2;
57667  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57668  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57669  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57670  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57671  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57672  for (i = 0; i < frameCount4; ++i) {
57673  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
57674  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
57675  __m128i left = _mm_add_epi32(right, side);
57676  left = _mm_srai_epi32(left, 16);
57677  right = _mm_srai_epi32(right, 16);
57678  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
57679  }
57680  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57681  drflac_uint32 side = pInputSamples0U32[i] << shift0;
57682  drflac_uint32 right = pInputSamples1U32[i] << shift1;
57683  drflac_uint32 left = right + side;
57684  left >>= 16;
57685  right >>= 16;
57686  pOutputSamples[i*2+0] = (drflac_int16)left;
57687  pOutputSamples[i*2+1] = (drflac_int16)right;
57688  }
57689 }
57690 #endif
57691 #if defined(DRFLAC_SUPPORT_NEON)
57692 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57693 {
57694  drflac_uint64 i;
57695  drflac_uint64 frameCount4 = frameCount >> 2;
57696  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57697  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57698  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57699  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57700  int32x4_t shift0_4;
57701  int32x4_t shift1_4;
57702  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57703  shift0_4 = vdupq_n_s32(shift0);
57704  shift1_4 = vdupq_n_s32(shift1);
57705  for (i = 0; i < frameCount4; ++i) {
57706  uint32x4_t side;
57707  uint32x4_t right;
57708  uint32x4_t left;
57709  side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
57710  right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
57711  left = vaddq_u32(right, side);
57712  left = vshrq_n_u32(left, 16);
57713  right = vshrq_n_u32(right, 16);
57714  drflac__vst2q_u16((drflac_uint16*)pOutputSamples + i*8, vzip_u16(vmovn_u32(left), vmovn_u32(right)));
57715  }
57716  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57717  drflac_uint32 side = pInputSamples0U32[i] << shift0;
57718  drflac_uint32 right = pInputSamples1U32[i] << shift1;
57719  drflac_uint32 left = right + side;
57720  left >>= 16;
57721  right >>= 16;
57722  pOutputSamples[i*2+0] = (drflac_int16)left;
57723  pOutputSamples[i*2+1] = (drflac_int16)right;
57724  }
57725 }
57726 #endif
57727 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57728 {
57729 #if defined(DRFLAC_SUPPORT_SSE2)
57730  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
57731  drflac_read_pcm_frames_s16__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57732  } else
57733 #elif defined(DRFLAC_SUPPORT_NEON)
57734  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
57735  drflac_read_pcm_frames_s16__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57736  } else
57737 #endif
57738  {
57739 #if 0
57740  drflac_read_pcm_frames_s16__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57741 #else
57742  drflac_read_pcm_frames_s16__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57743 #endif
57744  }
57745 }
57746 #if 0
57747 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57748 {
57749  for (drflac_uint64 i = 0; i < frameCount; ++i) {
57750  drflac_uint32 mid = (drflac_uint32)pInputSamples0[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57751  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57752  mid = (mid << 1) | (side & 0x01);
57753  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) >> 16);
57754  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) >> 16);
57755  }
57756 }
57757 #endif
57758 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57759 {
57760  drflac_uint64 i;
57761  drflac_uint64 frameCount4 = frameCount >> 2;
57762  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57763  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57764  drflac_uint32 shift = unusedBitsPerSample;
57765  if (shift > 0) {
57766  shift -= 1;
57767  for (i = 0; i < frameCount4; ++i) {
57768  drflac_uint32 temp0L;
57769  drflac_uint32 temp1L;
57770  drflac_uint32 temp2L;
57771  drflac_uint32 temp3L;
57772  drflac_uint32 temp0R;
57773  drflac_uint32 temp1R;
57774  drflac_uint32 temp2R;
57775  drflac_uint32 temp3R;
57776  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57777  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57778  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57779  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57780  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57781  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57782  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57783  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57784  mid0 = (mid0 << 1) | (side0 & 0x01);
57785  mid1 = (mid1 << 1) | (side1 & 0x01);
57786  mid2 = (mid2 << 1) | (side2 & 0x01);
57787  mid3 = (mid3 << 1) | (side3 & 0x01);
57788  temp0L = (mid0 + side0) << shift;
57789  temp1L = (mid1 + side1) << shift;
57790  temp2L = (mid2 + side2) << shift;
57791  temp3L = (mid3 + side3) << shift;
57792  temp0R = (mid0 - side0) << shift;
57793  temp1R = (mid1 - side1) << shift;
57794  temp2R = (mid2 - side2) << shift;
57795  temp3R = (mid3 - side3) << shift;
57796  temp0L >>= 16;
57797  temp1L >>= 16;
57798  temp2L >>= 16;
57799  temp3L >>= 16;
57800  temp0R >>= 16;
57801  temp1R >>= 16;
57802  temp2R >>= 16;
57803  temp3R >>= 16;
57804  pOutputSamples[i*8+0] = (drflac_int16)temp0L;
57805  pOutputSamples[i*8+1] = (drflac_int16)temp0R;
57806  pOutputSamples[i*8+2] = (drflac_int16)temp1L;
57807  pOutputSamples[i*8+3] = (drflac_int16)temp1R;
57808  pOutputSamples[i*8+4] = (drflac_int16)temp2L;
57809  pOutputSamples[i*8+5] = (drflac_int16)temp2R;
57810  pOutputSamples[i*8+6] = (drflac_int16)temp3L;
57811  pOutputSamples[i*8+7] = (drflac_int16)temp3R;
57812  }
57813  } else {
57814  for (i = 0; i < frameCount4; ++i) {
57815  drflac_uint32 temp0L;
57816  drflac_uint32 temp1L;
57817  drflac_uint32 temp2L;
57818  drflac_uint32 temp3L;
57819  drflac_uint32 temp0R;
57820  drflac_uint32 temp1R;
57821  drflac_uint32 temp2R;
57822  drflac_uint32 temp3R;
57823  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57824  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57825  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57826  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57827  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57828  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57829  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57830  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57831  mid0 = (mid0 << 1) | (side0 & 0x01);
57832  mid1 = (mid1 << 1) | (side1 & 0x01);
57833  mid2 = (mid2 << 1) | (side2 & 0x01);
57834  mid3 = (mid3 << 1) | (side3 & 0x01);
57835  temp0L = ((drflac_int32)(mid0 + side0) >> 1);
57836  temp1L = ((drflac_int32)(mid1 + side1) >> 1);
57837  temp2L = ((drflac_int32)(mid2 + side2) >> 1);
57838  temp3L = ((drflac_int32)(mid3 + side3) >> 1);
57839  temp0R = ((drflac_int32)(mid0 - side0) >> 1);
57840  temp1R = ((drflac_int32)(mid1 - side1) >> 1);
57841  temp2R = ((drflac_int32)(mid2 - side2) >> 1);
57842  temp3R = ((drflac_int32)(mid3 - side3) >> 1);
57843  temp0L >>= 16;
57844  temp1L >>= 16;
57845  temp2L >>= 16;
57846  temp3L >>= 16;
57847  temp0R >>= 16;
57848  temp1R >>= 16;
57849  temp2R >>= 16;
57850  temp3R >>= 16;
57851  pOutputSamples[i*8+0] = (drflac_int16)temp0L;
57852  pOutputSamples[i*8+1] = (drflac_int16)temp0R;
57853  pOutputSamples[i*8+2] = (drflac_int16)temp1L;
57854  pOutputSamples[i*8+3] = (drflac_int16)temp1R;
57855  pOutputSamples[i*8+4] = (drflac_int16)temp2L;
57856  pOutputSamples[i*8+5] = (drflac_int16)temp2R;
57857  pOutputSamples[i*8+6] = (drflac_int16)temp3L;
57858  pOutputSamples[i*8+7] = (drflac_int16)temp3R;
57859  }
57860  }
57861  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57862  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57863  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57864  mid = (mid << 1) | (side & 0x01);
57865  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) >> 16);
57866  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) >> 16);
57867  }
57868 }
57869 #if defined(DRFLAC_SUPPORT_SSE2)
57870 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57871 {
57872  drflac_uint64 i;
57873  drflac_uint64 frameCount4 = frameCount >> 2;
57874  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57875  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57876  drflac_uint32 shift = unusedBitsPerSample;
57877  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57878  if (shift == 0) {
57879  for (i = 0; i < frameCount4; ++i) {
57880  __m128i mid;
57881  __m128i side;
57882  __m128i left;
57883  __m128i right;
57884  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57885  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57886  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
57887  left = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
57888  right = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
57889  left = _mm_srai_epi32(left, 16);
57890  right = _mm_srai_epi32(right, 16);
57891  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
57892  }
57893  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57894  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57895  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57896  mid = (mid << 1) | (side & 0x01);
57897  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_int32)(mid + side) >> 1) >> 16);
57898  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_int32)(mid - side) >> 1) >> 16);
57899  }
57900  } else {
57901  shift -= 1;
57902  for (i = 0; i < frameCount4; ++i) {
57903  __m128i mid;
57904  __m128i side;
57905  __m128i left;
57906  __m128i right;
57907  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57908  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57909  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
57910  left = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
57911  right = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
57912  left = _mm_srai_epi32(left, 16);
57913  right = _mm_srai_epi32(right, 16);
57914  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
57915  }
57916  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57917  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57918  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57919  mid = (mid << 1) | (side & 0x01);
57920  pOutputSamples[i*2+0] = (drflac_int16)(((mid + side) << shift) >> 16);
57921  pOutputSamples[i*2+1] = (drflac_int16)(((mid - side) << shift) >> 16);
57922  }
57923  }
57924 }
57925 #endif
57926 #if defined(DRFLAC_SUPPORT_NEON)
57927 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57928 {
57929  drflac_uint64 i;
57930  drflac_uint64 frameCount4 = frameCount >> 2;
57931  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
57932  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
57933  drflac_uint32 shift = unusedBitsPerSample;
57934  int32x4_t wbpsShift0_4;
57935  int32x4_t wbpsShift1_4;
57936  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
57937  wbpsShift0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
57938  wbpsShift1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
57939  if (shift == 0) {
57940  for (i = 0; i < frameCount4; ++i) {
57941  uint32x4_t mid;
57942  uint32x4_t side;
57943  int32x4_t left;
57944  int32x4_t right;
57945  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
57946  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
57947  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
57948  left = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
57949  right = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
57950  left = vshrq_n_s32(left, 16);
57951  right = vshrq_n_s32(right, 16);
57952  drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
57953  }
57954  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57955  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57956  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57957  mid = (mid << 1) | (side & 0x01);
57958  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_int32)(mid + side) >> 1) >> 16);
57959  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_int32)(mid - side) >> 1) >> 16);
57960  }
57961  } else {
57962  int32x4_t shift4;
57963  shift -= 1;
57964  shift4 = vdupq_n_s32(shift);
57965  for (i = 0; i < frameCount4; ++i) {
57966  uint32x4_t mid;
57967  uint32x4_t side;
57968  int32x4_t left;
57969  int32x4_t right;
57970  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
57971  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
57972  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
57973  left = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
57974  right = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
57975  left = vshrq_n_s32(left, 16);
57976  right = vshrq_n_s32(right, 16);
57977  drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
57978  }
57979  for (i = (frameCount4 << 2); i < frameCount; ++i) {
57980  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
57981  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
57982  mid = (mid << 1) | (side & 0x01);
57983  pOutputSamples[i*2+0] = (drflac_int16)(((mid + side) << shift) >> 16);
57984  pOutputSamples[i*2+1] = (drflac_int16)(((mid - side) << shift) >> 16);
57985  }
57986  }
57987 }
57988 #endif
57989 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
57990 {
57991 #if defined(DRFLAC_SUPPORT_SSE2)
57992  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
57993  drflac_read_pcm_frames_s16__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57994  } else
57995 #elif defined(DRFLAC_SUPPORT_NEON)
57996  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
57997  drflac_read_pcm_frames_s16__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
57998  } else
57999 #endif
58000  {
58001 #if 0
58002  drflac_read_pcm_frames_s16__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58003 #else
58004  drflac_read_pcm_frames_s16__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58005 #endif
58006  }
58007 }
58008 #if 0
58009 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
58010 {
58011  for (drflac_uint64 i = 0; i < frameCount; ++i) {
58012  pOutputSamples[i*2+0] = (drflac_int16)((drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample)) >> 16);
58013  pOutputSamples[i*2+1] = (drflac_int16)((drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample)) >> 16);
58014  }
58015 }
58016 #endif
58017 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
58018 {
58019  drflac_uint64 i;
58020  drflac_uint64 frameCount4 = frameCount >> 2;
58021  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58022  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58023  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58024  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58025  for (i = 0; i < frameCount4; ++i) {
58026  drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
58027  drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
58028  drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
58029  drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
58030  drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
58031  drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
58032  drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
58033  drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
58034  tempL0 >>= 16;
58035  tempL1 >>= 16;
58036  tempL2 >>= 16;
58037  tempL3 >>= 16;
58038  tempR0 >>= 16;
58039  tempR1 >>= 16;
58040  tempR2 >>= 16;
58041  tempR3 >>= 16;
58042  pOutputSamples[i*8+0] = (drflac_int16)tempL0;
58043  pOutputSamples[i*8+1] = (drflac_int16)tempR0;
58044  pOutputSamples[i*8+2] = (drflac_int16)tempL1;
58045  pOutputSamples[i*8+3] = (drflac_int16)tempR1;
58046  pOutputSamples[i*8+4] = (drflac_int16)tempL2;
58047  pOutputSamples[i*8+5] = (drflac_int16)tempR2;
58048  pOutputSamples[i*8+6] = (drflac_int16)tempL3;
58049  pOutputSamples[i*8+7] = (drflac_int16)tempR3;
58050  }
58051  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58052  pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
58053  pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
58054  }
58055 }
58056 #if defined(DRFLAC_SUPPORT_SSE2)
58057 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
58058 {
58059  drflac_uint64 i;
58060  drflac_uint64 frameCount4 = frameCount >> 2;
58061  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58062  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58063  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58064  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58065  for (i = 0; i < frameCount4; ++i) {
58066  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
58067  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
58068  left = _mm_srai_epi32(left, 16);
58069  right = _mm_srai_epi32(right, 16);
58070  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
58071  }
58072  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58073  pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
58074  pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
58075  }
58076 }
58077 #endif
58078 #if defined(DRFLAC_SUPPORT_NEON)
58079 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
58080 {
58081  drflac_uint64 i;
58082  drflac_uint64 frameCount4 = frameCount >> 2;
58083  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58084  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58085  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58086  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58087  int32x4_t shift0_4 = vdupq_n_s32(shift0);
58088  int32x4_t shift1_4 = vdupq_n_s32(shift1);
58089  for (i = 0; i < frameCount4; ++i) {
58090  int32x4_t left;
58091  int32x4_t right;
58092  left = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4));
58093  right = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4));
58094  left = vshrq_n_s32(left, 16);
58095  right = vshrq_n_s32(right, 16);
58096  drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
58097  }
58098  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58099  pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
58100  pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
58101  }
58102 }
58103 #endif
58104 static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
58105 {
58106 #if defined(DRFLAC_SUPPORT_SSE2)
58107  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
58108  drflac_read_pcm_frames_s16__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58109  } else
58110 #elif defined(DRFLAC_SUPPORT_NEON)
58111  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
58112  drflac_read_pcm_frames_s16__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58113  } else
58114 #endif
58115  {
58116 #if 0
58117  drflac_read_pcm_frames_s16__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58118 #else
58119  drflac_read_pcm_frames_s16__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58120 #endif
58121  }
58122 }
58124 {
58125  drflac_uint64 framesRead;
58126  drflac_uint32 unusedBitsPerSample;
58127  if (pFlac == NULL || framesToRead == 0) {
58128  return 0;
58129  }
58130  if (pBufferOut == NULL) {
58131  return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
58132  }
58133  DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
58134  unusedBitsPerSample = 32 - pFlac->bitsPerSample;
58135  framesRead = 0;
58136  while (framesToRead > 0) {
58137  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
58139  break;
58140  }
58141  } else {
58144  drflac_uint64 frameCountThisIteration = framesToRead;
58145  if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
58146  frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
58147  }
58148  if (channelCount == 2) {
58149  const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
58150  const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
58151  switch (pFlac->currentFLACFrame.header.channelAssignment)
58152  {
58154  {
58155  drflac_read_pcm_frames_s16__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58156  } break;
58158  {
58159  drflac_read_pcm_frames_s16__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58160  } break;
58162  {
58163  drflac_read_pcm_frames_s16__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58164  } break;
58166  default:
58167  {
58168  drflac_read_pcm_frames_s16__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58169  } break;
58170  }
58171  } else {
58172  drflac_uint64 i;
58173  for (i = 0; i < frameCountThisIteration; ++i) {
58174  unsigned int j;
58175  for (j = 0; j < channelCount; ++j) {
58176  drflac_int32 sampleS32 = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
58177  pBufferOut[(i*channelCount)+j] = (drflac_int16)(sampleS32 >> 16);
58178  }
58179  }
58180  }
58181  framesRead += frameCountThisIteration;
58182  pBufferOut += frameCountThisIteration * channelCount;
58183  framesToRead -= frameCountThisIteration;
58184  pFlac->currentPCMFrame += frameCountThisIteration;
58185  pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)frameCountThisIteration;
58186  }
58187  }
58188  return framesRead;
58189 }
58190 #if 0
58191 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58192 {
58193  drflac_uint64 i;
58194  for (i = 0; i < frameCount; ++i) {
58195  drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
58196  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
58197  drflac_uint32 right = left - side;
58198  pOutputSamples[i*2+0] = (float)((drflac_int32)left / 2147483648.0);
58199  pOutputSamples[i*2+1] = (float)((drflac_int32)right / 2147483648.0);
58200  }
58201 }
58202 #endif
58203 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58204 {
58205  drflac_uint64 i;
58206  drflac_uint64 frameCount4 = frameCount >> 2;
58207  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58208  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58209  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58210  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58211  float factor = 1 / 2147483648.0;
58212  for (i = 0; i < frameCount4; ++i) {
58213  drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
58214  drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
58215  drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
58216  drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
58217  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
58218  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
58219  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
58220  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
58221  drflac_uint32 right0 = left0 - side0;
58222  drflac_uint32 right1 = left1 - side1;
58223  drflac_uint32 right2 = left2 - side2;
58224  drflac_uint32 right3 = left3 - side3;
58225  pOutputSamples[i*8+0] = (drflac_int32)left0 * factor;
58226  pOutputSamples[i*8+1] = (drflac_int32)right0 * factor;
58227  pOutputSamples[i*8+2] = (drflac_int32)left1 * factor;
58228  pOutputSamples[i*8+3] = (drflac_int32)right1 * factor;
58229  pOutputSamples[i*8+4] = (drflac_int32)left2 * factor;
58230  pOutputSamples[i*8+5] = (drflac_int32)right2 * factor;
58231  pOutputSamples[i*8+6] = (drflac_int32)left3 * factor;
58232  pOutputSamples[i*8+7] = (drflac_int32)right3 * factor;
58233  }
58234  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58235  drflac_uint32 left = pInputSamples0U32[i] << shift0;
58236  drflac_uint32 side = pInputSamples1U32[i] << shift1;
58237  drflac_uint32 right = left - side;
58238  pOutputSamples[i*2+0] = (drflac_int32)left * factor;
58239  pOutputSamples[i*2+1] = (drflac_int32)right * factor;
58240  }
58241 }
58242 #if defined(DRFLAC_SUPPORT_SSE2)
58243 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58244 {
58245  drflac_uint64 i;
58246  drflac_uint64 frameCount4 = frameCount >> 2;
58247  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58248  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58249  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
58250  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
58251  __m128 factor;
58252  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
58253  factor = _mm_set1_ps(1.0f / 8388608.0f);
58254  for (i = 0; i < frameCount4; ++i) {
58255  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
58256  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
58257  __m128i right = _mm_sub_epi32(left, side);
58258  __m128 leftf = _mm_mul_ps(_mm_cvtepi32_ps(left), factor);
58259  __m128 rightf = _mm_mul_ps(_mm_cvtepi32_ps(right), factor);
58260  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
58261  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
58262  }
58263  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58264  drflac_uint32 left = pInputSamples0U32[i] << shift0;
58265  drflac_uint32 side = pInputSamples1U32[i] << shift1;
58266  drflac_uint32 right = left - side;
58267  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
58268  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
58269  }
58270 }
58271 #endif
58272 #if defined(DRFLAC_SUPPORT_NEON)
58273 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58274 {
58275  drflac_uint64 i;
58276  drflac_uint64 frameCount4 = frameCount >> 2;
58277  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58278  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58279  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
58280  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
58281  float32x4_t factor4;
58282  int32x4_t shift0_4;
58283  int32x4_t shift1_4;
58284  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
58285  factor4 = vdupq_n_f32(1.0f / 8388608.0f);
58286  shift0_4 = vdupq_n_s32(shift0);
58287  shift1_4 = vdupq_n_s32(shift1);
58288  for (i = 0; i < frameCount4; ++i) {
58289  uint32x4_t left;
58290  uint32x4_t side;
58291  uint32x4_t right;
58292  float32x4_t leftf;
58293  float32x4_t rightf;
58294  left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
58295  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
58296  right = vsubq_u32(left, side);
58297  leftf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(left)), factor4);
58298  rightf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(right)), factor4);
58299  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
58300  }
58301  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58302  drflac_uint32 left = pInputSamples0U32[i] << shift0;
58303  drflac_uint32 side = pInputSamples1U32[i] << shift1;
58304  drflac_uint32 right = left - side;
58305  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
58306  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
58307  }
58308 }
58309 #endif
58310 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58311 {
58312 #if defined(DRFLAC_SUPPORT_SSE2)
58313  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
58314  drflac_read_pcm_frames_f32__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58315  } else
58316 #elif defined(DRFLAC_SUPPORT_NEON)
58317  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
58318  drflac_read_pcm_frames_f32__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58319  } else
58320 #endif
58321  {
58322 #if 0
58323  drflac_read_pcm_frames_f32__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58324 #else
58325  drflac_read_pcm_frames_f32__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58326 #endif
58327  }
58328 }
58329 #if 0
58330 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58331 {
58332  drflac_uint64 i;
58333  for (i = 0; i < frameCount; ++i) {
58334  drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
58335  drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
58336  drflac_uint32 left = right + side;
58337  pOutputSamples[i*2+0] = (float)((drflac_int32)left / 2147483648.0);
58338  pOutputSamples[i*2+1] = (float)((drflac_int32)right / 2147483648.0);
58339  }
58340 }
58341 #endif
58342 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58343 {
58344  drflac_uint64 i;
58345  drflac_uint64 frameCount4 = frameCount >> 2;
58346  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58347  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58348  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58349  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58350  float factor = 1 / 2147483648.0;
58351  for (i = 0; i < frameCount4; ++i) {
58352  drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
58353  drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
58354  drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
58355  drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
58356  drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
58357  drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
58358  drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
58359  drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
58360  drflac_uint32 left0 = right0 + side0;
58361  drflac_uint32 left1 = right1 + side1;
58362  drflac_uint32 left2 = right2 + side2;
58363  drflac_uint32 left3 = right3 + side3;
58364  pOutputSamples[i*8+0] = (drflac_int32)left0 * factor;
58365  pOutputSamples[i*8+1] = (drflac_int32)right0 * factor;
58366  pOutputSamples[i*8+2] = (drflac_int32)left1 * factor;
58367  pOutputSamples[i*8+3] = (drflac_int32)right1 * factor;
58368  pOutputSamples[i*8+4] = (drflac_int32)left2 * factor;
58369  pOutputSamples[i*8+5] = (drflac_int32)right2 * factor;
58370  pOutputSamples[i*8+6] = (drflac_int32)left3 * factor;
58371  pOutputSamples[i*8+7] = (drflac_int32)right3 * factor;
58372  }
58373  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58374  drflac_uint32 side = pInputSamples0U32[i] << shift0;
58375  drflac_uint32 right = pInputSamples1U32[i] << shift1;
58376  drflac_uint32 left = right + side;
58377  pOutputSamples[i*2+0] = (drflac_int32)left * factor;
58378  pOutputSamples[i*2+1] = (drflac_int32)right * factor;
58379  }
58380 }
58381 #if defined(DRFLAC_SUPPORT_SSE2)
58382 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58383 {
58384  drflac_uint64 i;
58385  drflac_uint64 frameCount4 = frameCount >> 2;
58386  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58387  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58388  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
58389  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
58390  __m128 factor;
58391  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
58392  factor = _mm_set1_ps(1.0f / 8388608.0f);
58393  for (i = 0; i < frameCount4; ++i) {
58394  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
58395  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
58396  __m128i left = _mm_add_epi32(right, side);
58397  __m128 leftf = _mm_mul_ps(_mm_cvtepi32_ps(left), factor);
58398  __m128 rightf = _mm_mul_ps(_mm_cvtepi32_ps(right), factor);
58399  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
58400  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
58401  }
58402  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58403  drflac_uint32 side = pInputSamples0U32[i] << shift0;
58404  drflac_uint32 right = pInputSamples1U32[i] << shift1;
58405  drflac_uint32 left = right + side;
58406  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
58407  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
58408  }
58409 }
58410 #endif
58411 #if defined(DRFLAC_SUPPORT_NEON)
58412 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58413 {
58414  drflac_uint64 i;
58415  drflac_uint64 frameCount4 = frameCount >> 2;
58416  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58417  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58418  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
58419  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
58420  float32x4_t factor4;
58421  int32x4_t shift0_4;
58422  int32x4_t shift1_4;
58423  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
58424  factor4 = vdupq_n_f32(1.0f / 8388608.0f);
58425  shift0_4 = vdupq_n_s32(shift0);
58426  shift1_4 = vdupq_n_s32(shift1);
58427  for (i = 0; i < frameCount4; ++i) {
58428  uint32x4_t side;
58429  uint32x4_t right;
58430  uint32x4_t left;
58431  float32x4_t leftf;
58432  float32x4_t rightf;
58433  side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
58434  right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
58435  left = vaddq_u32(right, side);
58436  leftf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(left)), factor4);
58437  rightf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(right)), factor4);
58438  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
58439  }
58440  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58441  drflac_uint32 side = pInputSamples0U32[i] << shift0;
58442  drflac_uint32 right = pInputSamples1U32[i] << shift1;
58443  drflac_uint32 left = right + side;
58444  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
58445  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
58446  }
58447 }
58448 #endif
58449 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58450 {
58451 #if defined(DRFLAC_SUPPORT_SSE2)
58452  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
58453  drflac_read_pcm_frames_f32__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58454  } else
58455 #elif defined(DRFLAC_SUPPORT_NEON)
58456  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
58457  drflac_read_pcm_frames_f32__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58458  } else
58459 #endif
58460  {
58461 #if 0
58462  drflac_read_pcm_frames_f32__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58463 #else
58464  drflac_read_pcm_frames_f32__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58465 #endif
58466  }
58467 }
58468 #if 0
58469 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58470 {
58471  for (drflac_uint64 i = 0; i < frameCount; ++i) {
58472  drflac_uint32 mid = (drflac_uint32)pInputSamples0[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58473  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58474  mid = (mid << 1) | (side & 0x01);
58475  pOutputSamples[i*2+0] = (float)((((drflac_int32)(mid + side) >> 1) << (unusedBitsPerSample)) / 2147483648.0);
58476  pOutputSamples[i*2+1] = (float)((((drflac_int32)(mid - side) >> 1) << (unusedBitsPerSample)) / 2147483648.0);
58477  }
58478 }
58479 #endif
58480 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58481 {
58482  drflac_uint64 i;
58483  drflac_uint64 frameCount4 = frameCount >> 2;
58484  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58485  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58486  drflac_uint32 shift = unusedBitsPerSample;
58487  float factor = 1 / 2147483648.0;
58488  if (shift > 0) {
58489  shift -= 1;
58490  for (i = 0; i < frameCount4; ++i) {
58491  drflac_uint32 temp0L;
58492  drflac_uint32 temp1L;
58493  drflac_uint32 temp2L;
58494  drflac_uint32 temp3L;
58495  drflac_uint32 temp0R;
58496  drflac_uint32 temp1R;
58497  drflac_uint32 temp2R;
58498  drflac_uint32 temp3R;
58499  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58500  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58501  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58502  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58503  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58504  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58505  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58506  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58507  mid0 = (mid0 << 1) | (side0 & 0x01);
58508  mid1 = (mid1 << 1) | (side1 & 0x01);
58509  mid2 = (mid2 << 1) | (side2 & 0x01);
58510  mid3 = (mid3 << 1) | (side3 & 0x01);
58511  temp0L = (mid0 + side0) << shift;
58512  temp1L = (mid1 + side1) << shift;
58513  temp2L = (mid2 + side2) << shift;
58514  temp3L = (mid3 + side3) << shift;
58515  temp0R = (mid0 - side0) << shift;
58516  temp1R = (mid1 - side1) << shift;
58517  temp2R = (mid2 - side2) << shift;
58518  temp3R = (mid3 - side3) << shift;
58519  pOutputSamples[i*8+0] = (drflac_int32)temp0L * factor;
58520  pOutputSamples[i*8+1] = (drflac_int32)temp0R * factor;
58521  pOutputSamples[i*8+2] = (drflac_int32)temp1L * factor;
58522  pOutputSamples[i*8+3] = (drflac_int32)temp1R * factor;
58523  pOutputSamples[i*8+4] = (drflac_int32)temp2L * factor;
58524  pOutputSamples[i*8+5] = (drflac_int32)temp2R * factor;
58525  pOutputSamples[i*8+6] = (drflac_int32)temp3L * factor;
58526  pOutputSamples[i*8+7] = (drflac_int32)temp3R * factor;
58527  }
58528  } else {
58529  for (i = 0; i < frameCount4; ++i) {
58530  drflac_uint32 temp0L;
58531  drflac_uint32 temp1L;
58532  drflac_uint32 temp2L;
58533  drflac_uint32 temp3L;
58534  drflac_uint32 temp0R;
58535  drflac_uint32 temp1R;
58536  drflac_uint32 temp2R;
58537  drflac_uint32 temp3R;
58538  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58539  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58540  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58541  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58542  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58543  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58544  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58545  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58546  mid0 = (mid0 << 1) | (side0 & 0x01);
58547  mid1 = (mid1 << 1) | (side1 & 0x01);
58548  mid2 = (mid2 << 1) | (side2 & 0x01);
58549  mid3 = (mid3 << 1) | (side3 & 0x01);
58550  temp0L = (drflac_uint32)((drflac_int32)(mid0 + side0) >> 1);
58551  temp1L = (drflac_uint32)((drflac_int32)(mid1 + side1) >> 1);
58552  temp2L = (drflac_uint32)((drflac_int32)(mid2 + side2) >> 1);
58553  temp3L = (drflac_uint32)((drflac_int32)(mid3 + side3) >> 1);
58554  temp0R = (drflac_uint32)((drflac_int32)(mid0 - side0) >> 1);
58555  temp1R = (drflac_uint32)((drflac_int32)(mid1 - side1) >> 1);
58556  temp2R = (drflac_uint32)((drflac_int32)(mid2 - side2) >> 1);
58557  temp3R = (drflac_uint32)((drflac_int32)(mid3 - side3) >> 1);
58558  pOutputSamples[i*8+0] = (drflac_int32)temp0L * factor;
58559  pOutputSamples[i*8+1] = (drflac_int32)temp0R * factor;
58560  pOutputSamples[i*8+2] = (drflac_int32)temp1L * factor;
58561  pOutputSamples[i*8+3] = (drflac_int32)temp1R * factor;
58562  pOutputSamples[i*8+4] = (drflac_int32)temp2L * factor;
58563  pOutputSamples[i*8+5] = (drflac_int32)temp2R * factor;
58564  pOutputSamples[i*8+6] = (drflac_int32)temp3L * factor;
58565  pOutputSamples[i*8+7] = (drflac_int32)temp3R * factor;
58566  }
58567  }
58568  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58569  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58570  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58571  mid = (mid << 1) | (side & 0x01);
58572  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) * factor;
58573  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) * factor;
58574  }
58575 }
58576 #if defined(DRFLAC_SUPPORT_SSE2)
58577 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58578 {
58579  drflac_uint64 i;
58580  drflac_uint64 frameCount4 = frameCount >> 2;
58581  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58582  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58583  drflac_uint32 shift = unusedBitsPerSample - 8;
58584  float factor;
58585  __m128 factor128;
58586  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
58587  factor = 1.0f / 8388608.0f;
58588  factor128 = _mm_set1_ps(factor);
58589  if (shift == 0) {
58590  for (i = 0; i < frameCount4; ++i) {
58591  __m128i mid;
58592  __m128i side;
58593  __m128i tempL;
58594  __m128i tempR;
58595  __m128 leftf;
58596  __m128 rightf;
58597  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
58598  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
58599  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
58600  tempL = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
58601  tempR = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
58602  leftf = _mm_mul_ps(_mm_cvtepi32_ps(tempL), factor128);
58603  rightf = _mm_mul_ps(_mm_cvtepi32_ps(tempR), factor128);
58604  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
58605  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
58606  }
58607  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58608  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58609  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58610  mid = (mid << 1) | (side & 0x01);
58611  pOutputSamples[i*2+0] = ((drflac_int32)(mid + side) >> 1) * factor;
58612  pOutputSamples[i*2+1] = ((drflac_int32)(mid - side) >> 1) * factor;
58613  }
58614  } else {
58615  shift -= 1;
58616  for (i = 0; i < frameCount4; ++i) {
58617  __m128i mid;
58618  __m128i side;
58619  __m128i tempL;
58620  __m128i tempR;
58621  __m128 leftf;
58622  __m128 rightf;
58623  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
58624  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
58625  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
58626  tempL = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
58627  tempR = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
58628  leftf = _mm_mul_ps(_mm_cvtepi32_ps(tempL), factor128);
58629  rightf = _mm_mul_ps(_mm_cvtepi32_ps(tempR), factor128);
58630  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
58631  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
58632  }
58633  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58634  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58635  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58636  mid = (mid << 1) | (side & 0x01);
58637  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift) * factor;
58638  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift) * factor;
58639  }
58640  }
58641 }
58642 #endif
58643 #if defined(DRFLAC_SUPPORT_NEON)
58644 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58645 {
58646  drflac_uint64 i;
58647  drflac_uint64 frameCount4 = frameCount >> 2;
58648  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58649  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58650  drflac_uint32 shift = unusedBitsPerSample - 8;
58651  float factor;
58652  float32x4_t factor4;
58653  int32x4_t shift4;
58654  int32x4_t wbps0_4;
58655  int32x4_t wbps1_4;
58656  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
58657  factor = 1.0f / 8388608.0f;
58658  factor4 = vdupq_n_f32(factor);
58659  wbps0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
58660  wbps1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
58661  if (shift == 0) {
58662  for (i = 0; i < frameCount4; ++i) {
58663  int32x4_t lefti;
58664  int32x4_t righti;
58665  float32x4_t leftf;
58666  float32x4_t rightf;
58667  uint32x4_t mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbps0_4);
58668  uint32x4_t side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbps1_4);
58669  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
58670  lefti = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
58671  righti = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
58672  leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
58673  rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
58674  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
58675  }
58676  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58677  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58678  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58679  mid = (mid << 1) | (side & 0x01);
58680  pOutputSamples[i*2+0] = ((drflac_int32)(mid + side) >> 1) * factor;
58681  pOutputSamples[i*2+1] = ((drflac_int32)(mid - side) >> 1) * factor;
58682  }
58683  } else {
58684  shift -= 1;
58685  shift4 = vdupq_n_s32(shift);
58686  for (i = 0; i < frameCount4; ++i) {
58687  uint32x4_t mid;
58688  uint32x4_t side;
58689  int32x4_t lefti;
58690  int32x4_t righti;
58691  float32x4_t leftf;
58692  float32x4_t rightf;
58693  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbps0_4);
58694  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbps1_4);
58695  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
58696  lefti = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
58697  righti = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
58698  leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
58699  rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
58700  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
58701  }
58702  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58703  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58704  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58705  mid = (mid << 1) | (side & 0x01);
58706  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift) * factor;
58707  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift) * factor;
58708  }
58709  }
58710 }
58711 #endif
58712 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58713 {
58714 #if defined(DRFLAC_SUPPORT_SSE2)
58715  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
58716  drflac_read_pcm_frames_f32__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58717  } else
58718 #elif defined(DRFLAC_SUPPORT_NEON)
58719  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
58720  drflac_read_pcm_frames_f32__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58721  } else
58722 #endif
58723  {
58724 #if 0
58725  drflac_read_pcm_frames_f32__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58726 #else
58727  drflac_read_pcm_frames_f32__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58728 #endif
58729  }
58730 }
58731 #if 0
58732 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58733 {
58734  for (drflac_uint64 i = 0; i < frameCount; ++i) {
58735  pOutputSamples[i*2+0] = (float)((drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample)) / 2147483648.0);
58736  pOutputSamples[i*2+1] = (float)((drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample)) / 2147483648.0);
58737  }
58738 }
58739 #endif
58740 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58741 {
58742  drflac_uint64 i;
58743  drflac_uint64 frameCount4 = frameCount >> 2;
58744  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58745  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58746  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
58747  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
58748  float factor = 1 / 2147483648.0;
58749  for (i = 0; i < frameCount4; ++i) {
58750  drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
58751  drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
58752  drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
58753  drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
58754  drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
58755  drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
58756  drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
58757  drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
58758  pOutputSamples[i*8+0] = (drflac_int32)tempL0 * factor;
58759  pOutputSamples[i*8+1] = (drflac_int32)tempR0 * factor;
58760  pOutputSamples[i*8+2] = (drflac_int32)tempL1 * factor;
58761  pOutputSamples[i*8+3] = (drflac_int32)tempR1 * factor;
58762  pOutputSamples[i*8+4] = (drflac_int32)tempL2 * factor;
58763  pOutputSamples[i*8+5] = (drflac_int32)tempR2 * factor;
58764  pOutputSamples[i*8+6] = (drflac_int32)tempL3 * factor;
58765  pOutputSamples[i*8+7] = (drflac_int32)tempR3 * factor;
58766  }
58767  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58768  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
58769  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
58770  }
58771 }
58772 #if defined(DRFLAC_SUPPORT_SSE2)
58773 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58774 {
58775  drflac_uint64 i;
58776  drflac_uint64 frameCount4 = frameCount >> 2;
58777  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58778  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58779  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
58780  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
58781  float factor = 1.0f / 8388608.0f;
58782  __m128 factor128 = _mm_set1_ps(factor);
58783  for (i = 0; i < frameCount4; ++i) {
58784  __m128i lefti;
58785  __m128i righti;
58786  __m128 leftf;
58787  __m128 rightf;
58788  lefti = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
58789  righti = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
58790  leftf = _mm_mul_ps(_mm_cvtepi32_ps(lefti), factor128);
58791  rightf = _mm_mul_ps(_mm_cvtepi32_ps(righti), factor128);
58792  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
58793  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
58794  }
58795  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58796  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
58797  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
58798  }
58799 }
58800 #endif
58801 #if defined(DRFLAC_SUPPORT_NEON)
58802 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58803 {
58804  drflac_uint64 i;
58805  drflac_uint64 frameCount4 = frameCount >> 2;
58806  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
58807  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
58808  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
58809  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
58810  float factor = 1.0f / 8388608.0f;
58811  float32x4_t factor4 = vdupq_n_f32(factor);
58812  int32x4_t shift0_4 = vdupq_n_s32(shift0);
58813  int32x4_t shift1_4 = vdupq_n_s32(shift1);
58814  for (i = 0; i < frameCount4; ++i) {
58815  int32x4_t lefti;
58816  int32x4_t righti;
58817  float32x4_t leftf;
58818  float32x4_t rightf;
58819  lefti = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4));
58820  righti = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4));
58821  leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
58822  rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
58823  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
58824  }
58825  for (i = (frameCount4 << 2); i < frameCount; ++i) {
58826  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
58827  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
58828  }
58829 }
58830 #endif
58831 static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
58832 {
58833 #if defined(DRFLAC_SUPPORT_SSE2)
58834  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
58835  drflac_read_pcm_frames_f32__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58836  } else
58837 #elif defined(DRFLAC_SUPPORT_NEON)
58838  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
58839  drflac_read_pcm_frames_f32__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58840  } else
58841 #endif
58842  {
58843 #if 0
58844  drflac_read_pcm_frames_f32__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58845 #else
58846  drflac_read_pcm_frames_f32__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
58847 #endif
58848  }
58849 }
58851 {
58852  drflac_uint64 framesRead;
58853  drflac_uint32 unusedBitsPerSample;
58854  if (pFlac == NULL || framesToRead == 0) {
58855  return 0;
58856  }
58857  if (pBufferOut == NULL) {
58858  return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
58859  }
58860  DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
58861  unusedBitsPerSample = 32 - pFlac->bitsPerSample;
58862  framesRead = 0;
58863  while (framesToRead > 0) {
58864  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
58866  break;
58867  }
58868  } else {
58871  drflac_uint64 frameCountThisIteration = framesToRead;
58872  if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
58873  frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
58874  }
58875  if (channelCount == 2) {
58876  const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
58877  const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
58878  switch (pFlac->currentFLACFrame.header.channelAssignment)
58879  {
58881  {
58882  drflac_read_pcm_frames_f32__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58883  } break;
58885  {
58886  drflac_read_pcm_frames_f32__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58887  } break;
58889  {
58890  drflac_read_pcm_frames_f32__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58891  } break;
58893  default:
58894  {
58895  drflac_read_pcm_frames_f32__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
58896  } break;
58897  }
58898  } else {
58899  drflac_uint64 i;
58900  for (i = 0; i < frameCountThisIteration; ++i) {
58901  unsigned int j;
58902  for (j = 0; j < channelCount; ++j) {
58903  drflac_int32 sampleS32 = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
58904  pBufferOut[(i*channelCount)+j] = (float)(sampleS32 / 2147483648.0);
58905  }
58906  }
58907  }
58908  framesRead += frameCountThisIteration;
58909  pBufferOut += frameCountThisIteration * channelCount;
58910  framesToRead -= frameCountThisIteration;
58911  pFlac->currentPCMFrame += frameCountThisIteration;
58912  pFlac->currentFLACFrame.pcmFramesRemaining -= (unsigned int)frameCountThisIteration;
58913  }
58914  }
58915  return framesRead;
58916 }
58918 {
58919  if (pFlac == NULL) {
58920  return DRFLAC_FALSE;
58921  }
58922  if (pFlac->currentPCMFrame == pcmFrameIndex) {
58923  return DRFLAC_TRUE;
58924  }
58925  if (pFlac->firstFLACFramePosInBytes == 0) {
58926  return DRFLAC_FALSE;
58927  }
58928  if (pcmFrameIndex == 0) {
58929  pFlac->currentPCMFrame = 0;
58930  return drflac__seek_to_first_frame(pFlac);
58931  } else {
58932  drflac_bool32 wasSuccessful = DRFLAC_FALSE;
58933  drflac_uint64 originalPCMFrame = pFlac->currentPCMFrame;
58934  if (pcmFrameIndex > pFlac->totalPCMFrameCount) {
58935  pcmFrameIndex = pFlac->totalPCMFrameCount;
58936  }
58937  if (pcmFrameIndex > pFlac->currentPCMFrame) {
58938  drflac_uint32 offset = (drflac_uint32)(pcmFrameIndex - pFlac->currentPCMFrame);
58939  if (pFlac->currentFLACFrame.pcmFramesRemaining > offset) {
58940  pFlac->currentFLACFrame.pcmFramesRemaining -= offset;
58941  pFlac->currentPCMFrame = pcmFrameIndex;
58942  return DRFLAC_TRUE;
58943  }
58944  } else {
58945  drflac_uint32 offsetAbs = (drflac_uint32)(pFlac->currentPCMFrame - pcmFrameIndex);
58946  drflac_uint32 currentFLACFramePCMFrameCount = pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
58947  drflac_uint32 currentFLACFramePCMFramesConsumed = currentFLACFramePCMFrameCount - pFlac->currentFLACFrame.pcmFramesRemaining;
58948  if (currentFLACFramePCMFramesConsumed > offsetAbs) {
58949  pFlac->currentFLACFrame.pcmFramesRemaining += offsetAbs;
58950  pFlac->currentPCMFrame = pcmFrameIndex;
58951  return DRFLAC_TRUE;
58952  }
58953  }
58954 #ifndef DR_FLAC_NO_OGG
58955  if (pFlac->container == drflac_container_ogg)
58956  {
58957  wasSuccessful = drflac_ogg__seek_to_pcm_frame(pFlac, pcmFrameIndex);
58958  }
58959  else
58960 #endif
58961  {
58962  if (!pFlac->_noSeekTableSeek) {
58963  wasSuccessful = drflac__seek_to_pcm_frame__seek_table(pFlac, pcmFrameIndex);
58964  }
58965 #if !defined(DR_FLAC_NO_CRC)
58966  if (!wasSuccessful && !pFlac->_noBinarySearchSeek && pFlac->totalPCMFrameCount > 0) {
58967  wasSuccessful = drflac__seek_to_pcm_frame__binary_search(pFlac, pcmFrameIndex);
58968  }
58969 #endif
58970  if (!wasSuccessful && !pFlac->_noBruteForceSeek) {
58971  wasSuccessful = drflac__seek_to_pcm_frame__brute_force(pFlac, pcmFrameIndex);
58972  }
58973  }
58974  if (wasSuccessful) {
58975  pFlac->currentPCMFrame = pcmFrameIndex;
58976  } else {
58977  if (drflac_seek_to_pcm_frame(pFlac, originalPCMFrame) == DRFLAC_FALSE) {
58978  drflac_seek_to_pcm_frame(pFlac, 0);
58979  }
58980  }
58981  return wasSuccessful;
58982  }
58983 }
58984 #if defined(SIZE_MAX)
58985  #define DRFLAC_SIZE_MAX SIZE_MAX
58986 #else
58987  #if defined(DRFLAC_64BIT)
58988  #define DRFLAC_SIZE_MAX ((drflac_uint64)0xFFFFFFFFFFFFFFFF)
58989  #else
58990  #define DRFLAC_SIZE_MAX 0xFFFFFFFF
58991  #endif
58992 #endif
58993 #define DRFLAC_DEFINE_FULL_READ_AND_CLOSE(extension, type) \
58994 static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut)\
58995 { \
58996  type* pSampleData = NULL; \
58997  drflac_uint64 totalPCMFrameCount; \
58998  \
58999  DRFLAC_ASSERT(pFlac != NULL); \
59000  \
59001  totalPCMFrameCount = pFlac->totalPCMFrameCount; \
59002  \
59003  if (totalPCMFrameCount == 0) { \
59004  type buffer[4096]; \
59005  drflac_uint64 pcmFramesRead; \
59006  size_t sampleDataBufferSize = sizeof(buffer); \
59007  \
59008  pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
59009  if (pSampleData == NULL) { \
59010  goto on_error; \
59011  } \
59012  \
59013  while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
59014  if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
59015  type* pNewSampleData; \
59016  size_t newSampleDataBufferSize; \
59017  \
59018  newSampleDataBufferSize = sampleDataBufferSize * 2; \
59019  pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
59020  if (pNewSampleData == NULL) { \
59021  drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
59022  goto on_error; \
59023  } \
59024  \
59025  sampleDataBufferSize = newSampleDataBufferSize; \
59026  pSampleData = pNewSampleData; \
59027  } \
59028  \
59029  DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
59030  totalPCMFrameCount += pcmFramesRead; \
59031  } \
59032  \
59033  \
59034  DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
59035  } else { \
59036  drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
59037  if (dataSize > DRFLAC_SIZE_MAX) { \
59038  goto on_error; \
59039  } \
59040  \
59041  pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); \
59042  if (pSampleData == NULL) { \
59043  goto on_error; \
59044  } \
59045  \
59046  totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
59047  } \
59048  \
59049  if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
59050  if (channelsOut) *channelsOut = pFlac->channels; \
59051  if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
59052  \
59053  drflac_close(pFlac); \
59054  return pSampleData; \
59055  \
59056 on_error: \
59057  drflac_close(pFlac); \
59058  return NULL; \
59059 }
59063 DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
59064 {
59065  drflac* pFlac;
59066  if (channelsOut) {
59067  *channelsOut = 0;
59068  }
59069  if (sampleRateOut) {
59070  *sampleRateOut = 0;
59071  }
59072  if (totalPCMFrameCountOut) {
59073  *totalPCMFrameCountOut = 0;
59074  }
59075  pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
59076  if (pFlac == NULL) {
59077  return NULL;
59078  }
59079  return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
59080 }
59081 DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
59082 {
59083  drflac* pFlac;
59084  if (channelsOut) {
59085  *channelsOut = 0;
59086  }
59087  if (sampleRateOut) {
59088  *sampleRateOut = 0;
59089  }
59090  if (totalPCMFrameCountOut) {
59091  *totalPCMFrameCountOut = 0;
59092  }
59093  pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
59094  if (pFlac == NULL) {
59095  return NULL;
59096  }
59097  return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
59098 }
59099 DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
59100 {
59101  drflac* pFlac;
59102  if (channelsOut) {
59103  *channelsOut = 0;
59104  }
59105  if (sampleRateOut) {
59106  *sampleRateOut = 0;
59107  }
59108  if (totalPCMFrameCountOut) {
59109  *totalPCMFrameCountOut = 0;
59110  }
59111  pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
59112  if (pFlac == NULL) {
59113  return NULL;
59114  }
59115  return drflac__full_read_and_close_f32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
59116 }
59117 #ifndef DR_FLAC_NO_STDIO
59118 DRFLAC_API drflac_int32* drflac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
59119 {
59120  drflac* pFlac;
59121  if (sampleRate) {
59122  *sampleRate = 0;
59123  }
59124  if (channels) {
59125  *channels = 0;
59126  }
59127  if (totalPCMFrameCount) {
59128  *totalPCMFrameCount = 0;
59129  }
59130  pFlac = drflac_open_file(filename, pAllocationCallbacks);
59131  if (pFlac == NULL) {
59132  return NULL;
59133  }
59134  return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
59135 }
59136 DRFLAC_API drflac_int16* drflac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
59137 {
59138  drflac* pFlac;
59139  if (sampleRate) {
59140  *sampleRate = 0;
59141  }
59142  if (channels) {
59143  *channels = 0;
59144  }
59145  if (totalPCMFrameCount) {
59146  *totalPCMFrameCount = 0;
59147  }
59148  pFlac = drflac_open_file(filename, pAllocationCallbacks);
59149  if (pFlac == NULL) {
59150  return NULL;
59151  }
59152  return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
59153 }
59154 DRFLAC_API float* drflac_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
59155 {
59156  drflac* pFlac;
59157  if (sampleRate) {
59158  *sampleRate = 0;
59159  }
59160  if (channels) {
59161  *channels = 0;
59162  }
59163  if (totalPCMFrameCount) {
59164  *totalPCMFrameCount = 0;
59165  }
59166  pFlac = drflac_open_file(filename, pAllocationCallbacks);
59167  if (pFlac == NULL) {
59168  return NULL;
59169  }
59170  return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
59171 }
59172 #endif
59173 DRFLAC_API drflac_int32* drflac_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
59174 {
59175  drflac* pFlac;
59176  if (sampleRate) {
59177  *sampleRate = 0;
59178  }
59179  if (channels) {
59180  *channels = 0;
59181  }
59182  if (totalPCMFrameCount) {
59183  *totalPCMFrameCount = 0;
59184  }
59185  pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
59186  if (pFlac == NULL) {
59187  return NULL;
59188  }
59189  return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
59190 }
59191 DRFLAC_API drflac_int16* drflac_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
59192 {
59193  drflac* pFlac;
59194  if (sampleRate) {
59195  *sampleRate = 0;
59196  }
59197  if (channels) {
59198  *channels = 0;
59199  }
59200  if (totalPCMFrameCount) {
59201  *totalPCMFrameCount = 0;
59202  }
59203  pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
59204  if (pFlac == NULL) {
59205  return NULL;
59206  }
59207  return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
59208 }
59209 DRFLAC_API float* drflac_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
59210 {
59211  drflac* pFlac;
59212  if (sampleRate) {
59213  *sampleRate = 0;
59214  }
59215  if (channels) {
59216  *channels = 0;
59217  }
59218  if (totalPCMFrameCount) {
59219  *totalPCMFrameCount = 0;
59220  }
59221  pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
59222  if (pFlac == NULL) {
59223  return NULL;
59224  }
59225  return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
59226 }
59227 DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
59228 {
59229  if (pAllocationCallbacks != NULL) {
59230  drflac__free_from_callbacks(p, pAllocationCallbacks);
59231  } else {
59233  }
59234 }
59236 {
59237  if (pIter == NULL) {
59238  return;
59239  }
59240  pIter->countRemaining = commentCount;
59241  pIter->pRunningData = (const char*)pComments;
59242 }
59244 {
59245  drflac_int32 length;
59246  const char* pComment;
59247  if (pCommentLengthOut) {
59248  *pCommentLengthOut = 0;
59249  }
59250  if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
59251  return NULL;
59252  }
59253  length = drflac__le2host_32(*(const drflac_uint32*)pIter->pRunningData);
59254  pIter->pRunningData += 4;
59255  pComment = pIter->pRunningData;
59256  pIter->pRunningData += length;
59257  pIter->countRemaining -= 1;
59258  if (pCommentLengthOut) {
59259  *pCommentLengthOut = length;
59260  }
59261  return pComment;
59262 }
59264 {
59265  if (pIter == NULL) {
59266  return;
59267  }
59268  pIter->countRemaining = trackCount;
59269  pIter->pRunningData = (const char*)pTrackData;
59270 }
59272 {
59273  drflac_cuesheet_track cuesheetTrack;
59274  const char* pRunningData;
59275  drflac_uint64 offsetHi;
59276  drflac_uint64 offsetLo;
59277  if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
59278  return DRFLAC_FALSE;
59279  }
59280  pRunningData = pIter->pRunningData;
59281  offsetHi = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
59282  offsetLo = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
59283  cuesheetTrack.offset = offsetLo | (offsetHi << 32);
59284  cuesheetTrack.trackNumber = pRunningData[0]; pRunningData += 1;
59285  DRFLAC_COPY_MEMORY(cuesheetTrack.ISRC, pRunningData, sizeof(cuesheetTrack.ISRC)); pRunningData += 12;
59286  cuesheetTrack.isAudio = (pRunningData[0] & 0x80) != 0;
59287  cuesheetTrack.preEmphasis = (pRunningData[0] & 0x40) != 0; pRunningData += 14;
59288  cuesheetTrack.indexCount = pRunningData[0]; pRunningData += 1;
59289  cuesheetTrack.pIndexPoints = (const drflac_cuesheet_track_index*)pRunningData; pRunningData += cuesheetTrack.indexCount * sizeof(drflac_cuesheet_track_index);
59290  pIter->pRunningData = pRunningData;
59291  pIter->countRemaining -= 1;
59292  if (pCuesheetTrack) {
59293  *pCuesheetTrack = cuesheetTrack;
59294  }
59295  return DRFLAC_TRUE;
59296 }
59297 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
59298  #pragma GCC diagnostic pop
59299 #endif
59300 #endif
59301 /* dr_flac_c end */
59302 #endif /* DRFLAC_IMPLEMENTATION */
59303 #endif /* MA_NO_FLAC */
59304 
59305 #if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
59306 #if !defined(DR_MP3_IMPLEMENTATION) && !defined(DRMP3_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
59307 /* dr_mp3_c begin */
59308 #ifndef dr_mp3_c
59309 #define dr_mp3_c
59310 #include <stdlib.h>
59311 #include <string.h>
59312 #include <limits.h>
59314 {
59315  if (pMajor) {
59316  *pMajor = DRMP3_VERSION_MAJOR;
59317  }
59318  if (pMinor) {
59319  *pMinor = DRMP3_VERSION_MINOR;
59320  }
59321  if (pRevision) {
59322  *pRevision = DRMP3_VERSION_REVISION;
59323  }
59324 }
59326 {
59327  return DRMP3_VERSION_STRING;
59328 }
59329 #if defined(__TINYC__)
59330 #define DR_MP3_NO_SIMD
59331 #endif
59332 #define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
59333 #define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304
59334 #ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
59335 #define DRMP3_MAX_FRAME_SYNC_MATCHES 10
59336 #endif
59337 #define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE
59338 #define DRMP3_MAX_BITRESERVOIR_BYTES 511
59339 #define DRMP3_SHORT_BLOCK_TYPE 2
59340 #define DRMP3_STOP_BLOCK_TYPE 3
59341 #define DRMP3_MODE_MONO 3
59342 #define DRMP3_MODE_JOINT_STEREO 1
59343 #define DRMP3_HDR_SIZE 4
59344 #define DRMP3_HDR_IS_MONO(h) (((h[3]) & 0xC0) == 0xC0)
59345 #define DRMP3_HDR_IS_MS_STEREO(h) (((h[3]) & 0xE0) == 0x60)
59346 #define DRMP3_HDR_IS_FREE_FORMAT(h) (((h[2]) & 0xF0) == 0)
59347 #define DRMP3_HDR_IS_CRC(h) (!((h[1]) & 1))
59348 #define DRMP3_HDR_TEST_PADDING(h) ((h[2]) & 0x2)
59349 #define DRMP3_HDR_TEST_MPEG1(h) ((h[1]) & 0x8)
59350 #define DRMP3_HDR_TEST_NOT_MPEG25(h) ((h[1]) & 0x10)
59351 #define DRMP3_HDR_TEST_I_STEREO(h) ((h[3]) & 0x10)
59352 #define DRMP3_HDR_TEST_MS_STEREO(h) ((h[3]) & 0x20)
59353 #define DRMP3_HDR_GET_STEREO_MODE(h) (((h[3]) >> 6) & 3)
59354 #define DRMP3_HDR_GET_STEREO_MODE_EXT(h) (((h[3]) >> 4) & 3)
59355 #define DRMP3_HDR_GET_LAYER(h) (((h[1]) >> 1) & 3)
59356 #define DRMP3_HDR_GET_BITRATE(h) ((h[2]) >> 4)
59357 #define DRMP3_HDR_GET_SAMPLE_RATE(h) (((h[2]) >> 2) & 3)
59358 #define DRMP3_HDR_GET_MY_SAMPLE_RATE(h) (DRMP3_HDR_GET_SAMPLE_RATE(h) + (((h[1] >> 3) & 1) + ((h[1] >> 4) & 1))*3)
59359 #define DRMP3_HDR_IS_FRAME_576(h) ((h[1] & 14) == 2)
59360 #define DRMP3_HDR_IS_LAYER_1(h) ((h[1] & 6) == 6)
59361 #define DRMP3_BITS_DEQUANTIZER_OUT -1
59362 #define DRMP3_MAX_SCF (255 + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210)
59363 #define DRMP3_MAX_SCFI ((DRMP3_MAX_SCF + 3) & ~3)
59364 #define DRMP3_MIN(a, b) ((a) > (b) ? (b) : (a))
59365 #define DRMP3_MAX(a, b) ((a) < (b) ? (b) : (a))
59366 #if !defined(DR_MP3_NO_SIMD)
59367 #if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64))
59368 #define DR_MP3_ONLY_SIMD
59369 #endif
59370 #if ((defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_IX86) || defined(_M_X64))) || ((defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__))
59371 #if defined(_MSC_VER)
59372 #include <intrin.h>
59373 #endif
59374 #include <emmintrin.h>
59375 #define DRMP3_HAVE_SSE 1
59376 #define DRMP3_HAVE_SIMD 1
59377 #define DRMP3_VSTORE _mm_storeu_ps
59378 #define DRMP3_VLD _mm_loadu_ps
59379 #define DRMP3_VSET _mm_set1_ps
59380 #define DRMP3_VADD _mm_add_ps
59381 #define DRMP3_VSUB _mm_sub_ps
59382 #define DRMP3_VMUL _mm_mul_ps
59383 #define DRMP3_VMAC(a, x, y) _mm_add_ps(a, _mm_mul_ps(x, y))
59384 #define DRMP3_VMSB(a, x, y) _mm_sub_ps(a, _mm_mul_ps(x, y))
59385 #define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
59386 #define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
59387 typedef __m128 drmp3_f4;
59388 #if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
59389 #define drmp3_cpuid __cpuid
59390 #else
59391 static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
59392 {
59393 #if defined(__PIC__)
59394  __asm__ __volatile__(
59395 #if defined(__x86_64__)
59396  "push %%rbx\n"
59397  "cpuid\n"
59398  "xchgl %%ebx, %1\n"
59399  "pop %%rbx\n"
59400 #else
59401  "xchgl %%ebx, %1\n"
59402  "cpuid\n"
59403  "xchgl %%ebx, %1\n"
59404 #endif
59405  : "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
59406  : "a" (InfoType));
59407 #else
59408  __asm__ __volatile__(
59409  "cpuid"
59410  : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
59411  : "a" (InfoType));
59412 #endif
59413 }
59414 #endif
59415 static int drmp3_have_simd(void)
59416 {
59417 #ifdef DR_MP3_ONLY_SIMD
59418  return 1;
59419 #else
59420  static int g_have_simd;
59421  int CPUInfo[4];
59422 #ifdef MINIMP3_TEST
59423  static int g_counter;
59424  if (g_counter++ > 100)
59425  return 0;
59426 #endif
59427  if (g_have_simd)
59428  goto end;
59429  drmp3_cpuid(CPUInfo, 0);
59430  if (CPUInfo[0] > 0)
59431  {
59432  drmp3_cpuid(CPUInfo, 1);
59433  g_have_simd = (CPUInfo[3] & (1 << 26)) + 1;
59434  return g_have_simd - 1;
59435  }
59436 end:
59437  return g_have_simd - 1;
59438 #endif
59439 }
59440 #elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64)
59441 #include <arm_neon.h>
59442 #define DRMP3_HAVE_SSE 0
59443 #define DRMP3_HAVE_SIMD 1
59444 #define DRMP3_VSTORE vst1q_f32
59445 #define DRMP3_VLD vld1q_f32
59446 #define DRMP3_VSET vmovq_n_f32
59447 #define DRMP3_VADD vaddq_f32
59448 #define DRMP3_VSUB vsubq_f32
59449 #define DRMP3_VMUL vmulq_f32
59450 #define DRMP3_VMAC(a, x, y) vmlaq_f32(a, x, y)
59451 #define DRMP3_VMSB(a, x, y) vmlsq_f32(a, x, y)
59452 #define DRMP3_VMUL_S(x, s) vmulq_f32(x, vmovq_n_f32(s))
59453 #define DRMP3_VREV(x) vcombine_f32(vget_high_f32(vrev64q_f32(x)), vget_low_f32(vrev64q_f32(x)))
59454 typedef float32x4_t drmp3_f4;
59455 static int drmp3_have_simd(void)
59456 {
59457  return 1;
59458 }
59459 #else
59460 #define DRMP3_HAVE_SSE 0
59461 #define DRMP3_HAVE_SIMD 0
59462 #ifdef DR_MP3_ONLY_SIMD
59463 #error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled
59464 #endif
59465 #endif
59466 #else
59467 #define DRMP3_HAVE_SIMD 0
59468 #endif
59469 #if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64)
59470 #define DRMP3_HAVE_ARMV6 1
59471 static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_arm(drmp3_int32 a)
59472 {
59473  drmp3_int32 x = 0;
59474  __asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
59475  return x;
59476 }
59477 #else
59478 #define DRMP3_HAVE_ARMV6 0
59479 #endif
59480 typedef struct
59481 {
59483  int pos, limit;
59484 } drmp3_bs;
59485 typedef struct
59486 {
59487  float scf[3*64];
59488  drmp3_uint8 total_bands, stereo_bands, bitalloc[64], scfcod[64];
59490 typedef struct
59491 {
59492  drmp3_uint8 tab_offset, code_tab_width, band_count;
59494 typedef struct
59495 {
59497  drmp3_uint16 part_23_length, big_values, scalefac_compress;
59498  drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
59499  drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
59500  drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
59502 typedef struct
59503 {
59505  drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
59506  drmp3_L3_gr_info gr_info[4];
59507  float grbuf[2][576], scf[40], syn[18 + 15][2*32];
59508  drmp3_uint8 ist_pos[2][39];
59510 static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
59511 {
59512  bs->buf = data;
59513  bs->pos = 0;
59514  bs->limit = bytes*8;
59515 }
59517 {
59518  drmp3_uint32 next, cache = 0, s = bs->pos & 7;
59519  int shl = n + s;
59520  const drmp3_uint8 *p = bs->buf + (bs->pos >> 3);
59521  if ((bs->pos += n) > bs->limit)
59522  return 0;
59523  next = *p++ & (255 >> s);
59524  while ((shl -= 8) > 0)
59525  {
59526  cache |= next << shl;
59527  next = *p++;
59528  }
59529  return cache | (next >> -shl);
59530 }
59531 static int drmp3_hdr_valid(const drmp3_uint8 *h)
59532 {
59533  return h[0] == 0xff &&
59534  ((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) &&
59535  (DRMP3_HDR_GET_LAYER(h) != 0) &&
59536  (DRMP3_HDR_GET_BITRATE(h) != 15) &&
59537  (DRMP3_HDR_GET_SAMPLE_RATE(h) != 3);
59538 }
59539 static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2)
59540 {
59541  return drmp3_hdr_valid(h2) &&
59542  ((h1[1] ^ h2[1]) & 0xFE) == 0 &&
59543  ((h1[2] ^ h2[2]) & 0x0C) == 0 &&
59545 }
59546 static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h)
59547 {
59548  static const drmp3_uint8 halfrate[2][3][15] = {
59549  { { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,16,24,28,32,40,48,56,64,72,80,88,96,112,128 } },
59550  { { 0,16,20,24,28,32,40,48,56,64,80,96,112,128,160 }, { 0,16,24,28,32,40,48,56,64,80,96,112,128,160,192 }, { 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224 } },
59551  };
59552  return 2*halfrate[!!DRMP3_HDR_TEST_MPEG1(h)][DRMP3_HDR_GET_LAYER(h) - 1][DRMP3_HDR_GET_BITRATE(h)];
59553 }
59554 static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h)
59555 {
59556  static const unsigned g_hz[3] = { 44100, 48000, 32000 };
59557  return g_hz[DRMP3_HDR_GET_SAMPLE_RATE(h)] >> (int)!DRMP3_HDR_TEST_MPEG1(h) >> (int)!DRMP3_HDR_TEST_NOT_MPEG25(h);
59558 }
59559 static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h)
59560 {
59561  return DRMP3_HDR_IS_LAYER_1(h) ? 384 : (1152 >> (int)DRMP3_HDR_IS_FRAME_576(h));
59562 }
59563 static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size)
59564 {
59566  if (DRMP3_HDR_IS_LAYER_1(h))
59567  {
59568  frame_bytes &= ~3;
59569  }
59570  return frame_bytes ? frame_bytes : free_format_size;
59571 }
59572 static int drmp3_hdr_padding(const drmp3_uint8 *h)
59573 {
59574  return DRMP3_HDR_TEST_PADDING(h) ? (DRMP3_HDR_IS_LAYER_1(h) ? 4 : 1) : 0;
59575 }
59576 #ifndef DR_MP3_ONLY_MP3
59578 {
59579  const drmp3_L12_subband_alloc *alloc;
59580  int mode = DRMP3_HDR_GET_STEREO_MODE(hdr);
59581  int nbands, stereo_bands = (mode == DRMP3_MODE_MONO) ? 0 : (mode == DRMP3_MODE_JOINT_STEREO) ? (DRMP3_HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32;
59582  if (DRMP3_HDR_IS_LAYER_1(hdr))
59583  {
59584  static const drmp3_L12_subband_alloc g_alloc_L1[] = { { 76, 4, 32 } };
59585  alloc = g_alloc_L1;
59586  nbands = 32;
59587  } else if (!DRMP3_HDR_TEST_MPEG1(hdr))
59588  {
59589  static const drmp3_L12_subband_alloc g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } };
59590  alloc = g_alloc_L2M2;
59591  nbands = 30;
59592  } else
59593  {
59594  static const drmp3_L12_subband_alloc g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } };
59595  int sample_rate_idx = DRMP3_HDR_GET_SAMPLE_RATE(hdr);
59596  unsigned kbps = drmp3_hdr_bitrate_kbps(hdr) >> (int)(mode != DRMP3_MODE_MONO);
59597  if (!kbps)
59598  {
59599  kbps = 192;
59600  }
59601  alloc = g_alloc_L2M1;
59602  nbands = 27;
59603  if (kbps < 56)
59604  {
59605  static const drmp3_L12_subband_alloc g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } };
59606  alloc = g_alloc_L2M1_lowrate;
59607  nbands = sample_rate_idx == 2 ? 12 : 8;
59608  } else if (kbps >= 96 && sample_rate_idx != 1)
59609  {
59610  nbands = 30;
59611  }
59612  }
59613  sci->total_bands = (drmp3_uint8)nbands;
59614  sci->stereo_bands = (drmp3_uint8)DRMP3_MIN(stereo_bands, nbands);
59615  return alloc;
59616 }
59617 static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf)
59618 {
59619  static const float g_deq_L12[18*3] = {
59620 #define DRMP3_DQ(x) 9.53674316e-07f/x, 7.56931807e-07f/x, 6.00777173e-07f/x
59621  DRMP3_DQ(3),DRMP3_DQ(7),DRMP3_DQ(15),DRMP3_DQ(31),DRMP3_DQ(63),DRMP3_DQ(127),DRMP3_DQ(255),DRMP3_DQ(511),DRMP3_DQ(1023),DRMP3_DQ(2047),DRMP3_DQ(4095),DRMP3_DQ(8191),DRMP3_DQ(16383),DRMP3_DQ(32767),DRMP3_DQ(65535),DRMP3_DQ(3),DRMP3_DQ(5),DRMP3_DQ(9)
59622  };
59623  int i, m;
59624  for (i = 0; i < bands; i++)
59625  {
59626  float s = 0;
59627  int ba = *pba++;
59628  int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0;
59629  for (m = 4; m; m >>= 1)
59630  {
59631  if (mask & m)
59632  {
59633  int b = drmp3_bs_get_bits(bs, 6);
59634  s = g_deq_L12[ba*3 - 6 + b % 3]*(int)(1 << 21 >> b/3);
59635  }
59636  *scf++ = s;
59637  }
59638  }
59639 }
59641 {
59642  static const drmp3_uint8 g_bitalloc_code_tab[] = {
59643  0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16,
59644  0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16,
59645  0,17,18, 3,19,4,5,16,
59646  0,17,18,16,
59647  0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15,
59648  0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14,
59649  0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16
59650  };
59651  const drmp3_L12_subband_alloc *subband_alloc = drmp3_L12_subband_alloc_table(hdr, sci);
59652  int i, k = 0, ba_bits = 0;
59653  const drmp3_uint8 *ba_code_tab = g_bitalloc_code_tab;
59654  for (i = 0; i < sci->total_bands; i++)
59655  {
59656  drmp3_uint8 ba;
59657  if (i == k)
59658  {
59659  k += subband_alloc->band_count;
59660  ba_bits = subband_alloc->code_tab_width;
59661  ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset;
59662  subband_alloc++;
59663  }
59664  ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
59665  sci->bitalloc[2*i] = ba;
59666  if (i < sci->stereo_bands)
59667  {
59668  ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
59669  }
59670  sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0;
59671  }
59672  for (i = 0; i < 2*sci->total_bands; i++)
59673  {
59674  sci->scfcod[i] = (drmp3_uint8)(sci->bitalloc[i] ? DRMP3_HDR_IS_LAYER_1(hdr) ? 2 : drmp3_bs_get_bits(bs, 2) : 6);
59675  }
59676  drmp3_L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf);
59677  for (i = sci->stereo_bands; i < sci->total_bands; i++)
59678  {
59679  sci->bitalloc[2*i + 1] = 0;
59680  }
59681 }
59682 static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size)
59683 {
59684  int i, j, k, choff = 576;
59685  for (j = 0; j < 4; j++)
59686  {
59687  float *dst = grbuf + group_size*j;
59688  for (i = 0; i < 2*sci->total_bands; i++)
59689  {
59690  int ba = sci->bitalloc[i];
59691  if (ba != 0)
59692  {
59693  if (ba < 17)
59694  {
59695  int half = (1 << (ba - 1)) - 1;
59696  for (k = 0; k < group_size; k++)
59697  {
59698  dst[k] = (float)((int)drmp3_bs_get_bits(bs, ba) - half);
59699  }
59700  } else
59701  {
59702  unsigned mod = (2 << (ba - 17)) + 1;
59703  unsigned code = drmp3_bs_get_bits(bs, mod + 2 - (mod >> 3));
59704  for (k = 0; k < group_size; k++, code /= mod)
59705  {
59706  dst[k] = (float)((int)(code % mod - mod/2));
59707  }
59708  }
59709  }
59710  dst += choff;
59711  choff = 18 - choff;
59712  }
59713  }
59714  return group_size*4;
59715 }
59716 static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst)
59717 {
59718  int i, k;
59719  memcpy(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float));
59720  for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6)
59721  {
59722  for (k = 0; k < 12; k++)
59723  {
59724  dst[k + 0] *= scf[0];
59725  dst[k + 576] *= scf[3];
59726  }
59727  }
59728 }
59729 #endif
59731 {
59732  static const drmp3_uint8 g_scf_long[8][23] = {
59733  { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
59734  { 12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2,0 },
59735  { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
59736  { 6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36,0 },
59737  { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
59738  { 4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,158,0 },
59739  { 4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,192,0 },
59740  { 4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,26,0 }
59741  };
59742  static const drmp3_uint8 g_scf_short[8][40] = {
59743  { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
59744  { 8,8,8,8,8,8,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 },
59745  { 4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 },
59746  { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 },
59747  { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
59748  { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 },
59749  { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 },
59750  { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 }
59751  };
59752  static const drmp3_uint8 g_scf_mixed[8][40] = {
59753  { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
59754  { 12,12,12,4,4,4,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 },
59755  { 6,6,6,6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 },
59756  { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 },
59757  { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
59758  { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 },
59759  { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 },
59760  { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 }
59761  };
59762  unsigned tables, scfsi = 0;
59763  int main_data_begin, part_23_sum = 0;
59764  int gr_count = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
59765  int sr_idx = DRMP3_HDR_GET_MY_SAMPLE_RATE(hdr); sr_idx -= (sr_idx != 0);
59766  if (DRMP3_HDR_TEST_MPEG1(hdr))
59767  {
59768  gr_count *= 2;
59769  main_data_begin = drmp3_bs_get_bits(bs, 9);
59770  scfsi = drmp3_bs_get_bits(bs, 7 + gr_count);
59771  } else
59772  {
59773  main_data_begin = drmp3_bs_get_bits(bs, 8 + gr_count) >> gr_count;
59774  }
59775  do
59776  {
59777  if (DRMP3_HDR_IS_MONO(hdr))
59778  {
59779  scfsi <<= 4;
59780  }
59782  part_23_sum += gr->part_23_length;
59784  if (gr->big_values > 288)
59785  {
59786  return -1;
59787  }
59790  gr->sfbtab = g_scf_long[sr_idx];
59791  gr->n_long_sfb = 22;
59792  gr->n_short_sfb = 0;
59793  if (drmp3_bs_get_bits(bs, 1))
59794  {
59796  if (!gr->block_type)
59797  {
59798  return -1;
59799  }
59801  gr->region_count[0] = 7;
59802  gr->region_count[1] = 255;
59804  {
59805  scfsi &= 0x0F0F;
59806  if (!gr->mixed_block_flag)
59807  {
59808  gr->region_count[0] = 8;
59809  gr->sfbtab = g_scf_short[sr_idx];
59810  gr->n_long_sfb = 0;
59811  gr->n_short_sfb = 39;
59812  } else
59813  {
59814  gr->sfbtab = g_scf_mixed[sr_idx];
59815  gr->n_long_sfb = DRMP3_HDR_TEST_MPEG1(hdr) ? 8 : 6;
59816  gr->n_short_sfb = 30;
59817  }
59818  }
59819  tables = drmp3_bs_get_bits(bs, 10);
59820  tables <<= 5;
59821  gr->subblock_gain[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
59822  gr->subblock_gain[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
59823  gr->subblock_gain[2] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
59824  } else
59825  {
59826  gr->block_type = 0;
59827  gr->mixed_block_flag = 0;
59828  tables = drmp3_bs_get_bits(bs, 15);
59829  gr->region_count[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 4);
59830  gr->region_count[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
59831  gr->region_count[2] = 255;
59832  }
59833  gr->table_select[0] = (drmp3_uint8)(tables >> 10);
59834  gr->table_select[1] = (drmp3_uint8)((tables >> 5) & 31);
59835  gr->table_select[2] = (drmp3_uint8)((tables) & 31);
59836  gr->preflag = (drmp3_uint8)(DRMP3_HDR_TEST_MPEG1(hdr) ? drmp3_bs_get_bits(bs, 1) : (gr->scalefac_compress >= 500));
59839  gr->scfsi = (drmp3_uint8)((scfsi >> 12) & 15);
59840  scfsi <<= 4;
59841  gr++;
59842  } while(--gr_count);
59843  if (part_23_sum + bs->pos > bs->limit + main_data_begin*8)
59844  {
59845  return -1;
59846  }
59847  return main_data_begin;
59848 }
59849 static void drmp3_L3_read_scalefactors(drmp3_uint8 *scf, drmp3_uint8 *ist_pos, const drmp3_uint8 *scf_size, const drmp3_uint8 *scf_count, drmp3_bs *bitbuf, int scfsi)
59850 {
59851  int i, k;
59852  for (i = 0; i < 4 && scf_count[i]; i++, scfsi *= 2)
59853  {
59854  int cnt = scf_count[i];
59855  if (scfsi & 8)
59856  {
59857  memcpy(scf, ist_pos, cnt);
59858  } else
59859  {
59860  int bits = scf_size[i];
59861  if (!bits)
59862  {
59863  memset(scf, 0, cnt);
59864  memset(ist_pos, 0, cnt);
59865  } else
59866  {
59867  int max_scf = (scfsi < 0) ? (1 << bits) - 1 : -1;
59868  for (k = 0; k < cnt; k++)
59869  {
59870  int s = drmp3_bs_get_bits(bitbuf, bits);
59871  ist_pos[k] = (drmp3_uint8)(s == max_scf ? -1 : s);
59872  scf[k] = (drmp3_uint8)s;
59873  }
59874  }
59875  }
59876  ist_pos += cnt;
59877  scf += cnt;
59878  }
59879  scf[0] = scf[1] = scf[2] = 0;
59880 }
59881 static float drmp3_L3_ldexp_q2(float y, int exp_q2)
59882 {
59883  static const float g_expfrac[4] = { 9.31322575e-10f,7.83145814e-10f,6.58544508e-10f,5.53767716e-10f };
59884  int e;
59885  do
59886  {
59887  e = DRMP3_MIN(30*4, exp_q2);
59888  y *= g_expfrac[e & 3]*(1 << 30 >> (e >> 2));
59889  } while ((exp_q2 -= e) > 0);
59890  return y;
59891 }
59892 static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
59893 {
59894  static const drmp3_uint8 g_scf_partitions[3][28] = {
59895  { 6,5,5, 5,6,5,5,5,6,5, 7,3,11,10,0,0, 7, 7, 7,0, 6, 6,6,3, 8, 8,5,0 },
59896  { 8,9,6,12,6,9,9,9,6,9,12,6,15,18,0,0, 6,15,12,0, 6,12,9,6, 6,18,9,0 },
59897  { 9,9,6,12,9,9,9,9,9,9,12,6,18,18,0,0,12,12,12,0,12, 9,9,6,15,12,9,0 }
59898  };
59899  const drmp3_uint8 *scf_partition = g_scf_partitions[!!gr->n_short_sfb + !gr->n_long_sfb];
59900  drmp3_uint8 scf_size[4], iscf[40];
59901  int i, scf_shift = gr->scalefac_scale + 1, gain_exp, scfsi = gr->scfsi;
59902  float gain;
59903  if (DRMP3_HDR_TEST_MPEG1(hdr))
59904  {
59905  static const drmp3_uint8 g_scfc_decode[16] = { 0,1,2,3, 12,5,6,7, 9,10,11,13, 14,15,18,19 };
59906  int part = g_scfc_decode[gr->scalefac_compress];
59907  scf_size[1] = scf_size[0] = (drmp3_uint8)(part >> 2);
59908  scf_size[3] = scf_size[2] = (drmp3_uint8)(part & 3);
59909  } else
59910  {
59911  static const drmp3_uint8 g_mod[6*4] = { 5,5,4,4,5,5,4,1,4,3,1,1,5,6,6,1,4,4,4,1,4,3,1,1 };
59912  int k, modprod, sfc, ist = DRMP3_HDR_TEST_I_STEREO(hdr) && ch;
59913  sfc = gr->scalefac_compress >> ist;
59914  for (k = ist*3*4; sfc >= 0; sfc -= modprod, k += 4)
59915  {
59916  for (modprod = 1, i = 3; i >= 0; i--)
59917  {
59918  scf_size[i] = (drmp3_uint8)(sfc / modprod % g_mod[k + i]);
59919  modprod *= g_mod[k + i];
59920  }
59921  }
59922  scf_partition += k;
59923  scfsi = -16;
59924  }
59925  drmp3_L3_read_scalefactors(iscf, ist_pos, scf_size, scf_partition, bs, scfsi);
59926  if (gr->n_short_sfb)
59927  {
59928  int sh = 3 - scf_shift;
59929  for (i = 0; i < gr->n_short_sfb; i += 3)
59930  {
59931  iscf[gr->n_long_sfb + i + 0] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 0] + (gr->subblock_gain[0] << sh));
59932  iscf[gr->n_long_sfb + i + 1] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 1] + (gr->subblock_gain[1] << sh));
59933  iscf[gr->n_long_sfb + i + 2] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 2] + (gr->subblock_gain[2] << sh));
59934  }
59935  } else if (gr->preflag)
59936  {
59937  static const drmp3_uint8 g_preamp[10] = { 1,1,1,1,2,2,3,3,3,2 };
59938  for (i = 0; i < 10; i++)
59939  {
59940  iscf[11 + i] = (drmp3_uint8)(iscf[11 + i] + g_preamp[i]);
59941  }
59942  }
59943  gain_exp = gr->global_gain + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210 - (DRMP3_HDR_IS_MS_STEREO(hdr) ? 2 : 0);
59944  gain = drmp3_L3_ldexp_q2(1 << (DRMP3_MAX_SCFI/4), DRMP3_MAX_SCFI - gain_exp);
59945  for (i = 0; i < (int)(gr->n_long_sfb + gr->n_short_sfb); i++)
59946  {
59947  scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
59948  }
59949 }
59950 static const float g_drmp3_pow43[129 + 16] = {
59951  0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
59952  0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f
59953 };
59954 static float drmp3_L3_pow_43(int x)
59955 {
59956  float frac;
59957  int sign, mult = 256;
59958  if (x < 129)
59959  {
59960  return g_drmp3_pow43[16 + x];
59961  }
59962  if (x < 1024)
59963  {
59964  mult = 16;
59965  x <<= 3;
59966  }
59967  sign = 2*x & 64;
59968  frac = (float)((x & 63) - sign) / ((x & ~63) + sign);
59969  return g_drmp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult;
59970 }
59971 static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
59972 {
59973  static const drmp3_int16 tabs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59974  785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,
59975  -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288,
59976  -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288,
59977  -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258,
59978  -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259,
59979  -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258,
59980  -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258,
59981  -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259,
59982  -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258,
59983  -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290,
59984  -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259,
59985  -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258,
59986  -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259,
59987  -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258,
59988  -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 };
59989  static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205};
59990  static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 };
59991  static const drmp3_int16 tabindex[2*16] = { 0,32,64,98,0,132,180,218,292,364,426,538,648,746,0,1126,1460,1460,1460,1460,1460,1460,1460,1460,1842,1842,1842,1842,1842,1842,1842,1842 };
59992  static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 };
59993 #define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - n))
59994 #define DRMP3_FLUSH_BITS(n) { bs_cache <<= (n); bs_sh += (n); }
59995 #define DRMP3_CHECK_BITS while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; }
59996 #define DRMP3_BSPOS ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh)
59997  float one = 0.0f;
59998  int ireg = 0, big_val_cnt = gr_info->big_values;
59999  const drmp3_uint8 *sfb = gr_info->sfbtab;
60000  const drmp3_uint8 *bs_next_ptr = bs->buf + bs->pos/8;
60001  drmp3_uint32 bs_cache = (((bs_next_ptr[0]*256u + bs_next_ptr[1])*256u + bs_next_ptr[2])*256u + bs_next_ptr[3]) << (bs->pos & 7);
60002  int pairs_to_decode, np, bs_sh = (bs->pos & 7) - 8;
60003  bs_next_ptr += 4;
60004  while (big_val_cnt > 0)
60005  {
60006  int tab_num = gr_info->table_select[ireg];
60007  int sfb_cnt = gr_info->region_count[ireg++];
60008  const drmp3_int16 *codebook = tabs + tabindex[tab_num];
60009  int linbits = g_linbits[tab_num];
60010  if (linbits)
60011  {
60012  do
60013  {
60014  np = *sfb++ / 2;
60015  pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
60016  one = *scf++;
60017  do
60018  {
60019  int j, w = 5;
60020  int leaf = codebook[DRMP3_PEEK_BITS(w)];
60021  while (leaf < 0)
60022  {
60023  DRMP3_FLUSH_BITS(w);
60024  w = leaf & 7;
60025  leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
60026  }
60027  DRMP3_FLUSH_BITS(leaf >> 8);
60028  for (j = 0; j < 2; j++, dst++, leaf >>= 4)
60029  {
60030  int lsb = leaf & 0x0F;
60031  if (lsb == 15)
60032  {
60033  lsb += DRMP3_PEEK_BITS(linbits);
60034  DRMP3_FLUSH_BITS(linbits);
60036  *dst = one*drmp3_L3_pow_43(lsb)*((drmp3_int32)bs_cache < 0 ? -1: 1);
60037  } else
60038  {
60039  *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
60040  }
60041  DRMP3_FLUSH_BITS(lsb ? 1 : 0);
60042  }
60044  } while (--pairs_to_decode);
60045  } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
60046  } else
60047  {
60048  do
60049  {
60050  np = *sfb++ / 2;
60051  pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
60052  one = *scf++;
60053  do
60054  {
60055  int j, w = 5;
60056  int leaf = codebook[DRMP3_PEEK_BITS(w)];
60057  while (leaf < 0)
60058  {
60059  DRMP3_FLUSH_BITS(w);
60060  w = leaf & 7;
60061  leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
60062  }
60063  DRMP3_FLUSH_BITS(leaf >> 8);
60064  for (j = 0; j < 2; j++, dst++, leaf >>= 4)
60065  {
60066  int lsb = leaf & 0x0F;
60067  *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
60068  DRMP3_FLUSH_BITS(lsb ? 1 : 0);
60069  }
60071  } while (--pairs_to_decode);
60072  } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
60073  }
60074  }
60075  for (np = 1 - big_val_cnt;; dst += 4)
60076  {
60077  const drmp3_uint8 *codebook_count1 = (gr_info->count1_table) ? tab33 : tab32;
60078  int leaf = codebook_count1[DRMP3_PEEK_BITS(4)];
60079  if (!(leaf & 8))
60080  {
60081  leaf = codebook_count1[(leaf >> 3) + (bs_cache << 4 >> (32 - (leaf & 3)))];
60082  }
60083  DRMP3_FLUSH_BITS(leaf & 7);
60084  if (DRMP3_BSPOS > layer3gr_limit)
60085  {
60086  break;
60087  }
60088 #define DRMP3_RELOAD_SCALEFACTOR if (!--np) { np = *sfb++/2; if (!np) break; one = *scf++; }
60089 #define DRMP3_DEQ_COUNT1(s) if (leaf & (128 >> s)) { dst[s] = ((drmp3_int32)bs_cache < 0) ? -one : one; DRMP3_FLUSH_BITS(1) }
60091  DRMP3_DEQ_COUNT1(0);
60092  DRMP3_DEQ_COUNT1(1);
60094  DRMP3_DEQ_COUNT1(2);
60095  DRMP3_DEQ_COUNT1(3);
60097  }
60098  bs->pos = layer3gr_limit;
60099 }
60100 static void drmp3_L3_midside_stereo(float *left, int n)
60101 {
60102  int i = 0;
60103  float *right = left + 576;
60104 #if DRMP3_HAVE_SIMD
60105  if (drmp3_have_simd()) for (; i < n - 3; i += 4)
60106  {
60107  drmp3_f4 vl = DRMP3_VLD(left + i);
60108  drmp3_f4 vr = DRMP3_VLD(right + i);
60109  DRMP3_VSTORE(left + i, DRMP3_VADD(vl, vr));
60110  DRMP3_VSTORE(right + i, DRMP3_VSUB(vl, vr));
60111  }
60112 #endif
60113  for (; i < n; i++)
60114  {
60115  float a = left[i];
60116  float b = right[i];
60117  left[i] = a + b;
60118  right[i] = a - b;
60119  }
60120 }
60121 static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr)
60122 {
60123  int i;
60124  for (i = 0; i < n; i++)
60125  {
60126  left[i + 576] = left[i]*kr;
60127  left[i] = left[i]*kl;
60128  }
60129 }
60130 static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3])
60131 {
60132  int i, k;
60133  max_band[0] = max_band[1] = max_band[2] = -1;
60134  for (i = 0; i < nbands; i++)
60135  {
60136  for (k = 0; k < sfb[i]; k += 2)
60137  {
60138  if (right[k] != 0 || right[k + 1] != 0)
60139  {
60140  max_band[i % 3] = i;
60141  break;
60142  }
60143  }
60144  right += sfb[i];
60145  }
60146 }
60147 static void drmp3_L3_stereo_process(float *left, const drmp3_uint8 *ist_pos, const drmp3_uint8 *sfb, const drmp3_uint8 *hdr, int max_band[3], int mpeg2_sh)
60148 {
60149  static const float g_pan[7*2] = { 0,1,0.21132487f,0.78867513f,0.36602540f,0.63397460f,0.5f,0.5f,0.63397460f,0.36602540f,0.78867513f,0.21132487f,1,0 };
60150  unsigned i, max_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 7 : 64;
60151  for (i = 0; sfb[i]; i++)
60152  {
60153  unsigned ipos = ist_pos[i];
60154  if ((int)i > max_band[i % 3] && ipos < max_pos)
60155  {
60156  float kl, kr, s = DRMP3_HDR_TEST_MS_STEREO(hdr) ? 1.41421356f : 1;
60157  if (DRMP3_HDR_TEST_MPEG1(hdr))
60158  {
60159  kl = g_pan[2*ipos];
60160  kr = g_pan[2*ipos + 1];
60161  } else
60162  {
60163  kl = 1;
60164  kr = drmp3_L3_ldexp_q2(1, (ipos + 1) >> 1 << mpeg2_sh);
60165  if (ipos & 1)
60166  {
60167  kl = kr;
60168  kr = 1;
60169  }
60170  }
60171  drmp3_L3_intensity_stereo_band(left, sfb[i], kl*s, kr*s);
60172  } else if (DRMP3_HDR_TEST_MS_STEREO(hdr))
60173  {
60174  drmp3_L3_midside_stereo(left, sfb[i]);
60175  }
60176  left += sfb[i];
60177  }
60178 }
60179 static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
60180 {
60181  int max_band[3], n_sfb = gr->n_long_sfb + gr->n_short_sfb;
60182  int i, max_blocks = gr->n_short_sfb ? 3 : 1;
60183  drmp3_L3_stereo_top_band(left + 576, gr->sfbtab, n_sfb, max_band);
60184  if (gr->n_long_sfb)
60185  {
60186  max_band[0] = max_band[1] = max_band[2] = DRMP3_MAX(DRMP3_MAX(max_band[0], max_band[1]), max_band[2]);
60187  }
60188  for (i = 0; i < max_blocks; i++)
60189  {
60190  int default_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 3 : 0;
60191  int itop = n_sfb - max_blocks + i;
60192  int prev = itop - max_blocks;
60193  ist_pos[itop] = (drmp3_uint8)(max_band[i] >= prev ? default_pos : ist_pos[prev]);
60194  }
60195  drmp3_L3_stereo_process(left, ist_pos, gr->sfbtab, hdr, max_band, gr[1].scalefac_compress & 1);
60196 }
60197 static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb)
60198 {
60199  int i, len;
60200  float *src = grbuf, *dst = scratch;
60201  for (;0 != (len = *sfb); sfb += 3, src += 2*len)
60202  {
60203  for (i = 0; i < len; i++, src++)
60204  {
60205  *dst++ = src[0*len];
60206  *dst++ = src[1*len];
60207  *dst++ = src[2*len];
60208  }
60209  }
60210  memcpy(grbuf, scratch, (dst - scratch)*sizeof(float));
60211 }
60212 static void drmp3_L3_antialias(float *grbuf, int nbands)
60213 {
60214  static const float g_aa[2][8] = {
60215  {0.85749293f,0.88174200f,0.94962865f,0.98331459f,0.99551782f,0.99916056f,0.99989920f,0.99999316f},
60216  {0.51449576f,0.47173197f,0.31337745f,0.18191320f,0.09457419f,0.04096558f,0.01419856f,0.00369997f}
60217  };
60218  for (; nbands > 0; nbands--, grbuf += 18)
60219  {
60220  int i = 0;
60221 #if DRMP3_HAVE_SIMD
60222  if (drmp3_have_simd()) for (; i < 8; i += 4)
60223  {
60224  drmp3_f4 vu = DRMP3_VLD(grbuf + 18 + i);
60225  drmp3_f4 vd = DRMP3_VLD(grbuf + 14 - i);
60226  drmp3_f4 vc0 = DRMP3_VLD(g_aa[0] + i);
60227  drmp3_f4 vc1 = DRMP3_VLD(g_aa[1] + i);
60228  vd = DRMP3_VREV(vd);
60229  DRMP3_VSTORE(grbuf + 18 + i, DRMP3_VSUB(DRMP3_VMUL(vu, vc0), DRMP3_VMUL(vd, vc1)));
60230  vd = DRMP3_VADD(DRMP3_VMUL(vu, vc1), DRMP3_VMUL(vd, vc0));
60231  DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vd));
60232  }
60233 #endif
60234 #ifndef DR_MP3_ONLY_SIMD
60235  for(; i < 8; i++)
60236  {
60237  float u = grbuf[18 + i];
60238  float d = grbuf[17 - i];
60239  grbuf[18 + i] = u*g_aa[0][i] - d*g_aa[1][i];
60240  grbuf[17 - i] = u*g_aa[1][i] + d*g_aa[0][i];
60241  }
60242 #endif
60243  }
60244 }
60245 static void drmp3_L3_dct3_9(float *y)
60246 {
60247  float s0, s1, s2, s3, s4, s5, s6, s7, s8, t0, t2, t4;
60248  s0 = y[0]; s2 = y[2]; s4 = y[4]; s6 = y[6]; s8 = y[8];
60249  t0 = s0 + s6*0.5f;
60250  s0 -= s6;
60251  t4 = (s4 + s2)*0.93969262f;
60252  t2 = (s8 + s2)*0.76604444f;
60253  s6 = (s4 - s8)*0.17364818f;
60254  s4 += s8 - s2;
60255  s2 = s0 - s4*0.5f;
60256  y[4] = s4 + s0;
60257  s8 = t0 - t2 + s6;
60258  s0 = t0 - t4 + t2;
60259  s4 = t0 + t4 - s6;
60260  s1 = y[1]; s3 = y[3]; s5 = y[5]; s7 = y[7];
60261  s3 *= 0.86602540f;
60262  t0 = (s5 + s1)*0.98480775f;
60263  t4 = (s5 - s7)*0.34202014f;
60264  t2 = (s1 + s7)*0.64278761f;
60265  s1 = (s1 - s5 - s7)*0.86602540f;
60266  s5 = t0 - s3 - t2;
60267  s7 = t4 - s3 - t0;
60268  s3 = t4 + s3 - t2;
60269  y[0] = s4 - s7;
60270  y[1] = s2 + s1;
60271  y[2] = s0 - s3;
60272  y[3] = s8 + s5;
60273  y[5] = s8 - s5;
60274  y[6] = s0 + s3;
60275  y[7] = s2 - s1;
60276  y[8] = s4 + s7;
60277 }
60278 static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands)
60279 {
60280  int i, j;
60281  static const float g_twid9[18] = {
60282  0.73727734f,0.79335334f,0.84339145f,0.88701083f,0.92387953f,0.95371695f,0.97629601f,0.99144486f,0.99904822f,0.67559021f,0.60876143f,0.53729961f,0.46174861f,0.38268343f,0.30070580f,0.21643961f,0.13052619f,0.04361938f
60283  };
60284  for (j = 0; j < nbands; j++, grbuf += 18, overlap += 9)
60285  {
60286  float co[9], si[9];
60287  co[0] = -grbuf[0];
60288  si[0] = grbuf[17];
60289  for (i = 0; i < 4; i++)
60290  {
60291  si[8 - 2*i] = grbuf[4*i + 1] - grbuf[4*i + 2];
60292  co[1 + 2*i] = grbuf[4*i + 1] + grbuf[4*i + 2];
60293  si[7 - 2*i] = grbuf[4*i + 4] - grbuf[4*i + 3];
60294  co[2 + 2*i] = -(grbuf[4*i + 3] + grbuf[4*i + 4]);
60295  }
60296  drmp3_L3_dct3_9(co);
60297  drmp3_L3_dct3_9(si);
60298  si[1] = -si[1];
60299  si[3] = -si[3];
60300  si[5] = -si[5];
60301  si[7] = -si[7];
60302  i = 0;
60303 #if DRMP3_HAVE_SIMD
60304  if (drmp3_have_simd()) for (; i < 8; i += 4)
60305  {
60306  drmp3_f4 vovl = DRMP3_VLD(overlap + i);
60307  drmp3_f4 vc = DRMP3_VLD(co + i);
60308  drmp3_f4 vs = DRMP3_VLD(si + i);
60309  drmp3_f4 vr0 = DRMP3_VLD(g_twid9 + i);
60310  drmp3_f4 vr1 = DRMP3_VLD(g_twid9 + 9 + i);
60311  drmp3_f4 vw0 = DRMP3_VLD(window + i);
60312  drmp3_f4 vw1 = DRMP3_VLD(window + 9 + i);
60313  drmp3_f4 vsum = DRMP3_VADD(DRMP3_VMUL(vc, vr1), DRMP3_VMUL(vs, vr0));
60314  DRMP3_VSTORE(overlap + i, DRMP3_VSUB(DRMP3_VMUL(vc, vr0), DRMP3_VMUL(vs, vr1)));
60315  DRMP3_VSTORE(grbuf + i, DRMP3_VSUB(DRMP3_VMUL(vovl, vw0), DRMP3_VMUL(vsum, vw1)));
60316  vsum = DRMP3_VADD(DRMP3_VMUL(vovl, vw1), DRMP3_VMUL(vsum, vw0));
60317  DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vsum));
60318  }
60319 #endif
60320  for (; i < 9; i++)
60321  {
60322  float ovl = overlap[i];
60323  float sum = co[i]*g_twid9[9 + i] + si[i]*g_twid9[0 + i];
60324  overlap[i] = co[i]*g_twid9[0 + i] - si[i]*g_twid9[9 + i];
60325  grbuf[i] = ovl*window[0 + i] - sum*window[9 + i];
60326  grbuf[17 - i] = ovl*window[9 + i] + sum*window[0 + i];
60327  }
60328  }
60329 }
60330 static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst)
60331 {
60332  float m1 = x1*0.86602540f;
60333  float a1 = x0 - x2*0.5f;
60334  dst[1] = x0 + x2;
60335  dst[0] = a1 + m1;
60336  dst[2] = a1 - m1;
60337 }
60338 static void drmp3_L3_imdct12(float *x, float *dst, float *overlap)
60339 {
60340  static const float g_twid3[6] = { 0.79335334f,0.92387953f,0.99144486f, 0.60876143f,0.38268343f,0.13052619f };
60341  float co[3], si[3];
60342  int i;
60343  drmp3_L3_idct3(-x[0], x[6] + x[3], x[12] + x[9], co);
60344  drmp3_L3_idct3(x[15], x[12] - x[9], x[6] - x[3], si);
60345  si[1] = -si[1];
60346  for (i = 0; i < 3; i++)
60347  {
60348  float ovl = overlap[i];
60349  float sum = co[i]*g_twid3[3 + i] + si[i]*g_twid3[0 + i];
60350  overlap[i] = co[i]*g_twid3[0 + i] - si[i]*g_twid3[3 + i];
60351  dst[i] = ovl*g_twid3[2 - i] - sum*g_twid3[5 - i];
60352  dst[5 - i] = ovl*g_twid3[5 - i] + sum*g_twid3[2 - i];
60353  }
60354 }
60355 static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands)
60356 {
60357  for (;nbands > 0; nbands--, overlap += 9, grbuf += 18)
60358  {
60359  float tmp[18];
60360  memcpy(tmp, grbuf, sizeof(tmp));
60361  memcpy(grbuf, overlap, 6*sizeof(float));
60362  drmp3_L3_imdct12(tmp, grbuf + 6, overlap + 6);
60363  drmp3_L3_imdct12(tmp + 1, grbuf + 12, overlap + 6);
60364  drmp3_L3_imdct12(tmp + 2, overlap, overlap + 6);
60365  }
60366 }
60367 static void drmp3_L3_change_sign(float *grbuf)
60368 {
60369  int b, i;
60370  for (b = 0, grbuf += 18; b < 32; b += 2, grbuf += 36)
60371  for (i = 1; i < 18; i += 2)
60372  grbuf[i] = -grbuf[i];
60373 }
60374 static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands)
60375 {
60376  static const float g_mdct_window[2][18] = {
60377  { 0.99904822f,0.99144486f,0.97629601f,0.95371695f,0.92387953f,0.88701083f,0.84339145f,0.79335334f,0.73727734f,0.04361938f,0.13052619f,0.21643961f,0.30070580f,0.38268343f,0.46174861f,0.53729961f,0.60876143f,0.67559021f },
60378  { 1,1,1,1,1,1,0.99144486f,0.92387953f,0.79335334f,0,0,0,0,0,0,0.13052619f,0.38268343f,0.60876143f }
60379  };
60380  if (n_long_bands)
60381  {
60382  drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands);
60383  grbuf += 18*n_long_bands;
60384  overlap += 9*n_long_bands;
60385  }
60386  if (block_type == DRMP3_SHORT_BLOCK_TYPE)
60387  drmp3_L3_imdct_short(grbuf, overlap, 32 - n_long_bands);
60388  else
60389  drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[block_type == DRMP3_STOP_BLOCK_TYPE], 32 - n_long_bands);
60390 }
60392 {
60393  int pos = (s->bs.pos + 7)/8u;
60394  int remains = s->bs.limit/8u - pos;
60395  if (remains > DRMP3_MAX_BITRESERVOIR_BYTES)
60396  {
60397  pos += remains - DRMP3_MAX_BITRESERVOIR_BYTES;
60398  remains = DRMP3_MAX_BITRESERVOIR_BYTES;
60399  }
60400  if (remains > 0)
60401  {
60402  memmove(h->reserv_buf, s->maindata + pos, remains);
60403  }
60404  h->reserv = remains;
60405 }
60406 static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin)
60407 {
60408  int frame_bytes = (bs->limit - bs->pos)/8;
60409  int bytes_have = DRMP3_MIN(h->reserv, main_data_begin);
60410  memcpy(s->maindata, h->reserv_buf + DRMP3_MAX(0, h->reserv - main_data_begin), DRMP3_MIN(h->reserv, main_data_begin));
60411  memcpy(s->maindata + bytes_have, bs->buf + bs->pos/8, frame_bytes);
60412  drmp3_bs_init(&s->bs, s->maindata, bytes_have + frame_bytes);
60413  return h->reserv >= main_data_begin;
60414 }
60415 static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch)
60416 {
60417  int ch;
60418  for (ch = 0; ch < nch; ch++)
60419  {
60420  int layer3gr_limit = s->bs.pos + gr_info[ch].part_23_length;
60421  drmp3_L3_decode_scalefactors(h->header, s->ist_pos[ch], &s->bs, gr_info + ch, s->scf, ch);
60422  drmp3_L3_huffman(s->grbuf[ch], &s->bs, gr_info + ch, s->scf, layer3gr_limit);
60423  }
60425  {
60426  drmp3_L3_intensity_stereo(s->grbuf[0], s->ist_pos[1], gr_info, h->header);
60427  } else if (DRMP3_HDR_IS_MS_STEREO(h->header))
60428  {
60429  drmp3_L3_midside_stereo(s->grbuf[0], 576);
60430  }
60431  for (ch = 0; ch < nch; ch++, gr_info++)
60432  {
60433  int aa_bands = 31;
60434  int n_long_bands = (gr_info->mixed_block_flag ? 2 : 0) << (int)(DRMP3_HDR_GET_MY_SAMPLE_RATE(h->header) == 2);
60435  if (gr_info->n_short_sfb)
60436  {
60437  aa_bands = n_long_bands - 1;
60438  drmp3_L3_reorder(s->grbuf[ch] + n_long_bands*18, s->syn[0], gr_info->sfbtab + gr_info->n_long_sfb);
60439  }
60440  drmp3_L3_antialias(s->grbuf[ch], aa_bands);
60441  drmp3_L3_imdct_gr(s->grbuf[ch], h->mdct_overlap[ch], gr_info->block_type, n_long_bands);
60442  drmp3_L3_change_sign(s->grbuf[ch]);
60443  }
60444 }
60445 static void drmp3d_DCT_II(float *grbuf, int n)
60446 {
60447  static const float g_sec[24] = {
60448  10.19000816f,0.50060302f,0.50241929f,3.40760851f,0.50547093f,0.52249861f,2.05778098f,0.51544732f,0.56694406f,1.48416460f,0.53104258f,0.64682180f,1.16943991f,0.55310392f,0.78815460f,0.97256821f,0.58293498f,1.06067765f,0.83934963f,0.62250412f,1.72244716f,0.74453628f,0.67480832f,5.10114861f
60449  };
60450  int i, k = 0;
60451 #if DRMP3_HAVE_SIMD
60452  if (drmp3_have_simd()) for (; k < n; k += 4)
60453  {
60454  drmp3_f4 t[4][8], *x;
60455  float *y = grbuf + k;
60456  for (x = t[0], i = 0; i < 8; i++, x++)
60457  {
60458  drmp3_f4 x0 = DRMP3_VLD(&y[i*18]);
60459  drmp3_f4 x1 = DRMP3_VLD(&y[(15 - i)*18]);
60460  drmp3_f4 x2 = DRMP3_VLD(&y[(16 + i)*18]);
60461  drmp3_f4 x3 = DRMP3_VLD(&y[(31 - i)*18]);
60462  drmp3_f4 t0 = DRMP3_VADD(x0, x3);
60463  drmp3_f4 t1 = DRMP3_VADD(x1, x2);
60464  drmp3_f4 t2 = DRMP3_VMUL_S(DRMP3_VSUB(x1, x2), g_sec[3*i + 0]);
60465  drmp3_f4 t3 = DRMP3_VMUL_S(DRMP3_VSUB(x0, x3), g_sec[3*i + 1]);
60466  x[0] = DRMP3_VADD(t0, t1);
60467  x[8] = DRMP3_VMUL_S(DRMP3_VSUB(t0, t1), g_sec[3*i + 2]);
60468  x[16] = DRMP3_VADD(t3, t2);
60469  x[24] = DRMP3_VMUL_S(DRMP3_VSUB(t3, t2), g_sec[3*i + 2]);
60470  }
60471  for (x = t[0], i = 0; i < 4; i++, x += 8)
60472  {
60473  drmp3_f4 x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt;
60474  xt = DRMP3_VSUB(x0, x7); x0 = DRMP3_VADD(x0, x7);
60475  x7 = DRMP3_VSUB(x1, x6); x1 = DRMP3_VADD(x1, x6);
60476  x6 = DRMP3_VSUB(x2, x5); x2 = DRMP3_VADD(x2, x5);
60477  x5 = DRMP3_VSUB(x3, x4); x3 = DRMP3_VADD(x3, x4);
60478  x4 = DRMP3_VSUB(x0, x3); x0 = DRMP3_VADD(x0, x3);
60479  x3 = DRMP3_VSUB(x1, x2); x1 = DRMP3_VADD(x1, x2);
60480  x[0] = DRMP3_VADD(x0, x1);
60481  x[4] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x1), 0.70710677f);
60482  x5 = DRMP3_VADD(x5, x6);
60483  x6 = DRMP3_VMUL_S(DRMP3_VADD(x6, x7), 0.70710677f);
60484  x7 = DRMP3_VADD(x7, xt);
60485  x3 = DRMP3_VMUL_S(DRMP3_VADD(x3, x4), 0.70710677f);
60486  x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f));
60487  x7 = DRMP3_VADD(x7, DRMP3_VMUL_S(x5, 0.382683432f));
60488  x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f));
60489  x0 = DRMP3_VSUB(xt, x6); xt = DRMP3_VADD(xt, x6);
60490  x[1] = DRMP3_VMUL_S(DRMP3_VADD(xt, x7), 0.50979561f);
60491  x[2] = DRMP3_VMUL_S(DRMP3_VADD(x4, x3), 0.54119611f);
60492  x[3] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x5), 0.60134488f);
60493  x[5] = DRMP3_VMUL_S(DRMP3_VADD(x0, x5), 0.89997619f);
60494  x[6] = DRMP3_VMUL_S(DRMP3_VSUB(x4, x3), 1.30656302f);
60495  x[7] = DRMP3_VMUL_S(DRMP3_VSUB(xt, x7), 2.56291556f);
60496  }
60497  if (k > n - 3)
60498  {
60499 #if DRMP3_HAVE_SSE
60500 #define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v)
60501 #else
60502 #define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[i*18], vget_low_f32(v))
60503 #endif
60504  for (i = 0; i < 7; i++, y += 4*18)
60505  {
60506  drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
60507  DRMP3_VSAVE2(0, t[0][i]);
60508  DRMP3_VSAVE2(1, DRMP3_VADD(t[2][i], s));
60509  DRMP3_VSAVE2(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
60510  DRMP3_VSAVE2(3, DRMP3_VADD(t[2][1 + i], s));
60511  }
60512  DRMP3_VSAVE2(0, t[0][7]);
60513  DRMP3_VSAVE2(1, DRMP3_VADD(t[2][7], t[3][7]));
60514  DRMP3_VSAVE2(2, t[1][7]);
60515  DRMP3_VSAVE2(3, t[3][7]);
60516  } else
60517  {
60518 #define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[i*18], v)
60519  for (i = 0; i < 7; i++, y += 4*18)
60520  {
60521  drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
60522  DRMP3_VSAVE4(0, t[0][i]);
60523  DRMP3_VSAVE4(1, DRMP3_VADD(t[2][i], s));
60524  DRMP3_VSAVE4(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
60525  DRMP3_VSAVE4(3, DRMP3_VADD(t[2][1 + i], s));
60526  }
60527  DRMP3_VSAVE4(0, t[0][7]);
60528  DRMP3_VSAVE4(1, DRMP3_VADD(t[2][7], t[3][7]));
60529  DRMP3_VSAVE4(2, t[1][7]);
60530  DRMP3_VSAVE4(3, t[3][7]);
60531  }
60532  } else
60533 #endif
60534 #ifdef DR_MP3_ONLY_SIMD
60535  {}
60536 #else
60537  for (; k < n; k++)
60538  {
60539  float t[4][8], *x, *y = grbuf + k;
60540  for (x = t[0], i = 0; i < 8; i++, x++)
60541  {
60542  float x0 = y[i*18];
60543  float x1 = y[(15 - i)*18];
60544  float x2 = y[(16 + i)*18];
60545  float x3 = y[(31 - i)*18];
60546  float t0 = x0 + x3;
60547  float t1 = x1 + x2;
60548  float t2 = (x1 - x2)*g_sec[3*i + 0];
60549  float t3 = (x0 - x3)*g_sec[3*i + 1];
60550  x[0] = t0 + t1;
60551  x[8] = (t0 - t1)*g_sec[3*i + 2];
60552  x[16] = t3 + t2;
60553  x[24] = (t3 - t2)*g_sec[3*i + 2];
60554  }
60555  for (x = t[0], i = 0; i < 4; i++, x += 8)
60556  {
60557  float x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt;
60558  xt = x0 - x7; x0 += x7;
60559  x7 = x1 - x6; x1 += x6;
60560  x6 = x2 - x5; x2 += x5;
60561  x5 = x3 - x4; x3 += x4;
60562  x4 = x0 - x3; x0 += x3;
60563  x3 = x1 - x2; x1 += x2;
60564  x[0] = x0 + x1;
60565  x[4] = (x0 - x1)*0.70710677f;
60566  x5 = x5 + x6;
60567  x6 = (x6 + x7)*0.70710677f;
60568  x7 = x7 + xt;
60569  x3 = (x3 + x4)*0.70710677f;
60570  x5 -= x7*0.198912367f;
60571  x7 += x5*0.382683432f;
60572  x5 -= x7*0.198912367f;
60573  x0 = xt - x6; xt += x6;
60574  x[1] = (xt + x7)*0.50979561f;
60575  x[2] = (x4 + x3)*0.54119611f;
60576  x[3] = (x0 - x5)*0.60134488f;
60577  x[5] = (x0 + x5)*0.89997619f;
60578  x[6] = (x4 - x3)*1.30656302f;
60579  x[7] = (xt - x7)*2.56291556f;
60580  }
60581  for (i = 0; i < 7; i++, y += 4*18)
60582  {
60583  y[0*18] = t[0][i];
60584  y[1*18] = t[2][i] + t[3][i] + t[3][i + 1];
60585  y[2*18] = t[1][i] + t[1][i + 1];
60586  y[3*18] = t[2][i + 1] + t[3][i] + t[3][i + 1];
60587  }
60588  y[0*18] = t[0][7];
60589  y[1*18] = t[2][7] + t[3][7];
60590  y[2*18] = t[1][7];
60591  y[3*18] = t[3][7];
60592  }
60593 #endif
60594 }
60595 #ifndef DR_MP3_FLOAT_OUTPUT
60597 static drmp3_int16 drmp3d_scale_pcm(float sample)
60598 {
60599  drmp3_int16 s;
60600 #if DRMP3_HAVE_ARMV6
60601  drmp3_int32 s32 = (drmp3_int32)(sample + .5f);
60602  s32 -= (s32 < 0);
60603  s = (drmp3_int16)drmp3_clip_int16_arm(s32);
60604 #else
60605  if (sample >= 32766.5) return (drmp3_int16) 32767;
60606  if (sample <= -32767.5) return (drmp3_int16)-32768;
60607  s = (drmp3_int16)(sample + .5f);
60608  s -= (s < 0);
60609 #endif
60610  return s;
60611 }
60612 #else
60613 typedef float drmp3d_sample_t;
60614 static float drmp3d_scale_pcm(float sample)
60615 {
60616  return sample*(1.f/32768.f);
60617 }
60618 #endif
60619 static void drmp3d_synth_pair(drmp3d_sample_t *pcm, int nch, const float *z)
60620 {
60621  float a;
60622  a = (z[14*64] - z[ 0]) * 29;
60623  a += (z[ 1*64] + z[13*64]) * 213;
60624  a += (z[12*64] - z[ 2*64]) * 459;
60625  a += (z[ 3*64] + z[11*64]) * 2037;
60626  a += (z[10*64] - z[ 4*64]) * 5153;
60627  a += (z[ 5*64] + z[ 9*64]) * 6574;
60628  a += (z[ 8*64] - z[ 6*64]) * 37489;
60629  a += z[ 7*64] * 75038;
60630  pcm[0] = drmp3d_scale_pcm(a);
60631  z += 2;
60632  a = z[14*64] * 104;
60633  a += z[12*64] * 1567;
60634  a += z[10*64] * 9727;
60635  a += z[ 8*64] * 64019;
60636  a += z[ 6*64] * -9975;
60637  a += z[ 4*64] * -45;
60638  a += z[ 2*64] * 146;
60639  a += z[ 0*64] * -5;
60640  pcm[16*nch] = drmp3d_scale_pcm(a);
60641 }
60642 static void drmp3d_synth(float *xl, drmp3d_sample_t *dstl, int nch, float *lins)
60643 {
60644  int i;
60645  float *xr = xl + 576*(nch - 1);
60646  drmp3d_sample_t *dstr = dstl + (nch - 1);
60647  static const float g_win[] = {
60648  -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
60649  -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
60650  -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
60651  -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
60652  -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
60653  -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
60654  -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
60655  -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
60656  -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
60657  -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
60658  -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
60659  -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
60660  -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
60661  -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
60662  -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
60663  };
60664  float *zlin = lins + 15*64;
60665  const float *w = g_win;
60666  zlin[4*15] = xl[18*16];
60667  zlin[4*15 + 1] = xr[18*16];
60668  zlin[4*15 + 2] = xl[0];
60669  zlin[4*15 + 3] = xr[0];
60670  zlin[4*31] = xl[1 + 18*16];
60671  zlin[4*31 + 1] = xr[1 + 18*16];
60672  zlin[4*31 + 2] = xl[1];
60673  zlin[4*31 + 3] = xr[1];
60674  drmp3d_synth_pair(dstr, nch, lins + 4*15 + 1);
60675  drmp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1);
60676  drmp3d_synth_pair(dstl, nch, lins + 4*15);
60677  drmp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64);
60678 #if DRMP3_HAVE_SIMD
60679  if (drmp3_have_simd()) for (i = 14; i >= 0; i--)
60680  {
60681 #define DRMP3_VLOAD(k) drmp3_f4 w0 = DRMP3_VSET(*w++); drmp3_f4 w1 = DRMP3_VSET(*w++); drmp3_f4 vz = DRMP3_VLD(&zlin[4*i - 64*k]); drmp3_f4 vy = DRMP3_VLD(&zlin[4*i - 64*(15 - k)]);
60682 #define DRMP3_V0(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0)) ; a = DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1)); }
60683 #define DRMP3_V1(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1))); }
60684 #define DRMP3_V2(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vy, w1), DRMP3_VMUL(vz, w0))); }
60685  drmp3_f4 a, b;
60686  zlin[4*i] = xl[18*(31 - i)];
60687  zlin[4*i + 1] = xr[18*(31 - i)];
60688  zlin[4*i + 2] = xl[1 + 18*(31 - i)];
60689  zlin[4*i + 3] = xr[1 + 18*(31 - i)];
60690  zlin[4*i + 64] = xl[1 + 18*(1 + i)];
60691  zlin[4*i + 64 + 1] = xr[1 + 18*(1 + i)];
60692  zlin[4*i - 64 + 2] = xl[18*(1 + i)];
60693  zlin[4*i - 64 + 3] = xr[18*(1 + i)];
60694  DRMP3_V0(0) DRMP3_V2(1) DRMP3_V1(2) DRMP3_V2(3) DRMP3_V1(4) DRMP3_V2(5) DRMP3_V1(6) DRMP3_V2(7)
60695  {
60696 #ifndef DR_MP3_FLOAT_OUTPUT
60697 #if DRMP3_HAVE_SSE
60698  static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f };
60699  static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f };
60700  __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)),
60701  _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min)));
60702  dstr[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
60703  dstr[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
60704  dstl[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
60705  dstl[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
60706  dstr[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
60707  dstr[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
60708  dstl[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
60709  dstl[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
60710 #else
60711  int16x4_t pcma, pcmb;
60712  a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
60713  b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
60714  pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
60715  pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
60716  vst1_lane_s16(dstr + (15 - i)*nch, pcma, 1);
60717  vst1_lane_s16(dstr + (17 + i)*nch, pcmb, 1);
60718  vst1_lane_s16(dstl + (15 - i)*nch, pcma, 0);
60719  vst1_lane_s16(dstl + (17 + i)*nch, pcmb, 0);
60720  vst1_lane_s16(dstr + (47 - i)*nch, pcma, 3);
60721  vst1_lane_s16(dstr + (49 + i)*nch, pcmb, 3);
60722  vst1_lane_s16(dstl + (47 - i)*nch, pcma, 2);
60723  vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2);
60724 #endif
60725 #else
60726  static const drmp3_f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f };
60727  a = DRMP3_VMUL(a, g_scale);
60728  b = DRMP3_VMUL(b, g_scale);
60729 #if DRMP3_HAVE_SSE
60730  _mm_store_ss(dstr + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)));
60731  _mm_store_ss(dstr + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(1, 1, 1, 1)));
60732  _mm_store_ss(dstl + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)));
60733  _mm_store_ss(dstl + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(0, 0, 0, 0)));
60734  _mm_store_ss(dstr + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)));
60735  _mm_store_ss(dstr + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 3, 3, 3)));
60736  _mm_store_ss(dstl + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
60737  _mm_store_ss(dstl + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(2, 2, 2, 2)));
60738 #else
60739  vst1q_lane_f32(dstr + (15 - i)*nch, a, 1);
60740  vst1q_lane_f32(dstr + (17 + i)*nch, b, 1);
60741  vst1q_lane_f32(dstl + (15 - i)*nch, a, 0);
60742  vst1q_lane_f32(dstl + (17 + i)*nch, b, 0);
60743  vst1q_lane_f32(dstr + (47 - i)*nch, a, 3);
60744  vst1q_lane_f32(dstr + (49 + i)*nch, b, 3);
60745  vst1q_lane_f32(dstl + (47 - i)*nch, a, 2);
60746  vst1q_lane_f32(dstl + (49 + i)*nch, b, 2);
60747 #endif
60748 #endif
60749  }
60750  } else
60751 #endif
60752 #ifdef DR_MP3_ONLY_SIMD
60753  {}
60754 #else
60755  for (i = 14; i >= 0; i--)
60756  {
60757 #define DRMP3_LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin[4*i - k*64]; float *vy = &zlin[4*i - (15 - k)*64];
60758 #define DRMP3_S0(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] = vz[j]*w1 + vy[j]*w0, a[j] = vz[j]*w0 - vy[j]*w1; }
60759 #define DRMP3_S1(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vz[j]*w0 - vy[j]*w1; }
60760 #define DRMP3_S2(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vy[j]*w1 - vz[j]*w0; }
60761  float a[4], b[4];
60762  zlin[4*i] = xl[18*(31 - i)];
60763  zlin[4*i + 1] = xr[18*(31 - i)];
60764  zlin[4*i + 2] = xl[1 + 18*(31 - i)];
60765  zlin[4*i + 3] = xr[1 + 18*(31 - i)];
60766  zlin[4*(i + 16)] = xl[1 + 18*(1 + i)];
60767  zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)];
60768  zlin[4*(i - 16) + 2] = xl[18*(1 + i)];
60769  zlin[4*(i - 16) + 3] = xr[18*(1 + i)];
60771  dstr[(15 - i)*nch] = drmp3d_scale_pcm(a[1]);
60772  dstr[(17 + i)*nch] = drmp3d_scale_pcm(b[1]);
60773  dstl[(15 - i)*nch] = drmp3d_scale_pcm(a[0]);
60774  dstl[(17 + i)*nch] = drmp3d_scale_pcm(b[0]);
60775  dstr[(47 - i)*nch] = drmp3d_scale_pcm(a[3]);
60776  dstr[(49 + i)*nch] = drmp3d_scale_pcm(b[3]);
60777  dstl[(47 - i)*nch] = drmp3d_scale_pcm(a[2]);
60778  dstl[(49 + i)*nch] = drmp3d_scale_pcm(b[2]);
60779  }
60780 #endif
60781 }
60782 static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, drmp3d_sample_t *pcm, float *lins)
60783 {
60784  int i;
60785  for (i = 0; i < nch; i++)
60786  {
60787  drmp3d_DCT_II(grbuf + 576*i, nbands);
60788  }
60789  memcpy(lins, qmf_state, sizeof(float)*15*64);
60790  for (i = 0; i < nbands; i += 2)
60791  {
60792  drmp3d_synth(grbuf + i, pcm + 32*nch*i, nch, lins + i*64);
60793  }
60794 #ifndef DR_MP3_NONSTANDARD_BUT_LOGICAL
60795  if (nch == 1)
60796  {
60797  for (i = 0; i < 15*64; i += 2)
60798  {
60799  qmf_state[i] = lins[nbands*64 + i];
60800  }
60801  } else
60802 #endif
60803  {
60804  memcpy(qmf_state, lins + nbands*64, sizeof(float)*15*64);
60805  }
60806 }
60807 static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes)
60808 {
60809  int i, nmatch;
60810  for (i = 0, nmatch = 0; nmatch < DRMP3_MAX_FRAME_SYNC_MATCHES; nmatch++)
60811  {
60812  i += drmp3_hdr_frame_bytes(hdr + i, frame_bytes) + drmp3_hdr_padding(hdr + i);
60813  if (i + DRMP3_HDR_SIZE > mp3_bytes)
60814  return nmatch > 0;
60815  if (!drmp3_hdr_compare(hdr, hdr + i))
60816  return 0;
60817  }
60818  return 1;
60819 }
60820 static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes)
60821 {
60822  int i, k;
60823  for (i = 0; i < mp3_bytes - DRMP3_HDR_SIZE; i++, mp3++)
60824  {
60825  if (drmp3_hdr_valid(mp3))
60826  {
60827  int frame_bytes = drmp3_hdr_frame_bytes(mp3, *free_format_bytes);
60828  int frame_and_padding = frame_bytes + drmp3_hdr_padding(mp3);
60829  for (k = DRMP3_HDR_SIZE; !frame_bytes && k < DRMP3_MAX_FREE_FORMAT_FRAME_SIZE && i + 2*k < mp3_bytes - DRMP3_HDR_SIZE; k++)
60830  {
60831  if (drmp3_hdr_compare(mp3, mp3 + k))
60832  {
60833  int fb = k - drmp3_hdr_padding(mp3);
60834  int nextfb = fb + drmp3_hdr_padding(mp3 + k);
60835  if (i + k + nextfb + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + k + nextfb))
60836  continue;
60837  frame_and_padding = k;
60838  frame_bytes = fb;
60839  *free_format_bytes = fb;
60840  }
60841  }
60842  if ((frame_bytes && i + frame_and_padding <= mp3_bytes &&
60843  drmp3d_match_frame(mp3, mp3_bytes - i, frame_bytes)) ||
60844  (!i && frame_and_padding == mp3_bytes))
60845  {
60846  *ptr_frame_bytes = frame_and_padding;
60847  return i;
60848  }
60849  *free_format_bytes = 0;
60850  }
60851  }
60852  *ptr_frame_bytes = 0;
60853  return mp3_bytes;
60854 }
60856 {
60857  dec->header[0] = 0;
60858 }
60859 DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info)
60860 {
60861  int i = 0, igr, frame_size = 0, success = 1;
60862  const drmp3_uint8 *hdr;
60863  drmp3_bs bs_frame[1];
60864  drmp3dec_scratch scratch;
60865  if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
60866  {
60867  frame_size = drmp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + drmp3_hdr_padding(mp3);
60868  if (frame_size != mp3_bytes && (frame_size + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + frame_size)))
60869  {
60870  frame_size = 0;
60871  }
60872  }
60873  if (!frame_size)
60874  {
60875  memset(dec, 0, sizeof(drmp3dec));
60876  i = drmp3d_find_frame(mp3, mp3_bytes, &dec->free_format_bytes, &frame_size);
60877  if (!frame_size || i + frame_size > mp3_bytes)
60878  {
60879  info->frame_bytes = i;
60880  return 0;
60881  }
60882  }
60883  hdr = mp3 + i;
60884  memcpy(dec->header, hdr, DRMP3_HDR_SIZE);
60885  info->frame_bytes = i + frame_size;
60886  info->channels = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
60887  info->hz = drmp3_hdr_sample_rate_hz(hdr);
60888  info->layer = 4 - DRMP3_HDR_GET_LAYER(hdr);
60889  info->bitrate_kbps = drmp3_hdr_bitrate_kbps(hdr);
60890  drmp3_bs_init(bs_frame, hdr + DRMP3_HDR_SIZE, frame_size - DRMP3_HDR_SIZE);
60891  if (DRMP3_HDR_IS_CRC(hdr))
60892  {
60893  drmp3_bs_get_bits(bs_frame, 16);
60894  }
60895  if (info->layer == 3)
60896  {
60897  int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
60898  if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
60899  {
60900  drmp3dec_init(dec);
60901  return 0;
60902  }
60903  success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
60904  if (success && pcm != NULL)
60905  {
60906  for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
60907  {
60908  memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
60909  drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
60910  drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
60911  }
60912  }
60913  drmp3_L3_save_reservoir(dec, &scratch);
60914  } else
60915  {
60916 #ifdef DR_MP3_ONLY_MP3
60917  return 0;
60918 #else
60919  drmp3_L12_scale_info sci[1];
60920  if (pcm == NULL) {
60921  return drmp3_hdr_frame_samples(hdr);
60922  }
60923  drmp3_L12_read_scale_info(hdr, bs_frame, sci);
60924  memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
60925  for (i = 0, igr = 0; igr < 3; igr++)
60926  {
60927  if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
60928  {
60929  i = 0;
60930  drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
60931  drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
60932  memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
60933  pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
60934  }
60935  if (bs_frame->pos > bs_frame->limit)
60936  {
60937  drmp3dec_init(dec);
60938  return 0;
60939  }
60940  }
60941 #endif
60942  }
60943  return success*drmp3_hdr_frame_samples(dec->header);
60944 }
60945 DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples)
60946 {
60947  size_t i = 0;
60948 #if DRMP3_HAVE_SIMD
60949  size_t aligned_count = num_samples & ~7;
60950  for(; i < aligned_count; i+=8)
60951  {
60952  drmp3_f4 scale = DRMP3_VSET(32768.0f);
60953  drmp3_f4 a = DRMP3_VMUL(DRMP3_VLD(&in[i ]), scale);
60954  drmp3_f4 b = DRMP3_VMUL(DRMP3_VLD(&in[i+4]), scale);
60955 #if DRMP3_HAVE_SSE
60956  drmp3_f4 s16max = DRMP3_VSET( 32767.0f);
60957  drmp3_f4 s16min = DRMP3_VSET(-32768.0f);
60958  __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, s16max), s16min)),
60959  _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, s16max), s16min)));
60960  out[i ] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
60961  out[i+1] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
60962  out[i+2] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
60963  out[i+3] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
60964  out[i+4] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
60965  out[i+5] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
60966  out[i+6] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
60967  out[i+7] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
60968 #else
60969  int16x4_t pcma, pcmb;
60970  a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
60971  b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
60972  pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
60973  pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
60974  vst1_lane_s16(out+i , pcma, 0);
60975  vst1_lane_s16(out+i+1, pcma, 1);
60976  vst1_lane_s16(out+i+2, pcma, 2);
60977  vst1_lane_s16(out+i+3, pcma, 3);
60978  vst1_lane_s16(out+i+4, pcmb, 0);
60979  vst1_lane_s16(out+i+5, pcmb, 1);
60980  vst1_lane_s16(out+i+6, pcmb, 2);
60981  vst1_lane_s16(out+i+7, pcmb, 3);
60982 #endif
60983  }
60984 #endif
60985  for(; i < num_samples; i++)
60986  {
60987  float sample = in[i] * 32768.0f;
60988  if (sample >= 32766.5)
60989  out[i] = (drmp3_int16) 32767;
60990  else if (sample <= -32767.5)
60991  out[i] = (drmp3_int16)-32768;
60992  else
60993  {
60994  short s = (drmp3_int16)(sample + .5f);
60995  s -= (s < 0);
60996  out[i] = s;
60997  }
60998  }
60999 }
61000 #include <math.h>
61001 #if defined(SIZE_MAX)
61002  #define DRMP3_SIZE_MAX SIZE_MAX
61003 #else
61004  #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
61005  #define DRMP3_SIZE_MAX ((drmp3_uint64)0xFFFFFFFFFFFFFFFF)
61006  #else
61007  #define DRMP3_SIZE_MAX 0xFFFFFFFF
61008  #endif
61009 #endif
61010 #ifndef DRMP3_SEEK_LEADING_MP3_FRAMES
61011 #define DRMP3_SEEK_LEADING_MP3_FRAMES 2
61012 #endif
61013 #define DRMP3_MIN_DATA_CHUNK_SIZE 16384
61014 #ifndef DRMP3_DATA_CHUNK_SIZE
61015 #define DRMP3_DATA_CHUNK_SIZE DRMP3_MIN_DATA_CHUNK_SIZE*4
61016 #endif
61017 #ifndef DRMP3_ASSERT
61018 #include <assert.h>
61019 #define DRMP3_ASSERT(expression) assert(expression)
61020 #endif
61021 #ifndef DRMP3_COPY_MEMORY
61022 #define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
61023 #endif
61024 #ifndef DRMP3_ZERO_MEMORY
61025 #define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
61026 #endif
61027 #define DRMP3_ZERO_OBJECT(p) DRMP3_ZERO_MEMORY((p), sizeof(*(p)))
61028 #ifndef DRMP3_MALLOC
61029 #define DRMP3_MALLOC(sz) malloc((sz))
61030 #endif
61031 #ifndef DRMP3_REALLOC
61032 #define DRMP3_REALLOC(p, sz) realloc((p), (sz))
61033 #endif
61034 #ifndef DRMP3_FREE
61035 #define DRMP3_FREE(p) free((p))
61036 #endif
61037 #define DRMP3_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
61038 #define DRMP3_CLAMP(x, lo, hi) (DRMP3_MAX(lo, DRMP3_MIN(x, hi)))
61039 #ifndef DRMP3_PI_D
61040 #define DRMP3_PI_D 3.14159265358979323846264
61041 #endif
61042 #define DRMP3_DEFAULT_RESAMPLER_LPF_ORDER 2
61043 static DRMP3_INLINE float drmp3_mix_f32(float x, float y, float a)
61044 {
61045  return x*(1-a) + y*a;
61046 }
61047 static DRMP3_INLINE float drmp3_mix_f32_fast(float x, float y, float a)
61048 {
61049  float r0 = (y - x);
61050  float r1 = r0*a;
61051  return x + r1;
61052 }
61054 {
61055  for (;;) {
61056  if (b == 0) {
61057  break;
61058  } else {
61059  drmp3_uint32 t = a;
61060  a = b;
61061  b = t % a;
61062  }
61063  }
61064  return a;
61065 }
61066 static DRMP3_INLINE double drmp3_sin(double x)
61067 {
61068  return sin(x);
61069 }
61070 static DRMP3_INLINE double drmp3_exp(double x)
61071 {
61072  return exp(x);
61073 }
61074 static DRMP3_INLINE double drmp3_cos(double x)
61075 {
61076  return drmp3_sin((DRMP3_PI_D*0.5) - x);
61077 }
61078 static void* drmp3__malloc_default(size_t sz, void* pUserData)
61079 {
61080  (void)pUserData;
61081  return DRMP3_MALLOC(sz);
61082 }
61083 static void* drmp3__realloc_default(void* p, size_t sz, void* pUserData)
61084 {
61085  (void)pUserData;
61086  return DRMP3_REALLOC(p, sz);
61087 }
61088 static void drmp3__free_default(void* p, void* pUserData)
61089 {
61090  (void)pUserData;
61091  DRMP3_FREE(p);
61092 }
61093 static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
61094 {
61095  if (pAllocationCallbacks == NULL) {
61096  return NULL;
61097  }
61098  if (pAllocationCallbacks->onMalloc != NULL) {
61099  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
61100  }
61101  if (pAllocationCallbacks->onRealloc != NULL) {
61102  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
61103  }
61104  return NULL;
61105 }
61106 static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks* pAllocationCallbacks)
61107 {
61108  if (pAllocationCallbacks == NULL) {
61109  return NULL;
61110  }
61111  if (pAllocationCallbacks->onRealloc != NULL) {
61112  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
61113  }
61114  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
61115  void* p2;
61116  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
61117  if (p2 == NULL) {
61118  return NULL;
61119  }
61120  if (p != NULL) {
61121  DRMP3_COPY_MEMORY(p2, p, szOld);
61122  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
61123  }
61124  return p2;
61125  }
61126  return NULL;
61127 }
61128 static void drmp3__free_from_callbacks(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
61129 {
61130  if (p == NULL || pAllocationCallbacks == NULL) {
61131  return;
61132  }
61133  if (pAllocationCallbacks->onFree != NULL) {
61134  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
61135  }
61136 }
61138 {
61139  if (pAllocationCallbacks != NULL) {
61140  return *pAllocationCallbacks;
61141  } else {
61142  drmp3_allocation_callbacks allocationCallbacks;
61143  allocationCallbacks.pUserData = NULL;
61144  allocationCallbacks.onMalloc = drmp3__malloc_default;
61145  allocationCallbacks.onRealloc = drmp3__realloc_default;
61146  allocationCallbacks.onFree = drmp3__free_default;
61147  return allocationCallbacks;
61148  }
61149 }
61150 static size_t drmp3__on_read(drmp3* pMP3, void* pBufferOut, size_t bytesToRead)
61151 {
61152  size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
61153  pMP3->streamCursor += bytesRead;
61154  return bytesRead;
61155 }
61156 static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin)
61157 {
61158  DRMP3_ASSERT(offset >= 0);
61159  if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
61160  return DRMP3_FALSE;
61161  }
61162  if (origin == drmp3_seek_origin_start) {
61163  pMP3->streamCursor = (drmp3_uint64)offset;
61164  } else {
61165  pMP3->streamCursor += offset;
61166  }
61167  return DRMP3_TRUE;
61168 }
61170 {
61171  if (offset <= 0x7FFFFFFF) {
61172  return drmp3__on_seek(pMP3, (int)offset, origin);
61173  }
61174  if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) {
61175  return DRMP3_FALSE;
61176  }
61177  offset -= 0x7FFFFFFF;
61178  while (offset > 0) {
61179  if (offset <= 0x7FFFFFFF) {
61180  if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) {
61181  return DRMP3_FALSE;
61182  }
61183  offset = 0;
61184  } else {
61185  if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) {
61186  return DRMP3_FALSE;
61187  }
61188  offset -= 0x7FFFFFFF;
61189  }
61190  }
61191  return DRMP3_TRUE;
61192 }
61194 {
61195  drmp3_uint32 pcmFramesRead = 0;
61196  DRMP3_ASSERT(pMP3 != NULL);
61197  DRMP3_ASSERT(pMP3->onRead != NULL);
61198  if (pMP3->atEnd) {
61199  return 0;
61200  }
61201  for (;;) {
61202  drmp3dec_frame_info info;
61203  if (pMP3->dataSize < DRMP3_MIN_DATA_CHUNK_SIZE) {
61204  size_t bytesRead;
61205  if (pMP3->pData != NULL) {
61206  memmove(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
61207  }
61208  pMP3->dataConsumed = 0;
61209  if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) {
61210  drmp3_uint8* pNewData;
61211  size_t newDataCap;
61212  newDataCap = DRMP3_DATA_CHUNK_SIZE;
61213  pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
61214  if (pNewData == NULL) {
61215  return 0;
61216  }
61217  pMP3->pData = pNewData;
61218  pMP3->dataCapacity = newDataCap;
61219  }
61220  bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
61221  if (bytesRead == 0) {
61222  if (pMP3->dataSize == 0) {
61223  pMP3->atEnd = DRMP3_TRUE;
61224  return 0;
61225  }
61226  }
61227  pMP3->dataSize += bytesRead;
61228  }
61229  if (pMP3->dataSize > INT_MAX) {
61230  pMP3->atEnd = DRMP3_TRUE;
61231  return 0;
61232  }
61233  DRMP3_ASSERT(pMP3->pData != NULL);
61234  DRMP3_ASSERT(pMP3->dataCapacity > 0);
61235  pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info);
61236  if (info.frame_bytes > 0) {
61237  pMP3->dataConsumed += (size_t)info.frame_bytes;
61238  pMP3->dataSize -= (size_t)info.frame_bytes;
61239  }
61240  if (pcmFramesRead > 0) {
61241  pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
61242  pMP3->pcmFramesConsumedInMP3Frame = 0;
61243  pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
61244  pMP3->mp3FrameChannels = info.channels;
61245  pMP3->mp3FrameSampleRate = info.hz;
61246  break;
61247  } else if (info.frame_bytes == 0) {
61248  size_t bytesRead;
61249  memmove(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
61250  pMP3->dataConsumed = 0;
61251  if (pMP3->dataCapacity == pMP3->dataSize) {
61252  drmp3_uint8* pNewData;
61253  size_t newDataCap;
61254  newDataCap = pMP3->dataCapacity + DRMP3_DATA_CHUNK_SIZE;
61255  pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
61256  if (pNewData == NULL) {
61257  return 0;
61258  }
61259  pMP3->pData = pNewData;
61260  pMP3->dataCapacity = newDataCap;
61261  }
61262  bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
61263  if (bytesRead == 0) {
61264  pMP3->atEnd = DRMP3_TRUE;
61265  return 0;
61266  }
61267  pMP3->dataSize += bytesRead;
61268  }
61269  };
61270  return pcmFramesRead;
61271 }
61273 {
61274  drmp3_uint32 pcmFramesRead = 0;
61275  drmp3dec_frame_info info;
61276  DRMP3_ASSERT(pMP3 != NULL);
61277  DRMP3_ASSERT(pMP3->memory.pData != NULL);
61278  if (pMP3->atEnd) {
61279  return 0;
61280  }
61281  pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->memory.pData + pMP3->memory.currentReadPos, (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos), pPCMFrames, &info);
61282  if (pcmFramesRead > 0) {
61283  pMP3->pcmFramesConsumedInMP3Frame = 0;
61284  pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
61285  pMP3->mp3FrameChannels = info.channels;
61286  pMP3->mp3FrameSampleRate = info.hz;
61287  }
61288  pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
61289  return pcmFramesRead;
61290 }
61292 {
61293  if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
61294  return drmp3_decode_next_frame_ex__memory(pMP3, pPCMFrames);
61295  } else {
61296  return drmp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames);
61297  }
61298 }
61300 {
61301  DRMP3_ASSERT(pMP3 != NULL);
61303 }
61304 #if 0
61305 static drmp3_uint32 drmp3_seek_next_frame(drmp3* pMP3)
61306 {
61307  drmp3_uint32 pcmFrameCount;
61308  DRMP3_ASSERT(pMP3 != NULL);
61309  pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, NULL);
61310  if (pcmFrameCount == 0) {
61311  return 0;
61312  }
61313  pMP3->currentPCMFrame += pcmFrameCount;
61314  pMP3->pcmFramesConsumedInMP3Frame = pcmFrameCount;
61315  pMP3->pcmFramesRemainingInMP3Frame = 0;
61316  return pcmFrameCount;
61317 }
61318 #endif
61319 static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
61320 {
61321  DRMP3_ASSERT(pMP3 != NULL);
61322  DRMP3_ASSERT(onRead != NULL);
61323  drmp3dec_init(&pMP3->decoder);
61324  pMP3->onRead = onRead;
61325  pMP3->onSeek = onSeek;
61326  pMP3->pUserData = pUserData;
61329  return DRMP3_FALSE;
61330  }
61331  if (!drmp3_decode_next_frame(pMP3)) {
61333  return DRMP3_FALSE;
61334  }
61335  pMP3->channels = pMP3->mp3FrameChannels;
61336  pMP3->sampleRate = pMP3->mp3FrameSampleRate;
61337  return DRMP3_TRUE;
61338 }
61339 DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
61340 {
61341  if (pMP3 == NULL || onRead == NULL) {
61342  return DRMP3_FALSE;
61343  }
61344  DRMP3_ZERO_OBJECT(pMP3);
61345  return drmp3_init_internal(pMP3, onRead, onSeek, pUserData, pAllocationCallbacks);
61346 }
61347 static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
61348 {
61349  drmp3* pMP3 = (drmp3*)pUserData;
61350  size_t bytesRemaining;
61351  DRMP3_ASSERT(pMP3 != NULL);
61353  bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos;
61354  if (bytesToRead > bytesRemaining) {
61355  bytesToRead = bytesRemaining;
61356  }
61357  if (bytesToRead > 0) {
61358  DRMP3_COPY_MEMORY(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead);
61359  pMP3->memory.currentReadPos += bytesToRead;
61360  }
61361  return bytesToRead;
61362 }
61363 static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin)
61364 {
61365  drmp3* pMP3 = (drmp3*)pUserData;
61366  DRMP3_ASSERT(pMP3 != NULL);
61367  if (origin == drmp3_seek_origin_current) {
61368  if (byteOffset > 0) {
61369  if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
61370  byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos);
61371  }
61372  } else {
61373  if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
61374  byteOffset = -(int)pMP3->memory.currentReadPos;
61375  }
61376  }
61377  pMP3->memory.currentReadPos += byteOffset;
61378  } else {
61379  if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) {
61380  pMP3->memory.currentReadPos = byteOffset;
61381  } else {
61382  pMP3->memory.currentReadPos = pMP3->memory.dataSize;
61383  }
61384  }
61385  return DRMP3_TRUE;
61386 }
61387 DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks)
61388 {
61389  if (pMP3 == NULL) {
61390  return DRMP3_FALSE;
61391  }
61392  DRMP3_ZERO_OBJECT(pMP3);
61393  if (pData == NULL || dataSize == 0) {
61394  return DRMP3_FALSE;
61395  }
61396  pMP3->memory.pData = (const drmp3_uint8*)pData;
61397  pMP3->memory.dataSize = dataSize;
61398  pMP3->memory.currentReadPos = 0;
61399  return drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, pMP3, pAllocationCallbacks);
61400 }
61401 #ifndef DR_MP3_NO_STDIO
61402 #include <stdio.h>
61403 #include <wchar.h>
61404 #include <errno.h>
61406 {
61407  switch (e)
61408  {
61409  case 0: return DRMP3_SUCCESS;
61410  #ifdef EPERM
61411  case EPERM: return DRMP3_INVALID_OPERATION;
61412  #endif
61413  #ifdef ENOENT
61414  case ENOENT: return DRMP3_DOES_NOT_EXIST;
61415  #endif
61416  #ifdef ESRCH
61417  case ESRCH: return DRMP3_DOES_NOT_EXIST;
61418  #endif
61419  #ifdef EINTR
61420  case EINTR: return DRMP3_INTERRUPT;
61421  #endif
61422  #ifdef EIO
61423  case EIO: return DRMP3_IO_ERROR;
61424  #endif
61425  #ifdef ENXIO
61426  case ENXIO: return DRMP3_DOES_NOT_EXIST;
61427  #endif
61428  #ifdef E2BIG
61429  case E2BIG: return DRMP3_INVALID_ARGS;
61430  #endif
61431  #ifdef ENOEXEC
61432  case ENOEXEC: return DRMP3_INVALID_FILE;
61433  #endif
61434  #ifdef EBADF
61435  case EBADF: return DRMP3_INVALID_FILE;
61436  #endif
61437  #ifdef ECHILD
61438  case ECHILD: return DRMP3_ERROR;
61439  #endif
61440  #ifdef EAGAIN
61441  case EAGAIN: return DRMP3_UNAVAILABLE;
61442  #endif
61443  #ifdef ENOMEM
61444  case ENOMEM: return DRMP3_OUT_OF_MEMORY;
61445  #endif
61446  #ifdef EACCES
61447  case EACCES: return DRMP3_ACCESS_DENIED;
61448  #endif
61449  #ifdef EFAULT
61450  case EFAULT: return DRMP3_BAD_ADDRESS;
61451  #endif
61452  #ifdef ENOTBLK
61453  case ENOTBLK: return DRMP3_ERROR;
61454  #endif
61455  #ifdef EBUSY
61456  case EBUSY: return DRMP3_BUSY;
61457  #endif
61458  #ifdef EEXIST
61459  case EEXIST: return DRMP3_ALREADY_EXISTS;
61460  #endif
61461  #ifdef EXDEV
61462  case EXDEV: return DRMP3_ERROR;
61463  #endif
61464  #ifdef ENODEV
61465  case ENODEV: return DRMP3_DOES_NOT_EXIST;
61466  #endif
61467  #ifdef ENOTDIR
61468  case ENOTDIR: return DRMP3_NOT_DIRECTORY;
61469  #endif
61470  #ifdef EISDIR
61471  case EISDIR: return DRMP3_IS_DIRECTORY;
61472  #endif
61473  #ifdef EINVAL
61474  case EINVAL: return DRMP3_INVALID_ARGS;
61475  #endif
61476  #ifdef ENFILE
61477  case ENFILE: return DRMP3_TOO_MANY_OPEN_FILES;
61478  #endif
61479  #ifdef EMFILE
61480  case EMFILE: return DRMP3_TOO_MANY_OPEN_FILES;
61481  #endif
61482  #ifdef ENOTTY
61483  case ENOTTY: return DRMP3_INVALID_OPERATION;
61484  #endif
61485  #ifdef ETXTBSY
61486  case ETXTBSY: return DRMP3_BUSY;
61487  #endif
61488  #ifdef EFBIG
61489  case EFBIG: return DRMP3_TOO_BIG;
61490  #endif
61491  #ifdef ENOSPC
61492  case ENOSPC: return DRMP3_NO_SPACE;
61493  #endif
61494  #ifdef ESPIPE
61495  case ESPIPE: return DRMP3_BAD_SEEK;
61496  #endif
61497  #ifdef EROFS
61498  case EROFS: return DRMP3_ACCESS_DENIED;
61499  #endif
61500  #ifdef EMLINK
61501  case EMLINK: return DRMP3_TOO_MANY_LINKS;
61502  #endif
61503  #ifdef EPIPE
61504  case EPIPE: return DRMP3_BAD_PIPE;
61505  #endif
61506  #ifdef EDOM
61507  case EDOM: return DRMP3_OUT_OF_RANGE;
61508  #endif
61509  #ifdef ERANGE
61510  case ERANGE: return DRMP3_OUT_OF_RANGE;
61511  #endif
61512  #ifdef EDEADLK
61513  case EDEADLK: return DRMP3_DEADLOCK;
61514  #endif
61515  #ifdef ENAMETOOLONG
61516  case ENAMETOOLONG: return DRMP3_PATH_TOO_LONG;
61517  #endif
61518  #ifdef ENOLCK
61519  case ENOLCK: return DRMP3_ERROR;
61520  #endif
61521  #ifdef ENOSYS
61522  case ENOSYS: return DRMP3_NOT_IMPLEMENTED;
61523  #endif
61524  #ifdef ENOTEMPTY
61525  case ENOTEMPTY: return DRMP3_DIRECTORY_NOT_EMPTY;
61526  #endif
61527  #ifdef ELOOP
61528  case ELOOP: return DRMP3_TOO_MANY_LINKS;
61529  #endif
61530  #ifdef ENOMSG
61531  case ENOMSG: return DRMP3_NO_MESSAGE;
61532  #endif
61533  #ifdef EIDRM
61534  case EIDRM: return DRMP3_ERROR;
61535  #endif
61536  #ifdef ECHRNG
61537  case ECHRNG: return DRMP3_ERROR;
61538  #endif
61539  #ifdef EL2NSYNC
61540  case EL2NSYNC: return DRMP3_ERROR;
61541  #endif
61542  #ifdef EL3HLT
61543  case EL3HLT: return DRMP3_ERROR;
61544  #endif
61545  #ifdef EL3RST
61546  case EL3RST: return DRMP3_ERROR;
61547  #endif
61548  #ifdef ELNRNG
61549  case ELNRNG: return DRMP3_OUT_OF_RANGE;
61550  #endif
61551  #ifdef EUNATCH
61552  case EUNATCH: return DRMP3_ERROR;
61553  #endif
61554  #ifdef ENOCSI
61555  case ENOCSI: return DRMP3_ERROR;
61556  #endif
61557  #ifdef EL2HLT
61558  case EL2HLT: return DRMP3_ERROR;
61559  #endif
61560  #ifdef EBADE
61561  case EBADE: return DRMP3_ERROR;
61562  #endif
61563  #ifdef EBADR
61564  case EBADR: return DRMP3_ERROR;
61565  #endif
61566  #ifdef EXFULL
61567  case EXFULL: return DRMP3_ERROR;
61568  #endif
61569  #ifdef ENOANO
61570  case ENOANO: return DRMP3_ERROR;
61571  #endif
61572  #ifdef EBADRQC
61573  case EBADRQC: return DRMP3_ERROR;
61574  #endif
61575  #ifdef EBADSLT
61576  case EBADSLT: return DRMP3_ERROR;
61577  #endif
61578  #ifdef EBFONT
61579  case EBFONT: return DRMP3_INVALID_FILE;
61580  #endif
61581  #ifdef ENOSTR
61582  case ENOSTR: return DRMP3_ERROR;
61583  #endif
61584  #ifdef ENODATA
61585  case ENODATA: return DRMP3_NO_DATA_AVAILABLE;
61586  #endif
61587  #ifdef ETIME
61588  case ETIME: return DRMP3_TIMEOUT;
61589  #endif
61590  #ifdef ENOSR
61591  case ENOSR: return DRMP3_NO_DATA_AVAILABLE;
61592  #endif
61593  #ifdef ENONET
61594  case ENONET: return DRMP3_NO_NETWORK;
61595  #endif
61596  #ifdef ENOPKG
61597  case ENOPKG: return DRMP3_ERROR;
61598  #endif
61599  #ifdef EREMOTE
61600  case EREMOTE: return DRMP3_ERROR;
61601  #endif
61602  #ifdef ENOLINK
61603  case ENOLINK: return DRMP3_ERROR;
61604  #endif
61605  #ifdef EADV
61606  case EADV: return DRMP3_ERROR;
61607  #endif
61608  #ifdef ESRMNT
61609  case ESRMNT: return DRMP3_ERROR;
61610  #endif
61611  #ifdef ECOMM
61612  case ECOMM: return DRMP3_ERROR;
61613  #endif
61614  #ifdef EPROTO
61615  case EPROTO: return DRMP3_ERROR;
61616  #endif
61617  #ifdef EMULTIHOP
61618  case EMULTIHOP: return DRMP3_ERROR;
61619  #endif
61620  #ifdef EDOTDOT
61621  case EDOTDOT: return DRMP3_ERROR;
61622  #endif
61623  #ifdef EBADMSG
61624  case EBADMSG: return DRMP3_BAD_MESSAGE;
61625  #endif
61626  #ifdef EOVERFLOW
61627  case EOVERFLOW: return DRMP3_TOO_BIG;
61628  #endif
61629  #ifdef ENOTUNIQ
61630  case ENOTUNIQ: return DRMP3_NOT_UNIQUE;
61631  #endif
61632  #ifdef EBADFD
61633  case EBADFD: return DRMP3_ERROR;
61634  #endif
61635  #ifdef EREMCHG
61636  case EREMCHG: return DRMP3_ERROR;
61637  #endif
61638  #ifdef ELIBACC
61639  case ELIBACC: return DRMP3_ACCESS_DENIED;
61640  #endif
61641  #ifdef ELIBBAD
61642  case ELIBBAD: return DRMP3_INVALID_FILE;
61643  #endif
61644  #ifdef ELIBSCN
61645  case ELIBSCN: return DRMP3_INVALID_FILE;
61646  #endif
61647  #ifdef ELIBMAX
61648  case ELIBMAX: return DRMP3_ERROR;
61649  #endif
61650  #ifdef ELIBEXEC
61651  case ELIBEXEC: return DRMP3_ERROR;
61652  #endif
61653  #ifdef EILSEQ
61654  case EILSEQ: return DRMP3_INVALID_DATA;
61655  #endif
61656  #ifdef ERESTART
61657  case ERESTART: return DRMP3_ERROR;
61658  #endif
61659  #ifdef ESTRPIPE
61660  case ESTRPIPE: return DRMP3_ERROR;
61661  #endif
61662  #ifdef EUSERS
61663  case EUSERS: return DRMP3_ERROR;
61664  #endif
61665  #ifdef ENOTSOCK
61666  case ENOTSOCK: return DRMP3_NOT_SOCKET;
61667  #endif
61668  #ifdef EDESTADDRREQ
61669  case EDESTADDRREQ: return DRMP3_NO_ADDRESS;
61670  #endif
61671  #ifdef EMSGSIZE
61672  case EMSGSIZE: return DRMP3_TOO_BIG;
61673  #endif
61674  #ifdef EPROTOTYPE
61675  case EPROTOTYPE: return DRMP3_BAD_PROTOCOL;
61676  #endif
61677  #ifdef ENOPROTOOPT
61678  case ENOPROTOOPT: return DRMP3_PROTOCOL_UNAVAILABLE;
61679  #endif
61680  #ifdef EPROTONOSUPPORT
61681  case EPROTONOSUPPORT: return DRMP3_PROTOCOL_NOT_SUPPORTED;
61682  #endif
61683  #ifdef ESOCKTNOSUPPORT
61684  case ESOCKTNOSUPPORT: return DRMP3_SOCKET_NOT_SUPPORTED;
61685  #endif
61686  #ifdef EOPNOTSUPP
61687  case EOPNOTSUPP: return DRMP3_INVALID_OPERATION;
61688  #endif
61689  #ifdef EPFNOSUPPORT
61690  case EPFNOSUPPORT: return DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED;
61691  #endif
61692  #ifdef EAFNOSUPPORT
61693  case EAFNOSUPPORT: return DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED;
61694  #endif
61695  #ifdef EADDRINUSE
61696  case EADDRINUSE: return DRMP3_ALREADY_IN_USE;
61697  #endif
61698  #ifdef EADDRNOTAVAIL
61699  case EADDRNOTAVAIL: return DRMP3_ERROR;
61700  #endif
61701  #ifdef ENETDOWN
61702  case ENETDOWN: return DRMP3_NO_NETWORK;
61703  #endif
61704  #ifdef ENETUNREACH
61705  case ENETUNREACH: return DRMP3_NO_NETWORK;
61706  #endif
61707  #ifdef ENETRESET
61708  case ENETRESET: return DRMP3_NO_NETWORK;
61709  #endif
61710  #ifdef ECONNABORTED
61711  case ECONNABORTED: return DRMP3_NO_NETWORK;
61712  #endif
61713  #ifdef ECONNRESET
61714  case ECONNRESET: return DRMP3_CONNECTION_RESET;
61715  #endif
61716  #ifdef ENOBUFS
61717  case ENOBUFS: return DRMP3_NO_SPACE;
61718  #endif
61719  #ifdef EISCONN
61720  case EISCONN: return DRMP3_ALREADY_CONNECTED;
61721  #endif
61722  #ifdef ENOTCONN
61723  case ENOTCONN: return DRMP3_NOT_CONNECTED;
61724  #endif
61725  #ifdef ESHUTDOWN
61726  case ESHUTDOWN: return DRMP3_ERROR;
61727  #endif
61728  #ifdef ETOOMANYREFS
61729  case ETOOMANYREFS: return DRMP3_ERROR;
61730  #endif
61731  #ifdef ETIMEDOUT
61732  case ETIMEDOUT: return DRMP3_TIMEOUT;
61733  #endif
61734  #ifdef ECONNREFUSED
61735  case ECONNREFUSED: return DRMP3_CONNECTION_REFUSED;
61736  #endif
61737  #ifdef EHOSTDOWN
61738  case EHOSTDOWN: return DRMP3_NO_HOST;
61739  #endif
61740  #ifdef EHOSTUNREACH
61741  case EHOSTUNREACH: return DRMP3_NO_HOST;
61742  #endif
61743  #ifdef EALREADY
61744  case EALREADY: return DRMP3_IN_PROGRESS;
61745  #endif
61746  #ifdef EINPROGRESS
61747  case EINPROGRESS: return DRMP3_IN_PROGRESS;
61748  #endif
61749  #ifdef ESTALE
61750  case ESTALE: return DRMP3_INVALID_FILE;
61751  #endif
61752  #ifdef EUCLEAN
61753  case EUCLEAN: return DRMP3_ERROR;
61754  #endif
61755  #ifdef ENOTNAM
61756  case ENOTNAM: return DRMP3_ERROR;
61757  #endif
61758  #ifdef ENAVAIL
61759  case ENAVAIL: return DRMP3_ERROR;
61760  #endif
61761  #ifdef EISNAM
61762  case EISNAM: return DRMP3_ERROR;
61763  #endif
61764  #ifdef EREMOTEIO
61765  case EREMOTEIO: return DRMP3_IO_ERROR;
61766  #endif
61767  #ifdef EDQUOT
61768  case EDQUOT: return DRMP3_NO_SPACE;
61769  #endif
61770  #ifdef ENOMEDIUM
61771  case ENOMEDIUM: return DRMP3_DOES_NOT_EXIST;
61772  #endif
61773  #ifdef EMEDIUMTYPE
61774  case EMEDIUMTYPE: return DRMP3_ERROR;
61775  #endif
61776  #ifdef ECANCELED
61777  case ECANCELED: return DRMP3_CANCELLED;
61778  #endif
61779  #ifdef ENOKEY
61780  case ENOKEY: return DRMP3_ERROR;
61781  #endif
61782  #ifdef EKEYEXPIRED
61783  case EKEYEXPIRED: return DRMP3_ERROR;
61784  #endif
61785  #ifdef EKEYREVOKED
61786  case EKEYREVOKED: return DRMP3_ERROR;
61787  #endif
61788  #ifdef EKEYREJECTED
61789  case EKEYREJECTED: return DRMP3_ERROR;
61790  #endif
61791  #ifdef EOWNERDEAD
61792  case EOWNERDEAD: return DRMP3_ERROR;
61793  #endif
61794  #ifdef ENOTRECOVERABLE
61795  case ENOTRECOVERABLE: return DRMP3_ERROR;
61796  #endif
61797  #ifdef ERFKILL
61798  case ERFKILL: return DRMP3_ERROR;
61799  #endif
61800  #ifdef EHWPOISON
61801  case EHWPOISON: return DRMP3_ERROR;
61802  #endif
61803  default: return DRMP3_ERROR;
61804  }
61805 }
61806 static drmp3_result drmp3_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
61807 {
61808 #if defined(_MSC_VER) && _MSC_VER >= 1400
61809  errno_t err;
61810 #endif
61811  if (ppFile != NULL) {
61812  *ppFile = NULL;
61813  }
61814  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
61815  return DRMP3_INVALID_ARGS;
61816  }
61817 #if defined(_MSC_VER) && _MSC_VER >= 1400
61818  err = fopen_s(ppFile, pFilePath, pOpenMode);
61819  if (err != 0) {
61820  return drmp3_result_from_errno(err);
61821  }
61822 #else
61823 #if defined(_WIN32) || defined(__APPLE__)
61824  *ppFile = fopen(pFilePath, pOpenMode);
61825 #else
61826  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
61827  *ppFile = fopen64(pFilePath, pOpenMode);
61828  #else
61829  *ppFile = fopen(pFilePath, pOpenMode);
61830  #endif
61831 #endif
61832  if (*ppFile == NULL) {
61834  if (result == DRMP3_SUCCESS) {
61835  result = DRMP3_ERROR;
61836  }
61837  return result;
61838  }
61839 #endif
61840  return DRMP3_SUCCESS;
61841 }
61842 #if defined(_WIN32)
61843  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
61844  #define DRMP3_HAS_WFOPEN
61845  #endif
61846 #endif
61847 static drmp3_result drmp3_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drmp3_allocation_callbacks* pAllocationCallbacks)
61848 {
61849  if (ppFile != NULL) {
61850  *ppFile = NULL;
61851  }
61852  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
61853  return DRMP3_INVALID_ARGS;
61854  }
61855 #if defined(DRMP3_HAS_WFOPEN)
61856  {
61857  #if defined(_MSC_VER) && _MSC_VER >= 1400
61858  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
61859  if (err != 0) {
61860  return drmp3_result_from_errno(err);
61861  }
61862  #else
61863  *ppFile = _wfopen(pFilePath, pOpenMode);
61864  if (*ppFile == NULL) {
61866  }
61867  #endif
61868  (void)pAllocationCallbacks;
61869  }
61870 #else
61871  {
61872  mbstate_t mbs;
61873  size_t lenMB;
61874  const wchar_t* pFilePathTemp = pFilePath;
61875  char* pFilePathMB = NULL;
61876  char pOpenModeMB[32] = {0};
61877  DRMP3_ZERO_OBJECT(&mbs);
61878  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
61879  if (lenMB == (size_t)-1) {
61881  }
61882  pFilePathMB = (char*)drmp3__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
61883  if (pFilePathMB == NULL) {
61884  return DRMP3_OUT_OF_MEMORY;
61885  }
61886  pFilePathTemp = pFilePath;
61887  DRMP3_ZERO_OBJECT(&mbs);
61888  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
61889  {
61890  size_t i = 0;
61891  for (;;) {
61892  if (pOpenMode[i] == 0) {
61893  pOpenModeMB[i] = '\0';
61894  break;
61895  }
61896  pOpenModeMB[i] = (char)pOpenMode[i];
61897  i += 1;
61898  }
61899  }
61900  *ppFile = fopen(pFilePathMB, pOpenModeMB);
61901  drmp3__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
61902  }
61903  if (*ppFile == NULL) {
61904  return DRMP3_ERROR;
61905  }
61906 #endif
61907  return DRMP3_SUCCESS;
61908 }
61909 static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
61910 {
61911  return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
61912 }
61913 static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin)
61914 {
61915  return fseek((FILE*)pUserData, offset, (origin == drmp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
61916 }
61917 DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
61918 {
61919  drmp3_bool32 result;
61920  FILE* pFile;
61921  if (drmp3_fopen(&pFile, pFilePath, "rb") != DRMP3_SUCCESS) {
61922  return DRMP3_FALSE;
61923  }
61924  result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
61925  if (result != DRMP3_TRUE) {
61926  fclose(pFile);
61927  return result;
61928  }
61929  return DRMP3_TRUE;
61930 }
61931 DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
61932 {
61933  drmp3_bool32 result;
61934  FILE* pFile;
61935  if (drmp3_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != DRMP3_SUCCESS) {
61936  return DRMP3_FALSE;
61937  }
61938  result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
61939  if (result != DRMP3_TRUE) {
61940  fclose(pFile);
61941  return result;
61942  }
61943  return DRMP3_TRUE;
61944 }
61945 #endif
61947 {
61948  if (pMP3 == NULL) {
61949  return;
61950  }
61951 #ifndef DR_MP3_NO_STDIO
61952  if (pMP3->onRead == drmp3__on_read_stdio) {
61953  FILE* pFile = (FILE*)pMP3->pUserData;
61954  if (pFile != NULL) {
61955  fclose(pFile);
61956  pMP3->pUserData = NULL;
61957  }
61958  }
61959 #endif
61961 }
61962 #if defined(DR_MP3_FLOAT_OUTPUT)
61963 static void drmp3_f32_to_s16(drmp3_int16* dst, const float* src, drmp3_uint64 sampleCount)
61964 {
61965  drmp3_uint64 i;
61966  drmp3_uint64 i4;
61967  drmp3_uint64 sampleCount4;
61968  i = 0;
61969  sampleCount4 = sampleCount >> 2;
61970  for (i4 = 0; i4 < sampleCount4; i4 += 1) {
61971  float x0 = src[i+0];
61972  float x1 = src[i+1];
61973  float x2 = src[i+2];
61974  float x3 = src[i+3];
61975  x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
61976  x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
61977  x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
61978  x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
61979  x0 = x0 * 32767.0f;
61980  x1 = x1 * 32767.0f;
61981  x2 = x2 * 32767.0f;
61982  x3 = x3 * 32767.0f;
61983  dst[i+0] = (drmp3_int16)x0;
61984  dst[i+1] = (drmp3_int16)x1;
61985  dst[i+2] = (drmp3_int16)x2;
61986  dst[i+3] = (drmp3_int16)x3;
61987  i += 4;
61988  }
61989  for (; i < sampleCount; i += 1) {
61990  float x = src[i];
61991  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
61992  x = x * 32767.0f;
61993  dst[i] = (drmp3_int16)x;
61994  }
61995 }
61996 #endif
61997 #if !defined(DR_MP3_FLOAT_OUTPUT)
61998 static void drmp3_s16_to_f32(float* dst, const drmp3_int16* src, drmp3_uint64 sampleCount)
61999 {
62000  drmp3_uint64 i;
62001  for (i = 0; i < sampleCount; i += 1) {
62002  float x = (float)src[i];
62003  x = x * 0.000030517578125f;
62004  dst[i] = x;
62005  }
62006 }
62007 #endif
62008 static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3* pMP3, drmp3_uint64 framesToRead, void* pBufferOut)
62009 {
62010  drmp3_uint64 totalFramesRead = 0;
62011  DRMP3_ASSERT(pMP3 != NULL);
62012  DRMP3_ASSERT(pMP3->onRead != NULL);
62013  while (framesToRead > 0) {
62014  drmp3_uint32 framesToConsume = (drmp3_uint32)DRMP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
62015  if (pBufferOut != NULL) {
62016  #if defined(DR_MP3_FLOAT_OUTPUT)
62017  float* pFramesOutF32 = (float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
62018  float* pFramesInF32 = (float*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
62019  DRMP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
62020  #else
62021  drmp3_int16* pFramesOutS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalFramesRead * pMP3->channels);
62022  drmp3_int16* pFramesInS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(drmp3_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
62023  DRMP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(drmp3_int16) * framesToConsume * pMP3->channels);
62024  #endif
62025  }
62026  pMP3->currentPCMFrame += framesToConsume;
62027  pMP3->pcmFramesConsumedInMP3Frame += framesToConsume;
62028  pMP3->pcmFramesRemainingInMP3Frame -= framesToConsume;
62029  totalFramesRead += framesToConsume;
62030  framesToRead -= framesToConsume;
62031  if (framesToRead == 0) {
62032  break;
62033  }
62035  if (drmp3_decode_next_frame(pMP3) == 0) {
62036  break;
62037  }
62038  }
62039  return totalFramesRead;
62040 }
62041 DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut)
62042 {
62043  if (pMP3 == NULL || pMP3->onRead == NULL) {
62044  return 0;
62045  }
62046 #if defined(DR_MP3_FLOAT_OUTPUT)
62047  return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
62048 #else
62049  {
62050  drmp3_int16 pTempS16[8192];
62051  drmp3_uint64 totalPCMFramesRead = 0;
62052  while (totalPCMFramesRead < framesToRead) {
62053  drmp3_uint64 framesJustRead;
62054  drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
62055  drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempS16) / pMP3->channels;
62056  if (framesToReadNow > framesRemaining) {
62057  framesToReadNow = framesRemaining;
62058  }
62059  framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempS16);
62060  if (framesJustRead == 0) {
62061  break;
62062  }
62063  drmp3_s16_to_f32((float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalPCMFramesRead * pMP3->channels), pTempS16, framesJustRead * pMP3->channels);
62064  totalPCMFramesRead += framesJustRead;
62065  }
62066  return totalPCMFramesRead;
62067  }
62068 #endif
62069 }
62071 {
62072  if (pMP3 == NULL || pMP3->onRead == NULL) {
62073  return 0;
62074  }
62075 #if !defined(DR_MP3_FLOAT_OUTPUT)
62076  return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
62077 #else
62078  {
62079  float pTempF32[4096];
62080  drmp3_uint64 totalPCMFramesRead = 0;
62081  while (totalPCMFramesRead < framesToRead) {
62082  drmp3_uint64 framesJustRead;
62083  drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
62084  drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempF32) / pMP3->channels;
62085  if (framesToReadNow > framesRemaining) {
62086  framesToReadNow = framesRemaining;
62087  }
62088  framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempF32);
62089  if (framesJustRead == 0) {
62090  break;
62091  }
62092  drmp3_f32_to_s16((drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalPCMFramesRead * pMP3->channels), pTempF32, framesJustRead * pMP3->channels);
62093  totalPCMFramesRead += framesJustRead;
62094  }
62095  return totalPCMFramesRead;
62096  }
62097 #endif
62098 }
62099 static void drmp3_reset(drmp3* pMP3)
62100 {
62101  DRMP3_ASSERT(pMP3 != NULL);
62102  pMP3->pcmFramesConsumedInMP3Frame = 0;
62103  pMP3->pcmFramesRemainingInMP3Frame = 0;
62104  pMP3->currentPCMFrame = 0;
62105  pMP3->dataSize = 0;
62106  pMP3->atEnd = DRMP3_FALSE;
62107  drmp3dec_init(&pMP3->decoder);
62108 }
62110 {
62111  DRMP3_ASSERT(pMP3 != NULL);
62112  DRMP3_ASSERT(pMP3->onSeek != NULL);
62113  if (!drmp3__on_seek(pMP3, 0, drmp3_seek_origin_start)) {
62114  return DRMP3_FALSE;
62115  }
62116  drmp3_reset(pMP3);
62117  return DRMP3_TRUE;
62118 }
62120 {
62121  drmp3_uint64 framesRead;
62122 #if defined(DR_MP3_FLOAT_OUTPUT)
62123  framesRead = drmp3_read_pcm_frames_f32(pMP3, frameOffset, NULL);
62124 #else
62125  framesRead = drmp3_read_pcm_frames_s16(pMP3, frameOffset, NULL);
62126 #endif
62127  if (framesRead != frameOffset) {
62128  return DRMP3_FALSE;
62129  }
62130  return DRMP3_TRUE;
62131 }
62133 {
62134  DRMP3_ASSERT(pMP3 != NULL);
62135  if (frameIndex == pMP3->currentPCMFrame) {
62136  return DRMP3_TRUE;
62137  }
62138  if (frameIndex < pMP3->currentPCMFrame) {
62139  if (!drmp3_seek_to_start_of_stream(pMP3)) {
62140  return DRMP3_FALSE;
62141  }
62142  }
62143  DRMP3_ASSERT(frameIndex >= pMP3->currentPCMFrame);
62144  return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, (frameIndex - pMP3->currentPCMFrame));
62145 }
62146 static drmp3_bool32 drmp3_find_closest_seek_point(drmp3* pMP3, drmp3_uint64 frameIndex, drmp3_uint32* pSeekPointIndex)
62147 {
62148  drmp3_uint32 iSeekPoint;
62149  DRMP3_ASSERT(pSeekPointIndex != NULL);
62150  *pSeekPointIndex = 0;
62151  if (frameIndex < pMP3->pSeekPoints[0].pcmFrameIndex) {
62152  return DRMP3_FALSE;
62153  }
62154  for (iSeekPoint = 0; iSeekPoint < pMP3->seekPointCount; ++iSeekPoint) {
62155  if (pMP3->pSeekPoints[iSeekPoint].pcmFrameIndex > frameIndex) {
62156  break;
62157  }
62158  *pSeekPointIndex = iSeekPoint;
62159  }
62160  return DRMP3_TRUE;
62161 }
62163 {
62164  drmp3_seek_point seekPoint;
62165  drmp3_uint32 priorSeekPointIndex;
62166  drmp3_uint16 iMP3Frame;
62167  drmp3_uint64 leftoverFrames;
62168  DRMP3_ASSERT(pMP3 != NULL);
62169  DRMP3_ASSERT(pMP3->pSeekPoints != NULL);
62170  DRMP3_ASSERT(pMP3->seekPointCount > 0);
62171  if (drmp3_find_closest_seek_point(pMP3, frameIndex, &priorSeekPointIndex)) {
62172  seekPoint = pMP3->pSeekPoints[priorSeekPointIndex];
62173  } else {
62174  seekPoint.seekPosInBytes = 0;
62175  seekPoint.pcmFrameIndex = 0;
62176  seekPoint.mp3FramesToDiscard = 0;
62177  seekPoint.pcmFramesToDiscard = 0;
62178  }
62179  if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, drmp3_seek_origin_start)) {
62180  return DRMP3_FALSE;
62181  }
62182  drmp3_reset(pMP3);
62183  for (iMP3Frame = 0; iMP3Frame < seekPoint.mp3FramesToDiscard; ++iMP3Frame) {
62184  drmp3_uint32 pcmFramesRead;
62185  drmp3d_sample_t* pPCMFrames;
62186  pPCMFrames = NULL;
62187  if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) {
62188  pPCMFrames = (drmp3d_sample_t*)pMP3->pcmFrames;
62189  }
62190  pcmFramesRead = drmp3_decode_next_frame_ex(pMP3, pPCMFrames);
62191  if (pcmFramesRead == 0) {
62192  return DRMP3_FALSE;
62193  }
62194  }
62195  pMP3->currentPCMFrame = seekPoint.pcmFrameIndex - seekPoint.pcmFramesToDiscard;
62196  leftoverFrames = frameIndex - pMP3->currentPCMFrame;
62197  return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, leftoverFrames);
62198 }
62200 {
62201  if (pMP3 == NULL || pMP3->onSeek == NULL) {
62202  return DRMP3_FALSE;
62203  }
62204  if (frameIndex == 0) {
62205  return drmp3_seek_to_start_of_stream(pMP3);
62206  }
62207  if (pMP3->pSeekPoints != NULL && pMP3->seekPointCount > 0) {
62208  return drmp3_seek_to_pcm_frame__seek_table(pMP3, frameIndex);
62209  } else {
62210  return drmp3_seek_to_pcm_frame__brute_force(pMP3, frameIndex);
62211  }
62212 }
62214 {
62215  drmp3_uint64 currentPCMFrame;
62216  drmp3_uint64 totalPCMFrameCount;
62217  drmp3_uint64 totalMP3FrameCount;
62218  if (pMP3 == NULL) {
62219  return DRMP3_FALSE;
62220  }
62221  if (pMP3->onSeek == NULL) {
62222  return DRMP3_FALSE;
62223  }
62224  currentPCMFrame = pMP3->currentPCMFrame;
62225  if (!drmp3_seek_to_start_of_stream(pMP3)) {
62226  return DRMP3_FALSE;
62227  }
62228  totalPCMFrameCount = 0;
62229  totalMP3FrameCount = 0;
62230  for (;;) {
62231  drmp3_uint32 pcmFramesInCurrentMP3Frame;
62232  pcmFramesInCurrentMP3Frame = drmp3_decode_next_frame_ex(pMP3, NULL);
62233  if (pcmFramesInCurrentMP3Frame == 0) {
62234  break;
62235  }
62236  totalPCMFrameCount += pcmFramesInCurrentMP3Frame;
62237  totalMP3FrameCount += 1;
62238  }
62239  if (!drmp3_seek_to_start_of_stream(pMP3)) {
62240  return DRMP3_FALSE;
62241  }
62242  if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
62243  return DRMP3_FALSE;
62244  }
62245  if (pMP3FrameCount != NULL) {
62246  *pMP3FrameCount = totalMP3FrameCount;
62247  }
62248  if (pPCMFrameCount != NULL) {
62249  *pPCMFrameCount = totalPCMFrameCount;
62250  }
62251  return DRMP3_TRUE;
62252 }
62254 {
62255  drmp3_uint64 totalPCMFrameCount;
62256  if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) {
62257  return 0;
62258  }
62259  return totalPCMFrameCount;
62260 }
62262 {
62263  drmp3_uint64 totalMP3FrameCount;
62264  if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, NULL)) {
62265  return 0;
62266  }
62267  return totalMP3FrameCount;
62268 }
62269 static void drmp3__accumulate_running_pcm_frame_count(drmp3* pMP3, drmp3_uint32 pcmFrameCountIn, drmp3_uint64* pRunningPCMFrameCount, float* pRunningPCMFrameCountFractionalPart)
62270 {
62271  float srcRatio;
62272  float pcmFrameCountOutF;
62273  drmp3_uint32 pcmFrameCountOut;
62274  srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate;
62275  DRMP3_ASSERT(srcRatio > 0);
62276  pcmFrameCountOutF = *pRunningPCMFrameCountFractionalPart + (pcmFrameCountIn / srcRatio);
62277  pcmFrameCountOut = (drmp3_uint32)pcmFrameCountOutF;
62278  *pRunningPCMFrameCountFractionalPart = pcmFrameCountOutF - pcmFrameCountOut;
62279  *pRunningPCMFrameCount += pcmFrameCountOut;
62280 }
62281 typedef struct
62282 {
62287 {
62288  drmp3_uint32 seekPointCount;
62289  drmp3_uint64 currentPCMFrame;
62290  drmp3_uint64 totalMP3FrameCount;
62291  drmp3_uint64 totalPCMFrameCount;
62292  if (pMP3 == NULL || pSeekPointCount == NULL || pSeekPoints == NULL) {
62293  return DRMP3_FALSE;
62294  }
62295  seekPointCount = *pSeekPointCount;
62296  if (seekPointCount == 0) {
62297  return DRMP3_FALSE;
62298  }
62299  currentPCMFrame = pMP3->currentPCMFrame;
62300  if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, &totalPCMFrameCount)) {
62301  return DRMP3_FALSE;
62302  }
62303  if (totalMP3FrameCount < DRMP3_SEEK_LEADING_MP3_FRAMES+1) {
62304  seekPointCount = 1;
62305  pSeekPoints[0].seekPosInBytes = 0;
62306  pSeekPoints[0].pcmFrameIndex = 0;
62307  pSeekPoints[0].mp3FramesToDiscard = 0;
62308  pSeekPoints[0].pcmFramesToDiscard = 0;
62309  } else {
62310  drmp3_uint64 pcmFramesBetweenSeekPoints;
62311  drmp3__seeking_mp3_frame_info mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES+1];
62312  drmp3_uint64 runningPCMFrameCount = 0;
62313  float runningPCMFrameCountFractionalPart = 0;
62314  drmp3_uint64 nextTargetPCMFrame;
62315  drmp3_uint32 iMP3Frame;
62316  drmp3_uint32 iSeekPoint;
62317  if (seekPointCount > totalMP3FrameCount-1) {
62318  seekPointCount = (drmp3_uint32)totalMP3FrameCount-1;
62319  }
62320  pcmFramesBetweenSeekPoints = totalPCMFrameCount / (seekPointCount+1);
62321  if (!drmp3_seek_to_start_of_stream(pMP3)) {
62322  return DRMP3_FALSE;
62323  }
62324  for (iMP3Frame = 0; iMP3Frame < DRMP3_SEEK_LEADING_MP3_FRAMES+1; ++iMP3Frame) {
62325  drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
62326  DRMP3_ASSERT(pMP3->streamCursor >= pMP3->dataSize);
62327  mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize;
62328  mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount;
62329  pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
62330  if (pcmFramesInCurrentMP3FrameIn == 0) {
62331  return DRMP3_FALSE;
62332  }
62333  drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
62334  }
62335  nextTargetPCMFrame = 0;
62336  for (iSeekPoint = 0; iSeekPoint < seekPointCount; ++iSeekPoint) {
62337  nextTargetPCMFrame += pcmFramesBetweenSeekPoints;
62338  for (;;) {
62339  if (nextTargetPCMFrame < runningPCMFrameCount) {
62340  pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
62341  pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
62342  pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
62343  pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
62344  break;
62345  } else {
62346  size_t i;
62347  drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
62348  for (i = 0; i < DRMP3_COUNTOF(mp3FrameInfo)-1; ++i) {
62349  mp3FrameInfo[i] = mp3FrameInfo[i+1];
62350  }
62351  mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize;
62352  mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount;
62353  pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
62354  if (pcmFramesInCurrentMP3FrameIn == 0) {
62355  pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
62356  pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
62357  pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
62358  pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
62359  break;
62360  }
62361  drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
62362  }
62363  }
62364  }
62365  if (!drmp3_seek_to_start_of_stream(pMP3)) {
62366  return DRMP3_FALSE;
62367  }
62368  if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
62369  return DRMP3_FALSE;
62370  }
62371  }
62372  *pSeekPointCount = seekPointCount;
62373  return DRMP3_TRUE;
62374 }
62376 {
62377  if (pMP3 == NULL) {
62378  return DRMP3_FALSE;
62379  }
62380  if (seekPointCount == 0 || pSeekPoints == NULL) {
62381  pMP3->seekPointCount = 0;
62382  pMP3->pSeekPoints = NULL;
62383  } else {
62384  pMP3->seekPointCount = seekPointCount;
62385  pMP3->pSeekPoints = pSeekPoints;
62386  }
62387  return DRMP3_TRUE;
62388 }
62389 static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
62390 {
62391  drmp3_uint64 totalFramesRead = 0;
62392  drmp3_uint64 framesCapacity = 0;
62393  float* pFrames = NULL;
62394  float temp[4096];
62395  DRMP3_ASSERT(pMP3 != NULL);
62396  for (;;) {
62397  drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
62398  drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp);
62399  if (framesJustRead == 0) {
62400  break;
62401  }
62402  if (framesCapacity < totalFramesRead + framesJustRead) {
62403  drmp3_uint64 oldFramesBufferSize;
62404  drmp3_uint64 newFramesBufferSize;
62405  drmp3_uint64 newFramesCap;
62406  float* pNewFrames;
62407  newFramesCap = framesCapacity * 2;
62408  if (newFramesCap < totalFramesRead + framesJustRead) {
62409  newFramesCap = totalFramesRead + framesJustRead;
62410  }
62411  oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(float);
62412  newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(float);
62413  if (newFramesBufferSize > DRMP3_SIZE_MAX) {
62414  break;
62415  }
62416  pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
62417  if (pNewFrames == NULL) {
62419  break;
62420  }
62421  pFrames = pNewFrames;
62422  framesCapacity = newFramesCap;
62423  }
62424  DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float)));
62425  totalFramesRead += framesJustRead;
62426  if (framesJustRead != framesToReadRightNow) {
62427  break;
62428  }
62429  }
62430  if (pConfig != NULL) {
62431  pConfig->channels = pMP3->channels;
62432  pConfig->sampleRate = pMP3->sampleRate;
62433  }
62434  drmp3_uninit(pMP3);
62435  if (pTotalFrameCount) {
62436  *pTotalFrameCount = totalFramesRead;
62437  }
62438  return pFrames;
62439 }
62440 static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
62441 {
62442  drmp3_uint64 totalFramesRead = 0;
62443  drmp3_uint64 framesCapacity = 0;
62444  drmp3_int16* pFrames = NULL;
62445  drmp3_int16 temp[4096];
62446  DRMP3_ASSERT(pMP3 != NULL);
62447  for (;;) {
62448  drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
62449  drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_s16(pMP3, framesToReadRightNow, temp);
62450  if (framesJustRead == 0) {
62451  break;
62452  }
62453  if (framesCapacity < totalFramesRead + framesJustRead) {
62454  drmp3_uint64 newFramesBufferSize;
62455  drmp3_uint64 oldFramesBufferSize;
62456  drmp3_uint64 newFramesCap;
62457  drmp3_int16* pNewFrames;
62458  newFramesCap = framesCapacity * 2;
62459  if (newFramesCap < totalFramesRead + framesJustRead) {
62460  newFramesCap = totalFramesRead + framesJustRead;
62461  }
62462  oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(drmp3_int16);
62463  newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(drmp3_int16);
62464  if (newFramesBufferSize > DRMP3_SIZE_MAX) {
62465  break;
62466  }
62467  pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
62468  if (pNewFrames == NULL) {
62470  break;
62471  }
62472  pFrames = pNewFrames;
62473  framesCapacity = newFramesCap;
62474  }
62475  DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(drmp3_int16)));
62476  totalFramesRead += framesJustRead;
62477  if (framesJustRead != framesToReadRightNow) {
62478  break;
62479  }
62480  }
62481  if (pConfig != NULL) {
62482  pConfig->channels = pMP3->channels;
62483  pConfig->sampleRate = pMP3->sampleRate;
62484  }
62485  drmp3_uninit(pMP3);
62486  if (pTotalFrameCount) {
62487  *pTotalFrameCount = totalFramesRead;
62488  }
62489  return pFrames;
62490 }
62491 DRMP3_API float* drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
62492 {
62493  drmp3 mp3;
62494  if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
62495  return NULL;
62496  }
62497  return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
62498 }
62499 DRMP3_API drmp3_int16* drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
62500 {
62501  drmp3 mp3;
62502  if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
62503  return NULL;
62504  }
62505  return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
62506 }
62507 DRMP3_API float* drmp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
62508 {
62509  drmp3 mp3;
62510  if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
62511  return NULL;
62512  }
62513  return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
62514 }
62515 DRMP3_API drmp3_int16* drmp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
62516 {
62517  drmp3 mp3;
62518  if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
62519  return NULL;
62520  }
62521  return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
62522 }
62523 #ifndef DR_MP3_NO_STDIO
62524 DRMP3_API float* drmp3_open_file_and_read_pcm_frames_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
62525 {
62526  drmp3 mp3;
62527  if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
62528  return NULL;
62529  }
62530  return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
62531 }
62532 DRMP3_API drmp3_int16* drmp3_open_file_and_read_pcm_frames_s16(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
62533 {
62534  drmp3 mp3;
62535  if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
62536  return NULL;
62537  }
62538  return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
62539 }
62540 #endif
62541 DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
62542 {
62543  if (pAllocationCallbacks != NULL) {
62544  return drmp3__malloc_from_callbacks(sz, pAllocationCallbacks);
62545  } else {
62546  return drmp3__malloc_default(sz, NULL);
62547  }
62548 }
62549 DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
62550 {
62551  if (pAllocationCallbacks != NULL) {
62552  drmp3__free_from_callbacks(p, pAllocationCallbacks);
62553  } else {
62555  }
62556 }
62557 #endif
62558 /* dr_mp3_c end */
62559 #endif /* DRMP3_IMPLEMENTATION */
62560 #endif /* MA_NO_MP3 */
62561 
62562 
62563 /* End globally disabled warnings. */
62564 #if defined(_MSC_VER)
62565  #pragma warning(pop)
62566 #endif
62567 
62568 #endif /* miniaudio_c */
62569 
62570 /*
62571 This software is available as a choice of the following licenses. Choose
62572 whichever you prefer.
62573 
62574 ===============================================================================
62575 ALTERNATIVE 1 - Public Domain (www.unlicense.org)
62576 ===============================================================================
62577 This is free and unencumbered software released into the public domain.
62578 
62579 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
62580 software, either in source code form or as a compiled binary, for any purpose,
62581 commercial or non-commercial, and by any means.
62582 
62583 In jurisdictions that recognize copyright laws, the author or authors of this
62584 software dedicate any and all copyright interest in the software to the public
62585 domain. We make this dedication for the benefit of the public at large and to
62586 the detriment of our heirs and successors. We intend this dedication to be an
62587 overt act of relinquishment in perpetuity of all present and future rights to
62588 this software under copyright law.
62589 
62590 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62591 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62592 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62593 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
62594 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
62595 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
62596 
62597 For more information, please refer to <http://unlicense.org/>
62598 
62599 ===============================================================================
62600 ALTERNATIVE 2 - MIT No Attribution
62601 ===============================================================================
62602 Copyright 2020 David Reid
62603 
62604 Permission is hereby granted, free of charge, to any person obtaining a copy of
62605 this software and associated documentation files (the "Software"), to deal in
62606 the Software without restriction, including without limitation the rights to
62607 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
62608 of the Software, and to permit persons to whom the Software is furnished to do
62609 so.
62610 
62611 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62612 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62613 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62614 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62615 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62616 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
62617 SOFTWARE.
62618 */
ma_int64
int64_t ma_int64
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1504
DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51418
ma__realloc_from_callbacks
static void * ma__realloc_from_callbacks(void *p, size_t szNew, size_t szOld, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1860
ma_encoder::config
ma_encoder_config config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5326
drwav_seek_origin
drwav_seek_origin
Definition: porcupine/demo/c/dr_libs/dr_wav.h:268
ma_device_is_started
MA_API ma_bool32 ma_device_is_started(const ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27603
drmp3_L3_gr_info::global_gain
drmp3_uint8 global_gain
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
drwav__write_u64ne_to_le
DRWAV_PRIVATE size_t drwav__write_u64ne_to_le(drwav *pWav, drwav_uint64 value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47851
ma_aaudio_usage_alarm
@ ma_aaudio_usage_alarm
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1829
drflac__realloc_default
static void * drflac__realloc_default(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54866
DRFLAC_ZERO_MEMORY
#define DRFLAC_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51350
DRFLAC_INLINE
#define DRFLAC_INLINE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51139
ma_backend_audio4
@ ma_backend_audio4
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2800
ma_pcm_rb_available_read
MA_API ma_uint32 ma_pcm_rb_available_read(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36949
ma_uint64
uint64_t ma_uint64
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1505
MA_FAILED_TO_STOP_BACKEND_DEVICE
#define MA_FAILED_TO_STOP_BACKEND_DEVICE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1733
ma_mp3_ds_get_length
static ma_result ma_mp3_ds_get_length(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42176
ma_get_bytes_per_frame
static MA_INLINE ma_uint32 ma_get_bytes_per_frame(ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2673
ma_bpf::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2052
ma_hpf1_get_latency
MA_API ma_uint32 ma_hpf1_get_latency(const ma_hpf1 *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31297
ma_device::speex
struct ma_device::@114::@120 speex
MA_LOG_LEVEL_DEBUG
#define MA_LOG_LEVEL_DEBUG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:208
ma_resampler_process_pcm_frames__read
static ma_result ma_resampler_process_pcm_frames__read(ma_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33246
ma_device_config::pDeviceID
ma_device_id * pDeviceID
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3127
ma_flac_init_memory
MA_API ma_result ma_flac_init_memory(const void *pData, size_t dataSize, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_flac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41744
ma_data_source_uninit
MA_API void ma_data_source_uninit(ma_data_source *pDataSource)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37255
drwav_init_with_metadata
DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav *pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void *pUserData, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47806
DRWAV_OUT_OF_MEMORY
#define DRWAV_OUT_OF_MEMORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39515
ma_backend_callbacks::onDeviceDataLoop
ma_result(* onDeviceDataLoop)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2134
drwav_s32_to_f32
DRWAV_API void drwav_s32_to_f32(float *pOut, const drwav_int32 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50396
MA_CHANNEL_AUX_12
#define MA_CHANNEL_AUX_12
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1633
ma_noise_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5400
drwav_acid::reserved1
drwav_uint16 reserved1
Definition: porcupine/demo/c/dr_libs/dr_wav.h:640
drwav_list_info_text
Definition: porcupine/demo/c/dr_libs/dr_wav.h:719
ma_data_converter_process_pcm_frames__channels_only
static ma_result ma_data_converter_process_pcm_frames__channels_only(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34898
DRFLAC_ALREADY_EXISTS
#define DRFLAC_ALREADY_EXISTS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51365
ma_decoder_init
MA_API ma_result ma_decoder_init(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43870
DRWAV_INVALID_OPERATION
#define DRWAV_INVALID_OPERATION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39514
NAME
string NAME
ma_vfs_or_default_info
MA_API ma_result ma_vfs_or_default_info(ma_vfs *pVFS, ma_vfs_file file, ma_file_info *pInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39420
ma_bpf2_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2024
ma_hpf2_process_pcm_frames
MA_API ma_result ma_hpf2_process_pcm_frames(ma_hpf2 *pHPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31389
drmp3_sin
static DRMP3_INLINE double drmp3_sin(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61066
drflac__decode_samples_with_residual__rice__scalar_zeroorder
static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar_zeroorder(drflac_bs *bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pSamplesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52892
MA_STATE_STARTED
#define MA_STATE_STARTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1627
ma_device_config::shareMode
ma_share_mode shareMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3131
ma_standard_channel_map_rfc3551
@ ma_standard_channel_map_rfc3551
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1807
ma_device_config::noClip
ma_bool32 noClip
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3109
drwav_s24_to_s16
DRWAV_API void drwav_s24_to_s16(drwav_int16 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50071
drwav_read_pcm_frames_f32__ima
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ima(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50222
drwav::delta
drwav_int32 delta[2]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:887
ma_biquad_process_pcm_frame_s16
static MA_INLINE void ma_biquad_process_pcm_frame_s16(ma_biquad *pBQ, ma_int16 *pY, const ma_int16 *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30565
ma_vfs_or_default_open_w
MA_API ma_result ma_vfs_or_default_open_w(ma_vfs *pVFS, const wchar_t *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39366
drflac__memory_stream
Definition: porcupine/demo/c/dr_libs/dr_flac.h:573
drflac_init_vorbis_comment_iterator
DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator *pIter, drflac_uint32 commentCount, const void *pComments)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59235
ma_lpf_reinit
MA_API ma_result ma_lpf_reinit(const ma_lpf_config *pConfig, ma_lpf *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31019
ma_mix_f32_fast
static MA_INLINE float ma_mix_f32_fast(float x, float y, float a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2350
MA_ATOMIC
#define MA_ATOMIC
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:225
g_drwavMulawTable
static unsigned short g_drwavMulawTable[256]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49836
ma_apply_volume_factor_pcm_frames_f32
MA_API void ma_apply_volume_factor_pcm_frames_f32(float *pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27984
drmp3_uninit
DRMP3_API void drmp3_uninit(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61946
drwav::bitsPerSample
drwav_uint16 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_wav.h:837
drflac_read_pcm_frames_s32__decode_left_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56797
drflac__seek_bits
static drflac_bool32 drflac__seek_bits(drflac_bs *bs, size_t bitsToSeek)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52100
ma_strappend
MA_API int ma_strappend(char *dst, size_t dstSize, const char *srcA, const char *srcB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1139
ma_strncpy_s
MA_API int ma_strncpy_s(char *dst, size_t dstSizeInBytes, const char *src, size_t count)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:925
ma_lcg_rand_u32
static MA_INLINE ma_uint32 ma_lcg_rand_u32(ma_lcg *pLCG)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2449
drmp3::channels
drmp3_uint32 channels
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:344
ma_channel_converter_config::channelMapOut
ma_channel channelMapOut[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2364
ma_context::playbackDeviceInfoCount
ma_uint32 playbackDeviceInfoCount
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3220
ma_notch2_process_pcm_frame_s16
static MA_INLINE void ma_notch2_process_pcm_frame_s16(ma_notch2 *pFilter, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32019
MA_LCG_C
#define MA_LCG_C
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2433
DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED
#define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39554
DRMP3_INVALID_DATA
#define DRMP3_INVALID_DATA
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40440
drflac__seek_to_byte
static drflac_bool32 drflac__seek_to_byte(drflac_bs *bs, drflac_uint64 offsetFromStart)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52338
drmp3_int16
signed short drmp3_int16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40348
DRMP3_INVALID_FILE
#define DRMP3_INVALID_FILE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40417
ma_pcm_s16_to_f32
MA_API void ma_pcm_s16_to_f32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28677
DRWAV_BEXT_UMID_BYTES
#define DRWAV_BEXT_UMID_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46888
DRMP3_NO_NETWORK
#define DRMP3_NO_NETWORK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40442
drwav_min
#define drwav_min(a, b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46304
MA_FALSE
#define MA_FALSE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1531
drwav_metadata_type_list_all_adtl
@ drwav_metadata_type_list_all_adtl
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39673
ma_device_type_loopback
@ ma_device_type_loopback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3015
drmp3dec::reserv
int reserv
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:265
ma_flac_ds_read
static ma_result ma_flac_ds_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41524
DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO
#define DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54514
drwav_init_write__internal
DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav *pWav, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48300
ma_decoder::data
union ma_decoder::@207 data
drwav_open_and_read_pcm_frames_s32
DRWAV_API drwav_int32 * drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void *pUserData, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50864
drwav_fmt::bitsPerSample
drwav_uint16 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_wav.h:320
MA_DEVICE_TYPE_NOT_SUPPORTED
#define MA_DEVICE_TYPE_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1716
ma_decoder::pBackendVTable
const ma_decoding_backend_vtable * pBackendVTable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4770
ma_event_uninit
MA_API void ma_event_uninit(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4872
drwav_smpl_loop::firstSampleByteOffset
drwav_uint32 firstSampleByteOffset
Definition: porcupine/demo/c/dr_libs/dr_wav.h:526
ma_waveform_set_amplitude
MA_API ma_result ma_waveform_set_amplitude(ma_waveform *pWaveform, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45480
drwav::fmt
drwav_fmt fmt
Definition: porcupine/demo/c/dr_libs/dr_wav.h:828
MA_CHANNEL_AUX_17
#define MA_CHANNEL_AUX_17
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1638
drflac__seek_forward_by_pcm_frames
static drflac_uint64 drflac__seek_forward_by_pcm_frames(drflac *pFlac, drflac_uint64 pcmFramesToSeek)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54418
ma_data_source_base
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4523
ma_device_config::resampling
struct ma_device_config::@96 resampling
ma_opensl_stream_type_voice
@ ma_opensl_stream_type_voice
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1802
ma_convert_frames_ex
MA_API ma_uint64 ma_convert_frames_ex(void *pOut, ma_uint64 frameCountOut, const void *pIn, ma_uint64 frameCountIn, const ma_data_converter_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36301
ma_lpf2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1908
ma_device_config::noAutoFormat
ma_bool32 noAutoFormat
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1991
MA_FAILED_TO_INIT_BACKEND
#define MA_FAILED_TO_INIT_BACKEND
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1730
ma_apply_volume_factor_pcm_frames_s32
MA_API void ma_apply_volume_factor_pcm_frames_s32(ma_int32 *pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27979
ma_convert_frames
MA_API ma_uint64 ma_convert_frames(void *pOut, ma_uint64 frameCountOut, ma_format formatOut, ma_uint32 channelsOut, ma_uint32 sampleRateOut, const void *pIn, ma_uint64 frameCountIn, ma_format formatIn, ma_uint32 channelsIn, ma_uint32 sampleRateIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36289
ma_device::resampling
struct ma_device::@114 resampling
drmp3_L3_read_scalefactors
static void drmp3_L3_read_scalefactors(drmp3_uint8 *scf, drmp3_uint8 *ist_pos, const drmp3_uint8 *scf_size, const drmp3_uint8 *scf_count, drmp3_bs *bitbuf, int scfsi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59849
DRFLAC_ZERO_OBJECT
#define DRFLAC_ZERO_OBJECT(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51353
DRWAV_CUE_BYTES
#define DRWAV_CUE_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46882
drmp3_L3_gr_info::n_short_sfb
drmp3_uint8 n_short_sfb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
c89atomic_compare_exchange_weak_explicit_32
#define c89atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3873
ma_wav
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40858
MA_ACCESS_DENIED
#define MA_ACCESS_DENIED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1665
drflac__read_uint32
static DRFLAC_INLINE drflac_bool32 drflac__read_uint32(drflac_bs *bs, unsigned int bitCount, drflac_uint32 *pResultOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51952
drwav_get_bytes_per_pcm_frame
DRWAV_PRIVATE drwav_uint32 drwav_get_bytes_per_pcm_frame(drwav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47470
drflac__be2host__cache_line
#define drflac__be2host__cache_line
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51834
ma_encoder::onWritePCMFrames
ma_encoder_write_pcm_frames_proc onWritePCMFrames
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5331
drmp3_mix_f32_fast
static DRMP3_INLINE float drmp3_mix_f32_fast(float x, float y, float a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61047
drwav_smpl::productId
drwav_uint32 productId
Definition: porcupine/demo/c/dr_libs/dr_wav.h:542
ma_context_command__wasapi::pEvent
ma_event * pEvent
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2175
c89atomic_compare_exchange_strong_explicit_64
c89atomic_bool c89atomic_compare_exchange_strong_explicit_64(volatile c89atomic_uint64 *dst, volatile c89atomic_uint64 *expected, c89atomic_uint64 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3855
ma_decoder__data_source_on_get_length
static ma_result ma_decoder__data_source_on_get_length(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43597
c89atomic_store_explicit_64
#define c89atomic_store_explicit_64(dst, src, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3788
ma_vfs_callbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4648
drwav__on_write_memory
DRWAV_PRIVATE size_t drwav__on_write_memory(void *pUserData, const void *pDataIn, size_t bytesToWrite)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49101
ma_hishelf2_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2152
drwav_init_ex
DRWAV_API drwav_bool32 drwav_init_ex(drwav *pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void *pReadSeekUserData, void *pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47799
ma_stream_layout_deinterleaved
@ ma_stream_layout_deinterleaved
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1769
ma_get_standard_channel_map_sound4
static void ma_get_standard_channel_map_sound4(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35996
DRWAV_FREE
#define DRWAV_FREE(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46291
ma_decoder_init_vfs_flac_w
MA_API ma_result ma_decoder_init_vfs_flac_w(ma_vfs *pVFS, const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44631
ma_audio_buffer_uninit_and_free
MA_API void ma_audio_buffer_uninit_and_free(ma_audio_buffer *pAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38416
ma_lpf2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1906
ma_thread
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2824
drwav_metadata_type_inst
@ drwav_metadata_type_inst
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39648
ma_vfs_tell
MA_API ma_result ma_vfs_tell(ma_vfs *pVFS, ma_vfs_file file, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38624
ma_biquad_config_init
MA_API ma_biquad_config ma_biquad_config_init(ma_format format, ma_uint32 channels, double b0, double b1, double b2, double a0, double a1, double a2)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30423
DRWAV_INST_BYTES
#define DRWAV_INST_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46880
ma_channel_converter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2367
drflac_oggbs::firstBytePos
drflac_uint64 firstBytePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55446
c89atomic_fetch_or_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_fetch_or_explicit_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3752
ma_log_register_callback
MA_API ma_result ma_log_register_callback(ma_log *pLog, ma_log_callback callback)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2061
ma_wav::dr
drwav dr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40867
drwav_init_file_write__internal_FILE
DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(drwav *pWav, FILE *pFile, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48999
MA_NO_ADDRESS
#define MA_NO_ADDRESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1697
drwav_metadata::bext
drwav_bext bext
Definition: porcupine/demo/c/dr_libs/dr_wav.h:797
ma_pcm_interleave_s16__optimized
static MA_INLINE void ma_pcm_interleave_s16__optimized(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28716
drflac_bs::onRead
drflac_read_proc onRead
Definition: porcupine/demo/c/dr_libs/dr_flac.h:584
drflac_subframe::subframeType
drflac_uint8 subframeType
Definition: porcupine/demo/c/dr_libs/dr_flac.h:628
ma_mp3_ds_get_cursor
static ma_result ma_mp3_ds_get_cursor(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42171
ma_rb::subbufferStrideInBytes
ma_uint32 subbufferStrideInBytes
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2570
ma_bpf2_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2025
ma_vfs_or_default_write
MA_API ma_result ma_vfs_or_default_write(ma_vfs *pVFS, ma_vfs_file file, const void *pSrc, size_t sizeInBytes, size_t *pBytesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39393
ma_device_config::streamType
ma_opensl_stream_type streamType
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2006
drwav__bswap_samples_s24
static DRWAV_INLINE void drwav__bswap_samples_s24(drwav_uint8 *pSamples, drwav_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46493
DRFLAC_VERSION_MAJOR
#define DRFLAC_VERSION_MAJOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39980
ma_device_id::dsound
ma_uint8 dsound[16]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3058
ma_encoder_config_init
MA_API ma_encoder_config ma_encoder_config_init(ma_resource_format resourceFormat, ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45183
ma_decoder_uninit
MA_API ma_result ma_decoder_uninit(ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44739
ma_data_converter_process_pcm_frames__passthrough
static ma_result ma_data_converter_process_pcm_frames__passthrough(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34682
ma_flac_ds_get_cursor
static ma_result ma_flac_ds_get_cursor(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41539
ma_opensl_stream_type_ring
@ ma_opensl_stream_type_ring
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1804
ma_hpf_init
MA_API ma_result ma_hpf_init(const ma_hpf_config *pConfig, ma_hpf *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31515
ma_pcm_deinterleave_s16__optimized
static MA_INLINE void ma_pcm_deinterleave_s16__optimized(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28745
MA_CHANNEL_AUX_10
#define MA_CHANNEL_AUX_10
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1631
drwav_open_file_and_read_pcm_frames_s32_w
DRWAV_API drwav_int32 * drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t *filename, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50967
c89atomic_load_32
#define c89atomic_load_32(ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3988
drmp3_version
DRMP3_API void drmp3_version(drmp3_uint32 *pMajor, drmp3_uint32 *pMinor, drmp3_uint32 *pRevision)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59313
ma_allocation_callbacks::onMalloc
void *(* onMalloc)(size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1826
ma_lpf_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1920
MA_CHANNEL_NONE
#define MA_CHANNEL_NONE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1601
drwav_bool32
drwav_uint32 drwav_bool32
Definition: porcupine/demo/c/dr_libs/dr_wav.h:163
ma_pcm_s24_to_s32__optimized
static MA_INLINE void ma_pcm_s24_to_s32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28941
ma_get_bytes_per_sample
MA_API ma_uint32 ma_get_bytes_per_sample(ma_format format)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37199
DRWAV_NOT_DIRECTORY
#define DRWAV_NOT_DIRECTORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39525
drflac_read_pcm_frames_s16__decode_left_side
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57580
ma_loshelf2_get_latency
MA_API ma_uint32 ma_loshelf2_get_latency(const ma_loshelf2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32293
ma_device::null_device
struct ma_device::@117::@121 null_device
ma_lpf::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1931
drflac__free_from_callbacks
static void drflac__free_from_callbacks(void *p, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54911
ma_resampler_uninit
MA_API void ma_resampler_uninit(ma_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33154
drmp3__on_seek_stdio
static drmp3_bool32 drmp3__on_seek_stdio(void *pUserData, int offset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61913
drflac_metadata::rawDataSize
drflac_uint32 rawDataSize
Definition: porcupine/demo/c/dr_libs/dr_flac.h:425
DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE
#define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51420
ma_hpf2_get_latency
MA_API ma_uint32 ma_hpf2_get_latency(const ma_hpf2 *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31398
drwav_f32_to_s32
DRWAV_API void drwav_f32_to_s32(drwav_int32 *pOut, const float *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50688
drmp3::pcmFramesConsumedInMP3Frame
drmp3_uint32 pcmFramesConsumedInMP3Frame
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:352
ma_vfs_or_default_tell
MA_API ma_result ma_vfs_or_default_tell(ma_vfs *pVFS, ma_vfs_file file, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39411
drwav_metadata::labelledCueRegion
drwav_list_labelled_cue_region labelledCueRegion
Definition: porcupine/demo/c/dr_libs/dr_wav.h:799
MA_NO_DEVICE
#define MA_NO_DEVICE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1719
drwavGUID_W64_RIFF
static const drwav_uint8 drwavGUID_W64_RIFF[16]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46387
ma_decoder::pBackend
ma_data_source * pBackend
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4769
ma_decoder_init_vfs_wav_w
MA_API ma_result ma_decoder_init_vfs_wav_w(ma_vfs *pVFS, const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44613
ma_device_descriptor::periodSizeInMilliseconds
ma_uint32 periodSizeInMilliseconds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2053
drwav_mulaw_to_s32
DRWAV_API void drwav_mulaw_to_s32(drwav_int32 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50718
ma_rb::subbufferCount
ma_uint32 subbufferCount
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2569
DR_WAVE_FORMAT_IEEE_FLOAT
#define DR_WAVE_FORMAT_IEEE_FLOAT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39567
ma_hishelf2_process_pcm_frame_s16
static MA_INLINE void ma_hishelf2_process_pcm_frame_s16(ma_hishelf2 *pFilter, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32400
ma_pcm_s16_to_f32__reference
static MA_INLINE void ma_pcm_s16_to_f32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28628
ma_data_source_base::cb
ma_data_source_callbacks cb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4525
drflac_bs::unalignedByteCount
size_t unalignedByteCount
Definition: porcupine/demo/c/dr_libs/dr_flac.h:598
ma_context_uninit_backend_apis__nix
static ma_result ma_context_uninit_backend_apis__nix(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26429
ma_linear_resampler::inAdvanceInt
ma_uint32 inAdvanceInt
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2207
drflac_cuesheet_track::trackNumber
drflac_uint8 trackNumber
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1296
drwav_read_pcm_frames_s16__mulaw
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49988
ma_device_config::noAutoConvertSRC
ma_bool32 noAutoConvertSRC
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3144
ma_rand_range_s32
static MA_INLINE ma_int32 ma_rand_range_s32(ma_int32 lo, ma_int32 hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2515
ma_pcm_f32_to_s24__optimized
static MA_INLINE void ma_pcm_f32_to_s24__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30044
ma_pcm_u8_to_f32
MA_API void ma_pcm_u8_to_f32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28308
DRFLAC_SOCKET_NOT_SUPPORTED
#define DRFLAC_SOCKET_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51401
drwav_fmt::validBitsPerSample
drwav_uint16 validBitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_wav.h:330
ma_channel_map_copy
MA_API void ma_channel_map_copy(ma_channel *pOut, const ma_channel *pIn, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36190
MA_CHANNEL_TOP_BACK_LEFT
#define MA_CHANNEL_TOP_BACK_LEFT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1618
ma_noise_config::amplitude
double amplitude
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5406
drmp3_decode_next_frame_ex__callbacks
static drmp3_uint32 drmp3_decode_next_frame_ex__callbacks(drmp3 *pMP3, drmp3d_sample_t *pPCMFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61193
MA_CHANNEL_BACK_RIGHT
#define MA_CHANNEL_BACK_RIGHT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1608
DRMP3_SEEK_LEADING_MP3_FRAMES
#define DRMP3_SEEK_LEADING_MP3_FRAMES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61011
ma_hpf::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1999
MA_INVALID_ARGS
#define MA_INVALID_ARGS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1661
drflac_uint64
unsigned long long drflac_uint64
Definition: porcupine/demo/c/dr_libs/dr_flac.h:259
ma_lpf1_reinit
MA_API ma_result ma_lpf1_reinit(const ma_lpf1_config *pConfig, ma_lpf1 *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30674
ma_pcm_u8_to_s16__reference
static MA_INLINE void ma_pcm_u8_to_s16__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28070
ma_decoder_get_cursor_in_pcm_frames
MA_API ma_result ma_decoder_get_cursor_in_pcm_frames(ma_decoder *pDecoder, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44763
MA_CHANNEL_AUX_31
#define MA_CHANNEL_AUX_31
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1652
DRFLAC_NO_HOST
#define DRFLAC_NO_HOST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51406
stb_vorbis_get_info
stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4280
ma_aaudio_usage_notification_event
@ ma_aaudio_usage_notification_event
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1837
drwav_list_labelled_cue_region::country
drwav_uint16 country
Definition: porcupine/demo/c/dr_libs/dr_wav.h:746
MA_CHANNEL_FRONT_RIGHT
#define MA_CHANNEL_FRONT_RIGHT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1604
ma_uint8
uint8_t ma_uint8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1499
ma_copy_string
MA_API char * ma_copy_string(const char *src, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1156
drmp3_uint64
unsigned long long drmp3_uint64
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:122
DRWAV_LIST_LABELLED_TEXT_BYTES
#define DRWAV_LIST_LABELLED_TEXT_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46891
drwav_chunk_header::guid
drwav_uint8 guid[16]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:286
ma_channel_converter_process_pcm_frames__simple_mono_expansion
static ma_result ma_channel_converter_process_pcm_frames__simple_mono_expansion(ma_channel_converter *pConverter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34201
drwav__on_write_stdio
DRWAV_PRIVATE size_t drwav__on_write_stdio(void *pUserData, const void *pData, size_t bytesToWrite)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48935
drmp3_open_and_read_pcm_frames_s16
DRMP3_API drmp3_int16 * drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void *pUserData, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62499
drmp3_L3_gr_info::n_long_sfb
drmp3_uint8 n_long_sfb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
ma_pcm_f32_to_s16__optimized
static MA_INLINE void ma_pcm_f32_to_s16__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29601
drflac_open_with_metadata_private
static drflac * drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void *pUserData, void *pUserDataMD, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55935
drwav__metadata_parser::pData
drwav_uint8 * pData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46906
ma_dlsym
MA_API ma_proc ma_dlsym(ma_context *pContext, ma_handle handle, const char *symbol)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5625
ma_timer::counter
ma_int64 counter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3051
c89atomic_exchange_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_exchange_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3499
drwav::totalPCMFrameCount
drwav_uint64 totalPCMFrameCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:843
ma_min
#define ma_min(x, y)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:778
c89atomic_if64::i
c89atomic_uint64 i
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4125
ma_hpf1::a
ma_biquad_coefficient a
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1965
drwav_init_memory
DRWAV_API drwav_bool32 drwav_init_memory(drwav *pWav, const void *data, size_t dataSize, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49153
drmp3dec_frame_info::layer
int layer
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:259
drflac_allocation_callbacks::onMalloc
void *(* onMalloc)(size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_flac.h:567
drmp3_L3_gr_info::part_23_length
drmp3_uint16 part_23_length
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59497
ma_mp3_init_internal
static ma_result ma_mp3_init_internal(const ma_decoding_backend_config *pConfig, ma_mp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42249
DRFLAC_OUT_OF_RANGE
#define DRFLAC_OUT_OF_RANGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51362
DRMP3_MODE_JOINT_STEREO
#define DRMP3_MODE_JOINT_STEREO
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59342
drwav__bswap_samples_pcm
static DRWAV_INLINE void drwav__bswap_samples_pcm(void *pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46546
drmp3_malloc
DRMP3_API void * drmp3_malloc(size_t sz, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62541
ma_noise
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5412
ma_mp3_ds_get_data_format
static ma_result ma_mp3_ds_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42166
MA_API_NOT_FOUND
#define MA_API_NOT_FOUND
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1720
ma_pcm_s16_to_s16
MA_API void ma_pcm_s16_to_s16(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28495
drmp3__realloc_from_callbacks
static void * drmp3__realloc_from_callbacks(void *p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61106
drwav_fmt::subFormat
drwav_uint8 subFormat[16]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:336
ma_decoder_init_file_flac
MA_API ma_result ma_decoder_init_file_flac(const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44697
ma_device_id::aaudio
ma_int32 aaudio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3067
drmp3__seeking_mp3_frame_info::bytePos
drmp3_uint64 bytePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62283
DRMP3_MAX_FREE_FORMAT_FRAME_SIZE
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59333
MA_CHANNEL_BACK_LEFT
#define MA_CHANNEL_BACK_LEFT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1607
ma_device::masterVolumeFactor
volatile float masterVolumeFactor
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3605
ma_decoder::pBackendUserData
void * pBackendUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4771
MA_VERSION_STRING
#define MA_VERSION_STRING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:24
drwav__malloc_from_callbacks
DRWAV_PRIVATE void * drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46632
drflac__free_default
static void drflac__free_default(void *p, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54871
ma_wav_read_pcm_frames
MA_API ma_result ma_wav_read_pcm_frames(ma_wav *pWav, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41160
ma_channel_mix_mode_custom_weights
@ ma_channel_mix_mode_custom_weights
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1798
ma_encoder_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5313
ma_decoder_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5174
ma_pcm_deinterleave_u8
MA_API void ma_pcm_deinterleave_u8(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28402
ma_lpf::lpf2Count
ma_uint32 lpf2Count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1933
ma_noise__data_source_on_get_data_format
static ma_result ma_noise__data_source_on_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45843
ma_audio_buffer_at_end
MA_API ma_bool32 ma_audio_buffer_at_end(const ma_audio_buffer *pAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38465
ma_resampler_config::quality
int quality
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2254
ma_audio_buffer::ownsData
ma_bool32 ownsData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4601
DRWAV_ALREADY_EXISTS
#define DRWAV_ALREADY_EXISTS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39519
ma_wav_init
MA_API ma_result ma_wav_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_wav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41005
ma_device::internalChannels
ma_uint32 internalChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3629
drflac_cuesheet_track
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1293
ma_tell_proc
ma_result(* ma_tell_proc)(void *pUserData, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4682
drflac__seek_to_first_frame
static drflac_bool32 drflac__seek_to_first_frame(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54404
ma_aaudio_usage_assistance_sonification
@ ma_aaudio_usage_assistance_sonification
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1832
drwav_list_label_or_note::stringLength
drwav_uint32 stringLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:667
ma_log_uninit
MA_API void ma_log_uninit(ma_log *pLog)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2032
ma_device_get_master_gain_db
MA_API ma_result ma_device_get_master_gain_db(ma_device *pDevice, float *pGainDB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27657
ma_decoding_backend_init_file_w__wav
static ma_result ma_decoding_backend_init_file_w__wav(void *pUserData, const wchar_t *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41412
ma_decoder_config_init_copy
MA_API ma_decoder_config ma_decoder_config_init_copy(const ma_decoder_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40668
DRFLAC_FREE
#define DRFLAC_FREE(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51344
drwav_smpl_loop_type_pingpong
@ drwav_smpl_loop_type_pingpong
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39682
drwavGUID_W64_WAVE
static const drwav_uint8 drwavGUID_W64_WAVE[16]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46388
MA_DEFAULT_CHANNELS
#define MA_DEFAULT_CHANNELS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:601
drflac__decode_samples__fixed
static drflac_bool32 drflac__decode_samples__fixed(drflac_bs *bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_uint8 lpcOrder, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53922
ma_pcm_s16_to_s24
MA_API void ma_pcm_s16_to_s24(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28541
ma_biquad::a1
ma_biquad_coefficient a1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1864
ma_encoder__on_init_wav
static ma_result ma_encoder__on_init_wav(ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45120
DRWAV_MAX_BITS_PER_SAMPLE
#define DRWAV_MAX_BITS_PER_SAMPLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46385
DRWAV_TOO_MANY_OPEN_FILES
#define DRWAV_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39520
drwav_int8
signed char drwav_int8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39450
MA_CHANNEL_TOP_BACK_CENTER
#define MA_CHANNEL_TOP_BACK_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1619
ma_lpf_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1921
ma_noise_type_brownian
@ ma_noise_type_brownian
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5397
MA_CHANNEL_AUX_0
#define MA_CHANNEL_AUX_0
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1621
ma_waveform__data_source_on_seek
static ma_result ma_waveform__data_source_on_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45399
drflac_meta_proc
void(* drflac_meta_proc)(void *pUserData, drflac_metadata *pMetadata)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40187
ma_biquad::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1860
DRMP3_NO_HOST
#define DRMP3_NO_HOST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40456
DRMP3_PATH_TOO_LONG
#define DRMP3_PATH_TOO_LONG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40419
MA_CANCELLED
#define MA_CANCELLED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1710
ma_strcmp
MA_API int ma_strcmp(const char *str1, const char *str2)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1116
DRFLAC_TRUE
#define DRFLAC_TRUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40015
ma_device_id::pulse
char pulse[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3061
ma_log_callback::pUserData
void * pUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:582
ma_pcm_s32_to_u8__reference
static MA_INLINE void ma_pcm_s32_to_u8__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29128
MA_CHANNEL_TOP_CENTER
#define MA_CHANNEL_TOP_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1614
ma_backend_wasapi
@ ma_backend_wasapi
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2795
ma_hpf::hpf2Count
ma_uint32 hpf2Count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2001
NULL
#define NULL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:92
ma_decode_from_vfs
MA_API ma_result ma_decode_from_vfs(ma_vfs *pVFS, const char *pFilePath, ma_decoder_config *pConfig, ma_uint64 *pFrameCountOut, void **ppPCMFramesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45042
ma_noise_read_pcm_frames__pink
static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__pink(ma_noise *pNoise, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46082
drwav__pcm_to_s16
DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16 *pOut, const drwav_uint8 *pIn, size_t totalSampleCount, unsigned int bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49862
ma_decoding_backend_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4723
ma_peak2_process_pcm_frame_f32
static MA_INLINE void ma_peak2_process_pcm_frame_f32(ma_peak2 *pFilter, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32153
MA_CONNECTION_REFUSED
#define MA_CONNECTION_REFUSED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1707
ma_mp3::pReadSeekTellUserData
void * pReadSeekTellUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42137
ma_flac_dr_callback__read
static size_t ma_flac_dr_callback__read(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41581
ma_dither_mode_triangle
@ ma_dither_mode_triangle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1776
ma_backend_callbacks::onDeviceWrite
ma_result(* onDeviceWrite)(ma_device *pDevice, const void *pFrames, ma_uint32 frameCount, ma_uint32 *pFramesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2133
ma_decoder_internal_on_tell__custom
static ma_result ma_decoder_internal_on_tell__custom(void *pUserData, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40778
ma_peak2_process_pcm_frames
MA_API ma_result ma_peak2_process_pcm_frames(ma_peak2 *pFilter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32158
ma_data_converter_config::channelMapIn
ma_channel channelMapIn[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2409
MA_CHANNEL_AUX_20
#define MA_CHANNEL_AUX_20
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1641
ma_proc
void(* ma_proc)(void)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1535
drmp3_L3_dct3_9
static void drmp3_L3_dct3_9(float *y)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60245
DRMP3_HDR_GET_SAMPLE_RATE
#define DRMP3_HDR_GET_SAMPLE_RATE(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59357
drwav__metadata_copy_string
DRWAV_PRIVATE char * drwav__metadata_copy_string(drwav__metadata_parser *pParser, char *str, size_t maxToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47078
drmp3dec_scratch::syn
float syn[18+15][2 *32]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59507
ma_channel_converter_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2354
ma_biquad::r1
ma_biquad_coefficient r1[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1866
ma_decoder_init_memory
MA_API ma_result ma_decoder_init_memory(const void *pData, size_t dataSize, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43977
ma_stop_proc
void(* ma_stop_proc)(ma_device *pDevice)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2974
c89atomic_load_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_load_explicit_8(volatile const c89atomic_uint8 *ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3765
DRMP3_HDR_IS_CRC
#define DRMP3_HDR_IS_CRC(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59347
c89atomic_exchange_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_exchange_explicit_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3521
ma_vfs_callbacks::onClose
ma_result(* onClose)(ma_vfs *pVFS, ma_vfs_file file)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4652
drwav_countof
#define drwav_countof(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46302
drwav_bytes_to_guid
static DRWAV_INLINE void drwav_bytes_to_guid(const drwav_uint8 *data, drwav_uint8 *guid)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46403
ma_standard_sample_rate_11025
@ ma_standard_sample_rate_11025
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:425
DRFLAC_SUBFRAME_CONSTANT
#define DRFLAC_SUBFRAME_CONSTANT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51412
DRFLAC_ASSERT
#define DRFLAC_ASSERT(expression)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51335
drmp3_seek_origin
drmp3_seek_origin
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40491
drwav_read_raw
DRWAV_API size_t drwav_read_raw(drwav *pWav, size_t bytesToRead, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49281
drwav_s16_to_f32
DRWAV_API void drwav_s16_to_f32(float *pOut, const drwav_int16 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50371
ma_pcm_s16_to_s32
MA_API void ma_pcm_s16_to_s32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28603
drwav_bext::loudnessRange
drwav_uint16 loudnessRange
Definition: porcupine/demo/c/dr_libs/dr_wav.h:706
ma_pcm_f32_to_u8__optimized
static MA_INLINE void ma_pcm_f32_to_u8__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29519
ma_data_converter_config::sampleRateOut
ma_uint32 sampleRateOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2408
ma_thread_priority_realtime
@ ma_thread_priority_realtime
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2820
drwav_init_file_write_w
DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav *pWav, const wchar_t *filename, const drwav_data_format *pFormat, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49045
stb_vorbis_seek
int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4893
ma_decoding_backend_init_file__flac
static ma_result ma_decoding_backend_init_file__flac(void *pUserData, const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42020
ma_channel_converter::isSimpleMonoExpansion
ma_bool32 isSimpleMonoExpansion
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2382
drwav_metadata_type_list_label
@ drwav_metadata_type_list_label
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39652
drwav_init_file
DRWAV_API drwav_bool32 drwav_init_file(drwav *pWav, const char *filename, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48943
ma_device_config::wasapi
struct ma_device_config::@99 wasapi
drflac_free
DRFLAC_API void drflac_free(void *p, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59227
DRMP3_SOCKET_NOT_SUPPORTED
#define DRMP3_SOCKET_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40451
drwav_metadata_type_none
@ drwav_metadata_type_none
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39645
ma_flac::onSeek
ma_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41503
ma_aaudio_usage_notification
@ ma_aaudio_usage_notification
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1836
drwav_chunk_header::sizeInBytes
drwav_uint64 sizeInBytes
Definition: porcupine/demo/c/dr_libs/dr_wav.h:290
ma_vfs_open_w
MA_API ma_result ma_vfs_open_w(ma_vfs *pVFS, const wchar_t *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38535
drflac
Definition: porcupine/demo/c/dr_libs/dr_flac.h:688
g_ma_decoding_backend_vtable_wav
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_wav
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41479
drwav_acid_flag
drwav_acid_flag
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39732
drmp3::currentReadPos
size_t currentReadPos
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:368
drflac_metadata::application
struct drflac_metadata::@0::@2 application
c89atomic_fetch_and_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_fetch_and_explicit_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3664
drflac_bool8
drflac_uint8 drflac_bool8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40013
ma_resource_format_wav
@ ma_resource_format_wav
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5147
ma_log::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:592
drflac_metadata::padding
struct drflac_metadata::@0::@1 padding
DRWAV_NOT_CONNECTED
#define DRWAV_NOT_CONNECTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39558
ma_flac_init_internal
static ma_result ma_flac_init_internal(const ma_decoding_backend_config *pConfig, ma_flac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41617
ma_context_uninit
MA_API ma_result ma_context_uninit(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26757
c89atomic_fetch_or_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_fetch_or_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3719
drwav_smpl_loop::type
drwav_uint32 type
Definition: porcupine/demo/c/dr_libs/dr_wav.h:523
ma_format_count
@ ma_format_count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1791
drmp3_L12_read_scale_info
static void drmp3_L12_read_scale_info(const drmp3_uint8 *hdr, drmp3_bs *bs, drmp3_L12_scale_info *sci)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59640
ma_thread_priority_normal
@ ma_thread_priority_normal
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2817
DRMP3_NOT_UNIQUE
#define DRMP3_NOT_UNIQUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40443
ma_channel_converter::f32
float f32[MA_MAX_CHANNELS][MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2377
ma_mutex_init
MA_API ma_result ma_mutex_init(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4769
ma_device_type_capture
@ ma_device_type_capture
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3013
ma_notch2_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2076
ma_device_descriptor::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2050
DRFLAC_ACCESS_DENIED
#define DRFLAC_ACCESS_DENIED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51363
ma_device_info::flags
ma_uint32 flags
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1933
drwav__ieee_to_s16
DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16 *pOut, const drwav_uint8 *pIn, size_t totalSampleCount, unsigned int bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49900
drwav_metadata_type_all_including_unknown
@ drwav_metadata_type_all_including_unknown
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39677
drwav_target_write_size_bytes
DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format *pFormat, drwav_uint64 totalFrameCount, drwav_metadata *pMetadata, drwav_uint32 metadataCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48408
ma_context::deviceInfoCapacity
ma_uint32 deviceInfoCapacity
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3219
ma_decoder__preinit
static ma_result ma_decoder__preinit(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, ma_decoder_tell_proc onTell, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43620
drflac::channels
drflac_uint8 channels
Definition: porcupine/demo/c/dr_libs/dr_flac.h:707
ma_hpf_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1989
ma_file_info::sizeInBytes
ma_uint64 sizeInBytes
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4645
ma_mp3::onSeek
ma_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42135
drflac_read_pcm_frames_f32
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac *pFlac, drflac_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58850
drwav_inst::highNote
drwav_int8 highNote
Definition: porcupine/demo/c/dr_libs/dr_wav.h:579
drmp3_L12_subband_alloc::code_tab_width
drmp3_uint8 code_tab_width
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59492
drmp3__full_read_and_close_s16
static drmp3_int16 * drmp3__full_read_and_close_s16(drmp3 *pMP3, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62440
drwav_preinit
DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav *pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void *pReadSeekUserData, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47489
drflac_seekpoint::firstPCMFrame
drflac_uint64 firstPCMFrame
Definition: porcupine/demo/c/dr_libs/dr_flac.h:390
drwav_bext::loudnessValue
drwav_uint16 loudnessValue
Definition: porcupine/demo/c/dr_libs/dr_wav.h:705
drmp3::currentPCMFrame
drmp3_uint64 currentPCMFrame
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:355
ma_wav_init_memory
MA_API ma_result ma_wav_init_memory(const void *pData, size_t dataSize, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_wav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41106
drwav_metadata::labelOrNote
drwav_list_label_or_note labelOrNote
Definition: porcupine/demo/c/dr_libs/dr_wav.h:798
ma_mp3_get_cursor_in_pcm_frames
MA_API ma_result ma_mp3_get_cursor_in_pcm_frames(ma_mp3 *pMP3, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42573
ma_decoder_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5170
ma_device::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3626
DRFLAC_COPY_MEMORY
#define DRFLAC_COPY_MEMORY(dst, src, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51347
ma_pcm_rb::rb
ma_rb rb
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2595
ma_aaudio_usage_announcement
@ ma_aaudio_usage_announcement
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1825
ma_log_unlock
static void ma_log_unlock(ma_log *pLog)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2052
drwav_f64_to_s32
DRWAV_API void drwav_f64_to_s32(drwav_int32 *pOut, const double *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50698
ma_encoder_uninit
MA_API void ma_encoder_uninit(ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45334
ma_audio_buffer_config::sizeInFrames
ma_uint64 sizeInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4590
ma_lpf1_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1887
c89atomic_memory_order_release
#define c89atomic_memory_order_release
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3291
drwav_metadata::type
drwav_metadata_type type
Definition: porcupine/demo/c/dr_libs/dr_wav.h:789
ma_device_config::deviceType
ma_device_type deviceType
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3102
ma_aaudio_usage_notification_ringtone
@ ma_aaudio_usage_notification_ringtone
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1838
c89atomic_fetch_sub_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_fetch_sub_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3587
MA_DEFAULT_LCG_SEED
#define MA_DEFAULT_LCG_SEED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2428
drflac_oggbs::pageData
drflac_uint8 pageData[DRFLAC_OGG_MAX_PAGE_SIZE]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55452
ma_channel_converter_config::channelsIn
ma_uint32 channelsIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2361
ma_resample_algorithm
ma_resample_algorithm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2234
ma_audio_buffer_ref_map
MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref *pAudioBufferRef, void **ppFramesOut, ma_uint64 *pFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38148
drflac__seek_to_pcm_frame__binary_search
static drflac_bool32 drflac__seek_to_pcm_frame__binary_search(drflac *pFlac, drflac_uint64 pcmFrameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54644
ma_bool32
ma_uint32 ma_bool32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1529
ma_biquad_config::a0
double a0
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1850
drmp3_config::channels
drmp3_uint32 channels
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:336
drflac_init_info::bs
drflac_bs bs
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54804
ma_has_avx512f
static MA_INLINE ma_bool32 ma_has_avx512f(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:324
drflac_init_info::firstFrameHeader
drflac_frame_header firstFrameHeader
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54805
ma_data_source_read_pcm_frames
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead, ma_bool32 loop)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37348
ma_device_stop
MA_API ma_result ma_device_stop(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27544
ma_calculate_channel_position_rectangular_weight
static float ma_calculate_channel_position_rectangular_weight(ma_channel channelPositionA, ma_channel channelPositionB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33691
ma_channel_converter::mixingMode
ma_channel_mix_mode mixingMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2374
drmp3_config
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:334
ma_device_init
MA_API ma_result ma_device_init(ma_context *pContext, const ma_device_config *pConfig, ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27048
drflac__crc8_table
static drflac_uint8 drflac__crc8_table[]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51614
ma_noise_read_pcm_frames__brownian
static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__brownian(ma_noise *pNoise, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46164
DRWAV_BAD_ADDRESS
#define DRWAV_BAD_ADDRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39535
ma_semaphore_uninit__posix
static void ma_semaphore_uninit__posix(ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4641
ma_noise::ds
ma_data_source_vtable ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:5022
drflac_init_info::onSeek
drflac_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54791
ma_pcm_s16_to_s32__optimized
static MA_INLINE void ma_pcm_s16_to_s32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28579
ma_waveform__calculate_advance
static double ma_waveform__calculate_advance(ma_uint32 sampleRate, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45424
DRMP3_SHORT_BLOCK_TYPE
#define DRMP3_SHORT_BLOCK_TYPE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59339
ma_event_signal__posix
static ma_result ma_event_signal__posix(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4604
ma_bpf2_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2026
drwav_container
drwav_container
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39580
ma_strncat_s
MA_API int ma_strncat_s(char *dst, size_t dstSizeInBytes, const char *src, size_t count)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1001
drwav_smpl::pLoops
drwav_smpl_loop * pLoops
Definition: porcupine/demo/c/dr_libs/dr_wav.h:563
drflac_cuesheet_track_iterator::countRemaining
drflac_uint32 countRemaining
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1279
ma_data_converter_set_rate
MA_API ma_result ma_data_converter_set_rate(ma_data_converter *pConverter, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35352
ma_lpf_init
MA_API ma_result ma_lpf_init(const ma_lpf_config *pConfig, ma_lpf *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31004
ma_mp3::onTell
ma_tell_proc onTell
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42136
drmp3_reset
static void drmp3_reset(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62099
ma_rb_available_write
MA_API ma_uint32 ma_rb_available_write(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36756
ma_convert_pcm_frames_format
MA_API void ma_convert_pcm_frames_format(void *pOut, ma_format formatOut, const void *pIn, ma_format formatIn, ma_uint64 frameCount, ma_uint32 channels, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30307
ma_lcg_rand_s16
static MA_INLINE ma_int16 ma_lcg_rand_s16(ma_lcg *pLCG)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2454
drflac_ogg__read_page_header
static drflac_result drflac_ogg__read_page_header(drflac_read_proc onRead, void *pUserData, drflac_ogg_page_header *pHeader, drflac_uint32 *pBytesRead, drflac_uint32 *pCRC32)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55407
drmp3_decode_next_frame
static drmp3_uint32 drmp3_decode_next_frame(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61299
ma_resampler_config::sampleRateOut
ma_uint32 sampleRateOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2245
ma_waveform_triangle_f32
static float ma_waveform_triangle_f32(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45553
ma_pcm_deinterleave_s32
MA_API void ma_pcm_deinterleave_s32(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29483
drwav__write_or_count_u32ne_to_le
DRWAV_PRIVATE size_t drwav__write_or_count_u32ne_to_le(drwav *pWav, drwav_uint32 value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47895
drwav::predictor
drwav_uint16 predictor[2]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:886
ma_waveform_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5361
ma_hpf2_process_pcm_frame_s16
static MA_INLINE void ma_hpf2_process_pcm_frame_s16(ma_hpf2 *pHPF, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31379
drflac_open_memory_and_read_pcm_frames_f32
DRFLAC_API float * drflac_open_memory_and_read_pcm_frames_f32(const void *data, size_t dataSize, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59209
ma_flac_init_file_w
MA_API ma_result ma_flac_init_file_w(const wchar_t *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_flac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41714
drflac__clz_software
static DRFLAC_INLINE drflac_uint32 drflac__clz_software(drflac_cache_t x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52183
DRWAV_TOO_MANY_LINKS
#define DRWAV_TOO_MANY_LINKS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39539
c89atomic_fetch_add_32
#define c89atomic_fetch_add_32(dst, src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4004
MA_CHANNEL_AUX_21
#define MA_CHANNEL_AUX_21
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1642
drflac__decode_flac_frame
static drflac_result drflac__decode_flac_frame(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54292
errno
int errno
DRWAV_INVALID_ARGS
#define DRWAV_INVALID_ARGS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39513
ma_pcm_u8_to_s24
MA_API void ma_pcm_u8_to_s24(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28177
ma_standard_sample_rate_max
@ ma_standard_sample_rate_max
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:432
drflac_container_ogg
@ drflac_container_ogg
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40103
ma_encoder::onUninit
ma_encoder_uninit_proc onUninit
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5330
drwav_container_rf64
@ drwav_container_rf64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39584
MA_CHANNEL_AUX_7
#define MA_CHANNEL_AUX_7
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1628
ma_hpf::hpf1
ma_hpf1 hpf1[1]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2002
ma_decoder_init_vfs_vorbis_w
MA_API ma_result ma_decoder_init_vfs_vorbis_w(ma_vfs *pVFS, const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44667
DRWAV_CUE_POINT_BYTES
#define DRWAV_CUE_POINT_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46889
ma_channel_map_equal
MA_API ma_bool32 ma_channel_map_equal(ma_uint32 channels, const ma_channel *pChannelMapA, const ma_channel *pChannelMapB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36234
ma_semaphore::lock
pthread_mutex_t lock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:534
ma_audio_buffer_ref::sizeInFrames
ma_uint64 sizeInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4568
drflac__get_channel_count_from_channel_assignment
static DRFLAC_INLINE drflac_uint8 drflac__get_channel_count_from_channel_assignment(drflac_int8 channelAssignment)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54286
ma_waveform_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5364
ma_countof
#define ma_countof(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:776
drwav_init_file_write
DRWAV_API drwav_bool32 drwav_init_file_write(drwav *pWav, const char *filename, const drwav_data_format *pFormat, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49030
drflac_wfopen
static drflac_result drflac_wfopen(FILE **ppFile, const wchar_t *pFilePath, const wchar_t *pOpenMode, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56530
ma_decode_memory
MA_API ma_result ma_decode_memory(const void *pData, size_t dataSize, ma_decoder_config *pConfig, ma_uint64 *pFrameCountOut, void **ppPCMFramesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45072
c89atomic_fetch_sub_32
#define c89atomic_fetch_sub_32(dst, src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4008
ma_format_f32
@ ma_format_f32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1790
ma_linear_resampler::config
ma_linear_resampler_config config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2206
ma_device_config::noHardwareOffloading
ma_bool32 noHardwareOffloading
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3147
drflac_vorbis_comment_iterator
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1257
drflac_read_proc
size_t(* drflac_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40185
ma_biquad_config::b1
double b1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1848
MA_LOG_LEVEL
#define MA_LOG_LEVEL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1594
ma_decoder_config::resampling
struct ma_decoder_config::@122 resampling
ma_hishelf2__get_biquad_config
static MA_INLINE ma_biquad_config ma_hishelf2__get_biquad_config(const ma_hishelf2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32324
ma_context_command__wasapi
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2172
DRMP3_BAD_MESSAGE
#define DRMP3_BAD_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40438
s
XmlRpcServer s
ma_decoder__on_read_vfs
static size_t ma_decoder__on_read_vfs(ma_decoder *pDecoder, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44245
DRMP3_HDR_GET_MY_SAMPLE_RATE
#define DRMP3_HDR_GET_MY_SAMPLE_RATE(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59358
ma_peak2_reinit
MA_API ma_result ma_peak2_reinit(const ma_peak2_config *pConfig, ma_peak2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32130
ma_bpf2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2023
ma_waveform__data_source_on_get_cursor
static ma_result ma_waveform__data_source_on_get_cursor(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45415
c89atomic_exchange_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_exchange_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3510
drmp3_result
drmp3_int32 drmp3_result
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40406
drflac_streaminfo::channels
drflac_uint8 channels
Definition: porcupine/demo/c/dr_libs/dr_flac.h:403
_stricmp
DR_INLINE int _stricmp(const char *string1, const char *string2)
Definition: porcupine/demo/c/dr_libs/old/dr.h:178
drwav_inst::highVelocity
drwav_int8 highVelocity
Definition: porcupine/demo/c/dr_libs/dr_wav.h:581
ma_lpf1_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1888
ma_channel_converter_init
MA_API ma_result ma_channel_converter_init(const ma_channel_converter_config *pConfig, ma_channel_converter *pConverter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33779
ma_dither_mode_rectangle
@ ma_dither_mode_rectangle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1775
DRMP3_INTERRUPT
#define DRMP3_INTERRUPT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40428
MA_MALLOC
#define MA_MALLOC(sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:722
DRWAV_NOT_UNIQUE
#define DRWAV_NOT_UNIQUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39547
ma_aaudio_usage_emergency
@ ma_aaudio_usage_emergency
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1826
drwav_allocation_callbacks::onRealloc
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:413
ma_backend_opensl
@ ma_backend_opensl
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2806
ma_vfs_or_default_read
MA_API ma_result ma_vfs_or_default_read(ma_vfs *pVFS, ma_vfs_file file, void *pDst, size_t sizeInBytes, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39384
ma_decoder::onRead
ma_decoder_read_proc onRead
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5195
ma_data_converter_config::ditherMode
ma_dither_mode ditherMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2411
MA_NOT_DIRECTORY
#define MA_NOT_DIRECTORY
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1673
ma_waveform_sine_f32
static float ma_waveform_sine_f32(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45524
ma_resampler_set_rate_ratio
MA_API ma_result ma_resampler_set_rate_ratio(ma_resampler *pResampler, float ratio)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33454
ma_data_converter_init
MA_API ma_result ma_data_converter_init(const ma_data_converter_config *pConfig, ma_data_converter *pConverter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34543
ma_decoder_init_file_wav
MA_API ma_result ma_decoder_init_file_wav(const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44692
ma_file_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4643
MA_DATA_CONVERTER_STACK_BUFFER_SIZE
#define MA_DATA_CONVERTER_STACK_BUFFER_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4226
ma_pcm_deinterleave_f32__reference
static void ma_pcm_deinterleave_f32__reference(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30205
ma_decoding_backend_init__flac
static ma_result ma_decoding_backend_init__flac(void *pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41996
ma_thread_priority_highest
@ ma_thread_priority_highest
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2819
ma_decoder_config::linear
struct ma_decoder_config::@122::@123 linear
ma_seek_origin_end
@ ma_seek_origin_end
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4640
MA_CHANNEL_TOP_FRONT_LEFT
#define MA_CHANNEL_TOP_FRONT_LEFT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1615
MA_NO_DATA_AVAILABLE
#define MA_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1691
DRFLAC_NO_MESSAGE
#define DRFLAC_NO_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51387
drwav__memory_stream_write::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:430
DRWAV_SEQUENTIAL
#define DRWAV_SEQUENTIAL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39572
DRMP3_DOES_NOT_EXIST
#define DRMP3_DOES_NOT_EXIST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40414
ma_bpf_process_pcm_frames
MA_API ma_result ma_bpf_process_pcm_frames(ma_bpf *pBPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31853
drwav_bext::codingHistorySize
drwav_uint32 codingHistorySize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:699
drwav__riff_chunk_size_riff
DRWAV_PRIVATE drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize, drwav_metadata *pMetadata, drwav_uint32 metadataCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48231
ma_mp3::dr
drmp3 dr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42140
drwav_bext::maxShortTermLoudness
drwav_uint16 maxShortTermLoudness
Definition: porcupine/demo/c/dr_libs/dr_wav.h:709
drwav_smpl_loop
Definition: porcupine/demo/c/dr_libs/dr_wav.h:517
drflac_ogg__seek_to_pcm_frame
static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac *pFlac, drflac_uint64 pcmFrameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55655
MA_BUSY
#define MA_BUSY
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1678
ma_decoder::memory
struct ma_decoder::@125 memory
drmp3_init_file
DRMP3_API drmp3_bool32 drmp3_init_file(drmp3 *pMP3, const char *pFilePath, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61917
c89atomic_if64::f
double f
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4126
drwav_cue_point::chunkStart
drwav_uint32 chunkStart
Definition: porcupine/demo/c/dr_libs/dr_wav.h:602
ma_biquad::b0
ma_biquad_coefficient b0
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1861
ma_mp3_init_memory
MA_API ma_result ma_mp3_init_memory(const void *pData, size_t dataSize, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_mp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42379
MA_FAILED_TO_OPEN_BACKEND_DEVICE
#define MA_FAILED_TO_OPEN_BACKEND_DEVICE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1731
speex_resampler_init
EXPORT SpeexResamplerState * speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:794
ma_data_source_base::pCurrent
ma_data_source * pCurrent
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4533
ma_log_post
MA_API ma_result ma_log_post(ma_log *pLog, ma_uint32 level, const char *pMessage)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2112
MA_64BIT
#define MA_64BIT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:65
ma_pcm_s24_to_s16
MA_API void ma_pcm_s24_to_s16(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28895
DRFLAC_NOT_UNIQUE
#define DRFLAC_NOT_UNIQUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51393
drmp3::pcmFrames
drmp3_uint8 pcmFrames[sizeof(float) *DRMP3_MAX_SAMPLES_PER_FRAME]
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:354
ma_gain_db_to_factor
MA_API float ma_gain_db_to_factor(float gain)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28000
DRWAV_SMPL_LOOP_BYTES
#define DRWAV_SMPL_LOOP_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46879
ma_device_config::noAutoStreamRouting
ma_bool32 noAutoStreamRouting
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3146
stb_vorbis_info
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:124
drwav_read_pcm_frames_s32be
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50646
drwav_f32_to_s16
DRWAV_API void drwav_f32_to_s16(drwav_int16 *pOut, const float *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50091
MA_CHANNEL_TOP_FRONT_RIGHT
#define MA_CHANNEL_TOP_FRONT_RIGHT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1617
ma_format_s32
@ ma_format_s32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1789
drflac_uint8
unsigned char drflac_uint8
Definition: porcupine/demo/c/dr_libs/dr_flac.h:242
drmp3_get_mp3_frame_count
DRMP3_API drmp3_uint64 drmp3_get_mp3_frame_count(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62261
DRWAV_BEXT_BYTES
#define DRWAV_BEXT_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46883
MA_INLINE
#define MA_INLINE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1569
ma_data_converter_config::channelsIn
ma_uint32 channelsIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2405
drwav_acid
Definition: porcupine/demo/c/dr_libs/dr_wav.h:631
ma_log10f
static MA_INLINE float ma_log10f(float x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:833
DRMP3_HDR_SIZE
#define DRMP3_HDR_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59343
drflac__read_and_decode_block_header
static DRFLAC_INLINE drflac_bool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void *pUserData, drflac_uint8 *isLastBlock, drflac_uint8 *blockType, drflac_uint32 *blockSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54819
MA_OUT_OF_RANGE
#define MA_OUT_OF_RANGE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1664
ma_data_source_vtable::onSeek
ma_result(* onSeek)(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4505
DRWAV_INVALID_FILE
#define DRWAV_INVALID_FILE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39521
DRWAV_BAD_PIPE
#define DRWAV_BAD_PIPE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39537
drmp3_allocation_callbacks_from_miniaudio
static drmp3_allocation_callbacks drmp3_allocation_callbacks_from_miniaudio(const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42194
drwav__chunk_padding_size_riff
DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46695
ma_context_post_error
static ma_result ma_context_post_error(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message, ma_result resultCode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5450
drflac_version
DRFLAC_API void drflac_version(drflac_uint32 *pMajor, drflac_uint32 *pMinor, drflac_uint32 *pRevision)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51424
ma_decoder_seek_to_pcm_frame
MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder *pDecoder, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44902
RESAMPLER_ERR_ALLOC_FAILED
@ RESAMPLER_ERR_ALLOC_FAILED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:105
drwav_result_from_errno
DRWAV_PRIVATE drwav_result drwav_result_from_errno(int e)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48427
drflac_oggbs::bytesRemainingInPage
drflac_uint32 bytesRemainingInPage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55450
ma_rb::subbufferSizeInBytes
ma_uint32 subbufferSizeInBytes
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2568
c89atomic_is_lock_free_ptr
static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_ptr(volatile void **ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3907
drflac_vorbis_comment_iterator::countRemaining
drflac_uint32 countRemaining
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1259
ma_silence_pcm_frames
MA_API void ma_silence_pcm_frames(void *p, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27789
drmp3_L3_gr_info::block_type
drmp3_uint8 block_type
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
ma_noise_read_pcm_frames__white
static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__white(ma_noise *pNoise, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45963
drflac_crc32_byte
static DRFLAC_INLINE drflac_uint32 drflac_crc32_byte(drflac_uint32 crc32, drflac_uint8 data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55321
drmp3_L3_gr_info::table_select
drmp3_uint8 table_select[3]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59499
ma__malloc_from_callbacks
static void * ma__malloc_from_callbacks(size_t sz, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1842
ma_waveform_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5365
drflac_metadata::cuesheet
struct drflac_metadata::@0::@5 cuesheet
DRWAV_PRIVATE
#define DRWAV_PRIVATE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39507
drwav_smpl::smpteOffset
drwav_uint32 smpteOffset
Definition: porcupine/demo/c/dr_libs/dr_wav.h:555
ma_mp3
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42131
ma_channel_map_copy_or_default
MA_API void ma_channel_map_copy_or_default(ma_channel *pOut, const ma_channel *pIn, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36197
FALSE
#define FALSE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:642
drmp3_init
DRMP3_API drmp3_bool32 drmp3_init(drmp3 *pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void *pUserData, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61339
drflac__seek_to_approximate_flac_frame_to_byte
static drflac_bool32 drflac__seek_to_approximate_flac_frame_to_byte(drflac *pFlac, drflac_uint64 targetByte, drflac_uint64 rangeLo, drflac_uint64 rangeHi, drflac_uint64 *pLastSuccessfulSeekOffset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54515
ma_is_backend_enabled
MA_API ma_bool32 ma_is_backend_enabled(ma_backend backend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5078
ma_audio_buffer_ref_get_available_frames
MA_API ma_result ma_audio_buffer_ref_get_available_frames(const ma_audio_buffer_ref *pAudioBufferRef, ma_uint64 *pAvailableFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38242
ma_prev_power_of_2
static MA_INLINE unsigned int ma_prev_power_of_2(unsigned int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1786
drflac_ogg_fail_on_crc_mismatch
@ drflac_ogg_fail_on_crc_mismatch
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55251
DRMP3_NOT_DIRECTORY
#define DRMP3_NOT_DIRECTORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40421
drwav__on_read_memory
DRWAV_PRIVATE size_t drwav__on_read_memory(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49061
ma_device_config::aaudio
struct ma_device_config::@179 aaudio
drmp3dec_frame_info::bitrate_kbps
int bitrate_kbps
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:259
ma_linear_resampler_get_expected_output_frame_count
MA_API ma_uint64 ma_linear_resampler_get_expected_output_frame_count(const ma_linear_resampler *pResampler, ma_uint64 inputFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33004
MA_SOCKET_NOT_SUPPORTED
#define MA_SOCKET_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1703
drflac_frame
Definition: porcupine/demo/c/dr_libs/dr_flac.h:673
ma_int8
int8_t ma_int8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1498
drwav::allowedMetadataTypes
drwav_metadata_type allowedMetadataTypes
Definition: porcupine/demo/c/dr_libs/dr_wav.h:870
DRWAV_MAX_CHANNELS
#define DRWAV_MAX_CHANNELS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46382
ma_mutex_uninit__posix
static void ma_mutex_uninit__posix(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4549
drmp3dec_frame_info::hz
int hz
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:259
drflac_container_unknown
@ drflac_container_unknown
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40104
drmp3_L3_gr_info::big_values
drmp3_uint16 big_values
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59497
drmp3_hdr_frame_bytes
static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59563
c89atomic_fetch_and_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_fetch_and_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3642
drflac_cuesheet_track::pIndexPoints
const drflac_cuesheet_track_index * pIndexPoints
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1301
ma_peak2_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2104
drwav::stepIndex
drwav_int32 stepIndex[2]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:898
drwav_init_file_ex
DRWAV_API drwav_bool32 drwav_init_file_ex(drwav *pWav, const char *filename, drwav_chunk_proc onChunk, void *pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48963
ma_uintptr
uintptr_t ma_uintptr
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1509
ma_device_config::alsa
struct ma_device_config::@100 alsa
ma_context_config::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3164
drflac_frame_header::channelAssignment
drflac_uint8 channelAssignment
Definition: porcupine/demo/c/dr_libs/dr_flac.h:664
drwav_smpl_loop_type_forward
@ drwav_smpl_loop_type_forward
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39681
ma_dlclose
MA_API void ma_dlclose(ma_context *pContext, ma_handle handle)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5614
drmp3dec_init
DRMP3_API void drmp3dec_init(drmp3dec *dec)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60855
drwav::onWrite
drwav_write_proc onWrite
Definition: porcupine/demo/c/dr_libs/dr_wav.h:811
MA_CHANNEL_AUX_11
#define MA_CHANNEL_AUX_11
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1632
ma_aaudio_usage_safety
@ ma_aaudio_usage_safety
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1827
ma_int16
int16_t ma_int16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1500
drwav_int64
signed long long drwav_int64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39467
ma_pcm_f32_to_s24
MA_API void ma_pcm_f32_to_s24(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30068
DRFLAC_NO_DATA_AVAILABLE
#define DRFLAC_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51389
drwav_open_memory_and_read_pcm_frames_s32
DRWAV_API drwav_int32 * drwav_open_memory_and_read_pcm_frames_s32(const void *data, size_t dataSize, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51019
ma_pcm_s32_to_s16__optimized
static MA_INLINE void ma_pcm_s32_to_s16__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29241
ma_allocation_callbacks::onFree
void(* onFree)(void *p, void *pUserData)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1828
ma_device_info::minChannels
ma_uint32 minChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3089
ma_duplex_rb::rb
ma_pcm_rb rb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1449
ma_hpf_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1985
DRMP3_PROTOCOL_UNAVAILABLE
#define DRMP3_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40447
ma_pcm_u8_to_s24__optimized
static MA_INLINE void ma_pcm_u8_to_s24__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28153
c89atomic_load_explicit_f32
static C89ATOMIC_INLINE float c89atomic_load_explicit_f32(volatile float *ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4142
drwav_metadata_type_list_info_title
@ drwav_metadata_type_list_info_title
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39657
c89atomic_fetch_sub_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_fetch_sub_explicit_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3620
c89atomic_spinlock_lock
static C89ATOMIC_INLINE void c89atomic_spinlock_lock(volatile c89atomic_spinlock *pSpinlock)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4179
decoder
ma_decoder decoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_deviceio/ma_test_deviceio.c:61
drwav_init_write_sequential_pcm_frames
DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav *pWav, const drwav_data_format *pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void *pUserData, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48392
drflac__seek_to_pcm_frame__brute_force
static drflac_bool32 drflac__seek_to_pcm_frame__brute_force(drflac *pFlac, drflac_uint64 pcmFrameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54441
ma_noise_set_amplitude
MA_API ma_result ma_noise_set_amplitude(ma_noise *pNoise, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45922
ma_semaphore_release
MA_API ma_result ma_semaphore_release(ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4974
drflac_bs::cacheL2
drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)]
Definition: porcupine/demo/c/dr_libs/dr_flac.h:613
drwav_metadata_location_top_level
@ drwav_metadata_location_top_level
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39795
ma_device_info::nativeDataFormatCount
ma_uint32 nativeDataFormatCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1927
drwav_list_labelled_cue_region::codePage
drwav_uint16 codePage
Definition: porcupine/demo/c/dr_libs/dr_wav.h:749
ma_device_id::nullbackend
int nullbackend
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3070
drmp3_result
drmp3_int32 drmp3_result
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:167
ma_pcm_interleave_s32__reference
static MA_INLINE void ma_pcm_interleave_s32__reference(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29435
drwav_read_pcm_frames_le
DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav *pWav, drwav_uint64 framesToRead, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49325
ma_standard_sample_rate_192000
@ ma_standard_sample_rate_192000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:422
drflac_ogg__get_page_header_size
static DRFLAC_INLINE drflac_uint32 drflac_ogg__get_page_header_size(drflac_ogg_page_header *pHeader)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55358
ma_spinlock_lock_ex
static MA_INLINE ma_result ma_spinlock_lock_ex(volatile ma_spinlock *pSpinlock, ma_bool32 yield)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4270
DRMP3_BAD_SEEK
#define DRMP3_BAD_SEEK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40432
ma_allocation_callbacks_init_default
static ma_allocation_callbacks ma_allocation_callbacks_init_default(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1911
DRWAV_ERROR
#define DRWAV_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39512
ma_encoding_format_wav
@ ma_encoding_format_wav
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4695
drflac_init_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54788
ma_device_config::stopCallback
ma_stop_proc stopCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3111
drflac_ogg_page_header::granulePosition
drflac_uint64 granulePosition
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54780
drwav_take_ownership_of_metadata
DRWAV_API drwav_metadata * drwav_take_ownership_of_metadata(drwav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47814
ma_resampler_set_rate
MA_API ma_result ma_resampler_set_rate(ma_resampler *pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33417
ma_wav::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40865
drwav_u8_to_f32
DRWAV_API void drwav_u8_to_f32(float *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50352
drmp3dec_scratch::bs
drmp3_bs bs
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59504
ma_resampler_process_pcm_frames__read__linear
static ma_result ma_resampler_process_pcm_frames__read__linear(ma_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33171
c89atomic_exchange_32
#define c89atomic_exchange_32(dst, src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3992
DRMP3_VERSION_MINOR
#define DRMP3_VERSION_MINOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40342
ma_resampler_get_input_latency
MA_API ma_uint64 ma_resampler_get_input_latency(const ma_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33560
MA_DEFAULT_CAPTURE_DEVICE_NAME
#define MA_DEFAULT_CAPTURE_DEVICE_NAME
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5418
ma_ios_session_category_record
@ ma_ios_session_category_record
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3032
ma_flac_ds_seek
static ma_result ma_flac_ds_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41529
ma_hpf1_reinit
MA_API ma_result ma_hpf1_reinit(const ma_hpf1_config *pConfig, ma_hpf1 *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31185
ma_pcm_s16_to_u8__reference
static MA_INLINE void ma_pcm_s16_to_u8__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28413
ma_data_source
void ma_data_source
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4500
ma_waveform_sine_s16
static ma_int16 ma_waveform_sine_s16(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45529
MA_INVALID_FILE
#define MA_INVALID_FILE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1669
ma_encoder_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5317
drmp3_version_string
const DRMP3_API char * drmp3_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59325
ma_linear_resampler_set_rate
MA_API ma_result ma_linear_resampler_set_rate(ma_linear_resampler *pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32958
c89atomic_if32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4118
DRFLAC_TOO_BIG
#define DRFLAC_TOO_BIG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51368
ma_mutex_uninit
MA_API void ma_mutex_uninit(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4784
drmp3_L3_antialias
static void drmp3_L3_antialias(float *grbuf, int nbands)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60212
drwav_mulaw_to_f32
DRWAV_API void drwav_mulaw_to_f32(float *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50426
drflac__get_pcm_frame_range_of_current_flac_frame
static void drflac__get_pcm_frame_range_of_current_flac_frame(drflac *pFlac, drflac_uint64 *pFirstPCMFrame, drflac_uint64 *pLastPCMFrame)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54384
ma_device::internalPeriods
ma_uint32 internalPeriods
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3633
ma_device_config::inputPreset
ma_aaudio_input_preset inputPreset
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2013
drflac_seek_origin
drflac_seek_origin
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40106
ma_flac::dr
drflac * dr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41508
ma_noise_set_seed
MA_API ma_result ma_noise_set_seed(ma_noise *pNoise, ma_int32 seed)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45932
drwav::bytesRemaining
drwav_uint64 bytesRemaining
Definition: porcupine/demo/c/dr_libs/dr_wav.h:853
ma_semaphore_init
MA_API ma_result ma_semaphore_init(int initialValue, ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4929
drflac_int8
signed char drflac_int8
Definition: porcupine/demo/c/dr_libs/dr_flac.h:241
ma_vfs_callbacks::onOpen
ma_result(* onOpen)(ma_vfs *pVFS, const char *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4650
drwav__on_seek_stdio
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48939
ma_device::channelMixMode
ma_channel_mix_mode channelMixMode
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2653
drwav__ieee_to_s32
DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32 *pOut, const drwav_uint8 *pIn, size_t totalSampleCount, unsigned int bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50474
BYTE
unsigned char BYTE
drmp3dec_scratch::grbuf
float grbuf[2][576]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59507
drwav__metadata_parser::pMetadata
drwav_metadata * pMetadata
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46904
drwav__read_bext_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata, drwav_uint64 chunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47091
ma_result_description
const MA_API char * ma_result_description(ma_result result)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37039
drwav_seek_origin
drwav_seek_origin
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39575
ma_channel_converter::channelMapOut
ma_channel channelMapOut[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2373
ma_format
ma_format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1779
ma_noise_set_type
MA_API ma_result ma_noise_set_type(ma_noise *pNoise, ma_noise_type type)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45943
MA_API
#define MA_API
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:174
ma_standard_channel_map_flac
@ ma_standard_channel_map_flac
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1808
drflac__seek_rice_parts
static DRFLAC_INLINE drflac_bool32 drflac__seek_rice_parts(drflac_bs *bs, drflac_uint8 riceParam)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52828
drwav_version_string
const DRWAV_API char * drwav_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46374
ma_semaphore
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2892
DRWAV_NO_DATA_AVAILABLE
#define DRWAV_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39543
drmp3_bool8
drmp3_uint8 drmp3_bool8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40374
ma_realloc
MA_API void * ma_realloc(void *p, size_t sz, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37126
MA_BAD_ADDRESS
#define MA_BAD_ADDRESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1683
ma_device::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3625
drwav_free
DRWAV_API void drwav_free(void *p, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51037
ma_dither_mode
ma_dither_mode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1772
drflac__init_private
static drflac_bool32 drflac__init_private(drflac_init_info *pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void *pUserData, void *pUserDataMD)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55854
ma_device_id::webaudio
char webaudio[32]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3069
ma_apply_volume_factor_pcm_frames
MA_API void ma_apply_volume_factor_pcm_frames(void *pPCMFrames, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27989
drflac_crc16_byte
static DRFLAC_INLINE drflac_uint16 drflac_crc16_byte(drflac_uint16 crc, drflac_uint8 data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51711
ma_data_converter_config::channelMixMode
ma_channel_mix_mode channelMixMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2412
drwav_inst
Definition: porcupine/demo/c/dr_libs/dr_wav.h:573
ma_peak2_config::frequency
double frequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2107
ma_backend_callbacks::onContextGetDeviceInfo
ma_result(* onContextGetDeviceInfo)(ma_context *pContext, ma_device_type deviceType, const ma_device_id *pDeviceID, ma_device_info *pDeviceInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2127
c89atomic_fetch_sub_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_fetch_sub_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3609
ma_decoding_backend_init__mp3
static ma_result ma_decoding_backend_init__mp3(void *pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42628
ma_context_config::threadPriority
ma_thread_priority threadPriority
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3163
drflac_has_sse41
static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51252
ma_decoder::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5208
drmp3dec::free_format_bytes
int free_format_bytes
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:265
drwav_read_pcm_frames_s32
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50607
drmp3__malloc_from_callbacks
static void * drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61093
speex_resampler_destroy
EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:868
drflac_streaminfo::minBlockSizeInPCMFrames
drflac_uint16 minBlockSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:398
ma_sleep__posix
static void ma_sleep__posix(ma_uint32 milliseconds)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:501
ma_linear_resampler_config::sampleRateOut
ma_uint32 sampleRateOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2210
miniaudio.h
ma_context_is_loopback_supported
MA_API ma_bool32 ma_context_is_loopback_supported(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27024
ma_decoding_backend_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4715
ma_data_source_init
MA_API ma_result ma_data_source_init(const ma_data_source_config *pConfig, ma_data_source *pDataSource)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37224
drflac_next_vorbis_comment
const DRFLAC_API char * drflac_next_vorbis_comment(drflac_vorbis_comment_iterator *pIter, drflac_uint32 *pCommentLengthOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59243
ma_log_callback_init
MA_API ma_log_callback ma_log_callback_init(ma_log_callback_proc onLog, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1991
drwav_init_file_write_sequential_pcm_frames
DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav *pWav, const char *filename, const drwav_data_format *pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49038
drwav__metadata_memory_capacity
DRWAV_PRIVATE size_t drwav__metadata_memory_capacity(drwav__metadata_parser *pParser)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46911
MA_CHANNEL_AUX_18
#define MA_CHANNEL_AUX_18
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1639
ma_device_type_playback
@ ma_device_type_playback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3012
ma_data_converter::hasPostFormatConversion
ma_bool32 hasPostFormatConversion
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2435
ma_pcm_sample_s32_to_s24_no_scale
static MA_INLINE void ma_pcm_sample_s32_to_s24_no_scale(ma_int64 x, ma_uint8 *s24)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28027
drflac_read_pcm_frames_s16__decode_independent_stereo__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58017
ma_waveform_read_pcm_frames__sine
static void ma_waveform_read_pcm_frames__sine(ma_waveform *pWaveform, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45583
drflac_ogg__read_page_header_after_capture_pattern
static drflac_result drflac_ogg__read_page_header_after_capture_pattern(drflac_read_proc onRead, void *pUserData, drflac_ogg_page_header *pHeader, drflac_uint32 *pBytesRead, drflac_uint32 *pCRC32)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55371
drmp3_read_pcm_frames_f32
DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3 *pMP3, drmp3_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62041
drflac_open_file
DRFLAC_API drflac * drflac_open_file(const char *pFileName, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56601
ma_apply_volume_factor_pcm_frames_s24
MA_API void ma_apply_volume_factor_pcm_frames_s24(void *pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27974
drwav_list_info_text::pString
char * pString
Definition: porcupine/demo/c/dr_libs/dr_wav.h:725
drmp3_seek_point::pcmFrameIndex
drmp3_uint64 pcmFrameIndex
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:293
drflac__memory_stream::data
const drflac_uint8 * data
Definition: porcupine/demo/c/dr_libs/dr_flac.h:575
ma_context_config::useVerboseDeviceEnumeration
ma_bool32 useVerboseDeviceEnumeration
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3168
drflac__memory_stream::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/dr_flac.h:576
DRWAV_ACCESS_DENIED
#define DRWAV_ACCESS_DENIED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39517
drwav::pMetadata
drwav_metadata * pMetadata
Definition: porcupine/demo/c/dr_libs/dr_wav.h:873
c89atomic_is_lock_free_8
static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_8(volatile void *ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3877
ma_loshelf2_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2131
DRMP3_VERSION_STRING
#define DRMP3_VERSION_STRING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40344
ma_hpf1_config_init
MA_API ma_hpf1_config ma_hpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31133
ma_standard_sample_rate_48000
@ ma_standard_sample_rate_48000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:412
drflac_metadata::data
union drflac_metadata::@0 data
ma_pcm_u8_to_s32__reference
static MA_INLINE void ma_pcm_u8_to_s32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28202
ma_aligned_free
MA_API void ma_aligned_free(void *p, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37171
ma_clip_s24
static MA_INLINE ma_int64 ma_clip_s24(ma_int64 x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28045
ma_thread_create__posix
static ma_result ma_thread_create__posix(ma_thread *pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4453
DRFLAC_CACHE_L1_SELECTION_SHIFT
#define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51840
DRWAV_IN_PROGRESS
#define DRWAV_IN_PROGRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39561
drmp3_L3_gr_info::scfsi
drmp3_uint8 scfsi
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59500
ma_device_id::wasapi
wchar_t wasapi[64]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3057
drmp3_bool32
drmp3_uint32 drmp3_bool32
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:133
ma_lpf_process_pcm_frames
MA_API ma_result ma_lpf_process_pcm_frames(ma_lpf *pLPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31060
DRMP3_IS_DIRECTORY
#define DRMP3_IS_DIRECTORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40422
MA_NOT_CONNECTED
#define MA_NOT_CONNECTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1706
MA_ADDRESS_FAMILY_NOT_SUPPORTED
#define MA_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1702
ma_backend_callbacks::onContextInit
ma_result(* onContextInit)(ma_context *pContext, const ma_context_config *pConfig, ma_backend_callbacks *pCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2124
ma_audio_buffer_ref__data_source_on_map
static ma_result ma_audio_buffer_ref__data_source_on_map(ma_data_source *pDataSource, void **ppFramesOut, ma_uint64 *pFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37990
DRFLAC_NOT_CONNECTED
#define DRFLAC_NOT_CONNECTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51404
ma_flac_ds_get_length
static ma_result ma_flac_ds_get_length(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41544
ma_vfs_callbacks::onRead
ma_result(* onRead)(ma_vfs *pVFS, ma_vfs_file file, void *pDst, size_t sizeInBytes, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4653
ma_device_info::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1930
DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED
#define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40449
drwav_smpl::samplePeriodNanoseconds
drwav_uint32 samplePeriodNanoseconds
Definition: porcupine/demo/c/dr_libs/dr_wav.h:545
ma_default_vfs_read
static ma_result ma_default_vfs_read(ma_vfs *pVFS, ma_vfs_file file, void *pDst, size_t sizeInBytes, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39251
ma_seed
static MA_INLINE void ma_seed(ma_int32 seed)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2485
drflac_ogg__is_capture_pattern
static DRFLAC_INLINE drflac_bool32 drflac_ogg__is_capture_pattern(drflac_uint8 pattern[4])
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55354
drwav__chunk_matches
DRWAV_PRIVATE drwav_bool32 drwav__chunk_matches(drwav_uint64 allowedMetadataTypes, const drwav_uint8 *pChunkID, drwav_metadata_type type, const char *pID)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47260
DRFLAC_CACHE_L1_SELECTION_MASK
#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51839
ma_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1823
ma_audio_buffer_get_available_frames
MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer *pAudioBuffer, ma_uint64 *pAvailableFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38492
ma_biquad_process_pcm_frame_f32__direct_form_2_transposed
static MA_INLINE void ma_biquad_process_pcm_frame_f32__direct_form_2_transposed(ma_biquad *pBQ, float *pY, const float *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30506
stb_vorbis_open_filename
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc_buffer)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:5057
drwav_result
drwav_int32 drwav_result
Definition: porcupine/demo/c/dr_libs/dr_wav.h:197
drflac__on_seek_ogg
static drflac_bool32 drflac__on_seek_ogg(void *pUserData, int offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55619
ma_device::converter
ma_data_converter converter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3634
ma_context_get_devices
MA_API ma_result ma_context_get_devices(ma_context *pContext, ma_device_info **ppPlaybackDeviceInfos, ma_uint32 *pPlaybackDeviceCount, ma_device_info **ppCaptureDeviceInfos, ma_uint32 *pCaptureDeviceCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26866
ma_context_uninit_backend_apis
static ma_result ma_context_uninit_backend_apis(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26513
ma_data_converter_get_expected_output_frame_count
MA_API ma_uint64 ma_data_converter_get_expected_output_frame_count(const ma_data_converter *pConverter, ma_uint64 inputFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35391
ma_device_descriptor::channelMap
ma_channel channelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2051
DRMP3_UNAVAILABLE
#define DRMP3_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40429
MA_REALLOC
#define MA_REALLOC(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:730
ma_lpf1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1893
g_ma_audio_buffer_ref_data_source_vtable
static ma_data_source_vtable g_ma_audio_buffer_ref_data_source_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38029
drflac_subframe::lpcOrder
drflac_uint8 lpcOrder
Definition: porcupine/demo/c/dr_libs/dr_flac.h:634
ma_audio_buffer_ref_set_data
MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref *pAudioBufferRef, const void *pData, ma_uint64 sizeInFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38077
drflac__calculate_prediction_32
static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_32(drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52418
ma_rb
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2561
drflac_oggbs
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55440
ma_channel_converter_float_to_fixed
static ma_int32 ma_channel_converter_float_to_fixed(float x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33753
drmp3_wfopen
static drmp3_result drmp3_wfopen(FILE **ppFile, const wchar_t *pFilePath, const wchar_t *pOpenMode, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61847
DRFLAC_NOT_SOCKET
#define DRFLAC_NOT_SOCKET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51394
MA_TOO_BIG
#define MA_TOO_BIG
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1670
ma_context::backend
ma_backend backend
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3212
MA_DEFAULT_FORMAT
#define MA_DEFAULT_FORMAT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:596
DRFLAC_API
#define DRFLAC_API
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40041
ma_flac::onRead
ma_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41502
DRFLAC_INVALID_DATA
#define DRFLAC_INVALID_DATA
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51390
drflac_init_info::hasStreamInfoBlock
drflac_bool32 hasStreamInfoBlock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54802
ma_resampler::speex
struct ma_resampler::@77::@78 speex
ma_mp3_init_file
MA_API ma_result ma_mp3_init_file(const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_mp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42317
ma_lcg_rand_s32
static MA_INLINE ma_int32 ma_lcg_rand_s32(ma_lcg *pLCG)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2443
ma_flac_get_data_format
MA_API ma_result ma_flac_get_data_format(ma_flac *pFlac, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41892
ma_default_vfs_info
static ma_result ma_default_vfs_info(ma_vfs *pVFS, ma_vfs_file file, ma_file_info *pInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39317
MA_TOO_MANY_LINKS
#define MA_TOO_MANY_LINKS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1687
drflac__clz
static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52304
DRWAV_VERSION_MAJOR
#define DRWAV_VERSION_MAJOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39445
ma_get_standard_channel_map_vorbis
static void ma_get_standard_channel_map_vorbis(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35908
MA_CHANNEL_AUX_16
#define MA_CHANNEL_AUX_16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1637
c89atomic_if32::f
float f
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4121
ma_mix_f64
static MA_INLINE double ma_mix_f64(double x, double y, double a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2384
drflac_open_memory
DRFLAC_API drflac * drflac_open_memory(const void *pData, size_t dataSize, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56697
ma_share_mode_exclusive
@ ma_share_mode_exclusive
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3021
ma_linear_resampler_set_rate_ratio
MA_API ma_result ma_linear_resampler_set_rate_ratio(ma_linear_resampler *pResampler, float ratioInOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32963
drflac_result_from_errno
static drflac_result drflac_result_from_errno(int e)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56088
ma_lpf_process_pcm_frame_s16
static MA_INLINE void ma_lpf_process_pcm_frame_s16(ma_lpf *pLPF, ma_int16 *pY, const ma_int16 *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31042
drmp3_seek_to_pcm_frame__brute_force
static drmp3_bool32 drmp3_seek_to_pcm_frame__brute_force(drmp3 *pMP3, drmp3_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62132
drwav_metadata_type_list_info_software
@ drwav_metadata_type_list_info_software
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39655
drwav::dataChunkDataSizeTargetWrite
drwav_uint64 dataChunkDataSizeTargetWrite
Definition: porcupine/demo/c/dr_libs/dr_wav.h:863
drwav_uint64
unsigned long long drwav_uint64
Definition: porcupine/demo/c/dr_libs/dr_wav.h:152
ma_audio_buffer_ref_uninit
MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref *pAudioBufferRef)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38068
ma_loshelf2_config_init
MA_API ma_loshelf2_config ma_loshelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32182
ma_device_info::minSampleRate
ma_uint32 minSampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3091
ma_pcm_s16_to_s32__reference
static MA_INLINE void ma_pcm_s16_to_s32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28566
ma_resampler_config::sampleRateIn
ma_uint32 sampleRateIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2244
c89atomic_load_explicit_f64
static C89ATOMIC_INLINE double c89atomic_load_explicit_f64(volatile double *ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4148
drflac_bs::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:590
drflac_ogg_page_header::segmentTable
drflac_uint8 segmentTable[255]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54785
MA_DEVICE_OP_NONE__NULL
#define MA_DEVICE_OP_NONE__NULL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6218
drwav_acid::numBeats
drwav_uint32 numBeats
Definition: porcupine/demo/c/dr_libs/dr_wav.h:644
ma_apply_volume_factor_f32
MA_API void ma_apply_volume_factor_f32(float *pSamples, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27921
c89atomic_uint8
unsigned char c89atomic_uint8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2573
c89atomic_compare_and_swap_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_compare_and_swap_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 expected, c89atomic_uint32 desired)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3463
ma_rb_commit_write
MA_API ma_result ma_rb_commit_write(ma_rb *pRB, size_t sizeInBytes, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36584
drwav__bswap_samples_f64
static DRWAV_INLINE void drwav__bswap_samples_f64(double *pSamples, drwav_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46539
drflac_open_memory_and_read_pcm_frames_s16
DRFLAC_API drflac_int16 * drflac_open_memory_and_read_pcm_frames_s16(const void *data, size_t dataSize, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59191
g_maLCG
static ma_lcg g_maLCG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2435
ma_lpf1_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1889
ma_audio_buffer_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4589
MA_DEFAULT_PLAYBACK_DEVICE_NAME
#define MA_DEFAULT_PLAYBACK_DEVICE_NAME
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5417
ma_audio_buffer_ref::cursor
ma_uint64 cursor
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4567
ma_rb__construct_offset
static MA_INLINE ma_uint32 ma_rb__construct_offset(ma_uint32 offsetInBytes, ma_uint32 offsetLoopFlag)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36356
ma_hpf1_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1949
ma_format_s24
@ ma_format_s24
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1788
ma_has_avx2
static MA_INLINE ma_bool32 ma_has_avx2(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:289
ma_linear_resampler::f32
float f32[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2213
drflac::memoryStream
drflac__memory_stream memoryStream
Definition: porcupine/demo/c/dr_libs/dr_flac.h:741
ma_rb_get_subbuffer_stride
MA_API size_t ma_rb_get_subbuffer_stride(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36774
ma_biquad_reinit
MA_API ma_result ma_biquad_reinit(const ma_biquad_config *pConfig, ma_biquad *pBQ)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30459
drflac_read_pcm_frames_s32__decode_mid_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57052
MA_MOVE_MEMORY
#define MA_MOVE_MEMORY(dst, src, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:762
ma_mp3_dr_callback__read
static size_t ma_mp3_dr_callback__read(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42213
ma_audio_buffer_ref_at_end
MA_API ma_bool32 ma_audio_buffer_ref_at_end(const ma_audio_buffer_ref *pAudioBufferRef)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38199
ma_backend_callbacks::onDeviceUninit
ma_result(* onDeviceUninit)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2129
DRMP3_ACCESS_DENIED
#define DRMP3_ACCESS_DENIED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40413
drwav__memory_stream::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:421
DRFLAC_VERSION_MINOR
#define DRFLAC_VERSION_MINOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39981
ma_audio_buffer_ref__data_source_on_get_cursor
static ma_result ma_audio_buffer_ref__data_source_on_get_cursor(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38011
drmp3_hdr_bitrate_kbps
static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59546
ma_linear_resampler_config::sampleRateIn
ma_uint32 sampleRateIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2209
c89atomic_load_explicit_ptr
static C89ATOMIC_INLINE void * c89atomic_load_explicit_ptr(volatile void **ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3911
MA_CHANNEL_LFE
#define MA_CHANNEL_LFE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1606
drwav_chunk_header::fourcc
drwav_uint8 fourcc[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:285
drmp3_L12_subband_alloc::tab_offset
drmp3_uint8 tab_offset
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59492
ma_device_config::dataCallback
ma_device_callback_proc dataCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3110
ma_device_config::noMMap
ma_bool32 noMMap
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3151
drflac__decode_samples_with_residual__unencoded
static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs *bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 unencodedBitsPerSample, drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pSamplesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53744
ma_device_id::coreaudio
char coreaudio[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3063
drwav__bswap16
static DRWAV_INLINE drwav_uint16 drwav__bswap16(drwav_uint16 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46410
ma_biquad_init
MA_API ma_result ma_biquad_init(const ma_biquad_config *pConfig, ma_biquad *pBQ)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30440
drflac_read_pcm_frames_s32__decode_right_side
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57021
drmp3
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:340
ma_thread_priority_lowest
@ ma_thread_priority_lowest
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2815
ma_vfs_open_and_read_file_ex
static ma_result ma_vfs_open_and_read_file_ex(ma_vfs *pVFS, const char *pFilePath, const wchar_t *pFilePathW, void **ppData, size_t *pSize, const ma_allocation_callbacks *pAllocationCallbacks, ma_uint32 allocationType)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38667
ma_biquad_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1843
ma_vfs_open_and_read_file_w
MA_API ma_result ma_vfs_open_and_read_file_w(ma_vfs *pVFS, const wchar_t *pFilePath, void **ppData, size_t *pSize, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38737
drflac_read_pcm_frames_f32__decode_left_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58203
g_ma_noise_data_source_vtable
static ma_data_source_vtable g_ma_noise_data_source_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45854
ma_decoder_init_vfs_wav
MA_API ma_result ma_decoder_init_vfs_wav(ma_vfs *pVFS, const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44410
drwav_open_and_read_pcm_frames_f32
DRWAV_API float * drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void *pUserData, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50847
drwav_alaw_to_s16
DRWAV_API void drwav_alaw_to_s16(drwav_int16 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50119
ma_decoder::pData
const ma_uint8 * pData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5216
drwav_fopen
DRWAV_PRIVATE drwav_result drwav_fopen(FILE **ppFile, const char *pFilePath, const char *pOpenMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48828
MA_UNAVAILABLE
#define MA_UNAVAILABLE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1681
ma_biquad_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1846
drmp3_open_file_and_read_pcm_frames_s16
DRMP3_API drmp3_int16 * drmp3_open_file_and_read_pcm_frames_s16(const char *filePath, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62532
ma_opensl_stream_type_notification
@ ma_opensl_stream_type_notification
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1807
drwav__seek_forward
DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46733
drwav_read_pcm_frames_f32__mulaw
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50284
ma_seek_origin
ma_seek_origin
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5139
drmp3dec_frame_info
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:257
DRFLAC_ERROR
#define DRFLAC_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51358
ma_audio_buffer_alloc_and_init
MA_API ma_result ma_audio_buffer_alloc_and_init(const ma_audio_buffer_config *pConfig, ma_audio_buffer **ppAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38362
drwav_cue_point::dataChunkId
drwav_uint8 dataChunkId[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:599
ma_data_source_seek_to_pcm_frame
MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37549
ma_audio_buffer_ref::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4565
drwav_fmt::channelMask
drwav_uint32 channelMask
Definition: porcupine/demo/c/dr_libs/dr_wav.h:333
stb_vorbis_stream_length_in_samples
unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4920
ma_device::noPreZeroedOutputBuffer
ma_bool32 noPreZeroedOutputBuffer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3603
DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51417
drflac_frame_header::flacFrameNumber
drflac_uint32 flacFrameNumber
Definition: porcupine/demo/c/dr_libs/dr_flac.h:652
drwav__strlen_clamped
DRWAV_PRIVATE size_t drwav__strlen_clamped(char *str, size_t maxToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47070
drmp3_seek_point::pcmFramesToDiscard
drmp3_uint16 pcmFramesToDiscard
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:295
ma_thread_result
void * ma_thread_result
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4266
ma_lpf_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1922
ma_backend_callbacks::onDeviceRead
ma_result(* onDeviceRead)(ma_device *pDevice, void *pFrames, ma_uint32 frameCount, ma_uint32 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2132
ma_malloc
MA_API void * ma_malloc(size_t sz, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37117
ma_log_unregister_callback
MA_API ma_result ma_log_unregister_callback(ma_log *pLog, ma_log_callback callback)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2083
ma_peak2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2102
ma_spinlock_lock
MA_API ma_result ma_spinlock_lock(volatile ma_spinlock *pSpinlock)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4291
drwav_cue_point::playOrderPosition
drwav_uint32 playOrderPosition
Definition: porcupine/demo/c/dr_libs/dr_wav.h:596
DRMP3_TOO_MANY_OPEN_FILES
#define DRMP3_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40416
c89atomic_store_explicit_f32
static C89ATOMIC_INLINE void c89atomic_store_explicit_f32(volatile float *dst, float src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4130
drmp3__on_seek
static drmp3_bool32 drmp3__on_seek(drmp3 *pMP3, int offset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61156
drflac_int16
signed short drflac_int16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39987
ma__free_default
static void ma__free_default(void *p, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1835
ma_device__read_frames_from_client
static void ma_device__read_frames_from_client(ma_device *pDevice, ma_uint32 frameCount, void *pFramesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5736
drwav_smpl::pSamplerSpecificData
drwav_uint8 * pSamplerSpecificData
Definition: porcupine/demo/c/dr_libs/dr_wav.h:564
ma_bpf2_process_pcm_frame_f32
static MA_INLINE void ma_bpf2_process_pcm_frame_f32(ma_bpf2 *pBPF, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31723
drwav__write_or_count_string_to_fixed_size_buf
DRWAV_PRIVATE size_t drwav__write_or_count_string_to_fixed_size_buf(drwav *pWav, char *str, size_t bufFixedSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47918
ma_data_converter::isPassthrough
ma_bool32 isPassthrough
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2438
drwav__bswap_samples_ieee
static DRWAV_INLINE void drwav__bswap_samples_ieee(void *pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46568
ma_channel_map_init_blank
MA_API void ma_channel_map_init_blank(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35565
drwav_allocation_callbacks::onFree
void(* onFree)(void *p, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:414
DRMP3_REALLOC
#define DRMP3_REALLOC(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61032
ma_loshelf2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2138
ma_decoding_backend_config_init
MA_API ma_decoding_backend_config ma_decoding_backend_config_init(ma_format preferredFormat)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40635
drwav_seek_proc
drwav_bool32(* drwav_seek_proc)(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39612
MA_OPEN_MODE_WRITE
#define MA_OPEN_MODE_WRITE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4634
MA_DEFAULT_RESAMPLER_LPF_ORDER
#define MA_DEFAULT_RESAMPLER_LPF_ORDER
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:627
ma_dither_f32_triangle
static MA_INLINE float ma_dither_f32_triangle(float ditherMin, float ditherMax)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2526
ma_calculate_buffer_size_in_frames_from_milliseconds
MA_API ma_uint32 ma_calculate_buffer_size_in_frames_from_milliseconds(ma_uint32 bufferSizeInMilliseconds, ma_uint32 sampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27770
ma_device::state
volatile ma_uint32 state
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3589
ma_rand_f32
static MA_INLINE float ma_rand_f32(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2505
ma_decoder_config::speex
struct ma_decoder_config::@122::@124 speex
ma_biquad_process_pcm_frame_s16__direct_form_2_transposed
static MA_INLINE void ma_biquad_process_pcm_frame_s16__direct_form_2_transposed(ma_biquad *pBQ, ma_int16 *pY, const ma_int16 *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30538
ma_device_config_init
MA_API ma_device_config ma_device_config_init(ma_device_type deviceType)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27034
ma_mp3_init_file_w
MA_API ma_result ma_mp3_init_file_w(const wchar_t *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_mp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42348
ma_radians_to_degrees_f
static MA_INLINE float ma_radians_to_degrees_f(float radians)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:854
ma_aaudio_input_preset_unprocessed
@ ma_aaudio_input_preset_unprocessed
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1859
ma_linear_resampler_get_output_latency
MA_API ma_uint64 ma_linear_resampler_get_output_latency(const ma_linear_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33050
drwav__metadata_get_memory
DRWAV_PRIVATE drwav_uint8 * drwav__metadata_get_memory(drwav__metadata_parser *pParser, size_t size, size_t align)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46919
DRWAV_COPY_MEMORY
#define DRWAV_COPY_MEMORY(dst, src, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46294
ma_pcm_rb_get_subbuffer_size
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_size(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36967
ma_biquad::b1
ma_biquad_coefficient b1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1862
ma_decoder::onTell
ma_decoder_tell_proc onTell
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4774
DRFLAC_INVALID_FILE
#define DRFLAC_INVALID_FILE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51367
ma_pcm_deinterleave_s16__reference
static MA_INLINE void ma_pcm_deinterleave_s16__reference(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28731
drwav__pcm_to_f32
DRWAV_PRIVATE void drwav__pcm_to_f32(float *pOut, const drwav_uint8 *pIn, size_t sampleCount, unsigned int bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50133
drmp3_seek_forward_by_pcm_frames__brute_force
static drmp3_bool32 drmp3_seek_forward_by_pcm_frames__brute_force(drmp3 *pMP3, drmp3_uint64 frameOffset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62119
DRFLAC_BAD_PROTOCOL
#define DRFLAC_BAD_PROTOCOL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51396
ma_pcm_f32_to_s16
MA_API void ma_pcm_f32_to_s16(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29989
ma_device_config::noDefaultQualitySRC
ma_bool32 noDefaultQualitySRC
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3145
MA_CHANNEL_MONO
#define MA_CHANNEL_MONO
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1602
ma_aaudio_usage_voice_communication_signalling
@ ma_aaudio_usage_voice_communication_signalling
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1840
drwav::sampleRate
drwav_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_wav.h:831
ma_decoder::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5197
ma_waveform_uninit
MA_API void ma_waveform_uninit(ma_waveform *pWaveform)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45471
ma_device_config::periodSizeInFrames
ma_uint32 periodSizeInFrames
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3104
drflac_init_info::onMeta
drflac_meta_proc onMeta
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54792
ma_pcm_f32_to_u8
MA_API void ma_pcm_f32_to_u8(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29543
drmp3_decode_next_frame_ex__memory
static drmp3_uint32 drmp3_decode_next_frame_ex__memory(drmp3 *pMP3, drmp3d_sample_t *pPCMFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61272
drwav_container
drwav_container
Definition: porcupine/demo/c/dr_libs/dr_wav.h:274
ma_decoder::readPointerInPCMFrames
ma_uint64 readPointerInPCMFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4776
ma_waveform_set_type
MA_API ma_result ma_waveform_set_type(ma_waveform *pWaveform, ma_waveform_type type)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45502
ma_get_format_name
const MA_API char * ma_get_format_name(ma_format format)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37176
drflac_metadata::streaminfo
drflac_streaminfo streaminfo
Definition: porcupine/demo/c/dr_libs/dr_flac.h:429
ma_device::internalFormat
ma_format internalFormat
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3628
drflac_bs::onSeek
drflac_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/dr_flac.h:587
ma_encoding_format_mp3
@ ma_encoding_format_mp3
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4697
MA_INVALID_DEVICE_CONFIG
#define MA_INVALID_DEVICE_CONFIG
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1721
c89atomic_store_explicit_8
#define c89atomic_store_explicit_8(dst, src, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3785
c89atomic_fetch_add_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_fetch_add_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3536
drmp3_L12_scale_info::scfcod
drmp3_uint8 scfcod[64]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59488
ma_default_vfs_seek__stdio
static ma_result ma_default_vfs_seek__stdio(ma_vfs *pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39107
ma_decoder::outputFormat
ma_format outputFormat
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5203
ma_hpf2_reinit
MA_API ma_result ma_hpf2_reinit(const ma_hpf2_config *pConfig, ma_hpf2 *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31361
drflac_int64
signed long long drflac_int64
Definition: porcupine/demo/c/dr_libs/dr_flac.h:258
c89atomic_fetch_and_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_fetch_and_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3653
DRMP3_DEQ_COUNT1
#define DRMP3_DEQ_COUNT1(s)
ma_audio_buffer_ref_seek_to_pcm_frame
MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref *pAudioBufferRef, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38133
ma_context_enumerate_devices
MA_API ma_result ma_context_enumerate_devices(ma_context *pContext, ma_enum_devices_callback_proc callback, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26795
drmp3::dataCapacity
size_t dataCapacity
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:360
drmp3_L3_pow_43
static float drmp3_L3_pow_43(int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59954
MA_NO_MESSAGE
#define MA_NO_MESSAGE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1689
ma_lpf_reinit__internal
static ma_result ma_lpf_reinit__internal(const ma_lpf_config *pConfig, ma_lpf *pLPF, ma_bool32 isNew)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30911
drwav_chunk_header
Definition: porcupine/demo/c/dr_libs/dr_wav.h:281
ma_standard_sample_rate_8000
@ ma_standard_sample_rate_8000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:426
c89atomic_uint32
unsigned int c89atomic_uint32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2577
ma_device_config::speex
struct ma_device_config::@96::@103 speex
MA_LCG_M
#define MA_LCG_M
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2431
ma_decoder_config::channelMixMode
ma_channel_mix_mode channelMixMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5176
drflac_streaminfo::maxFrameSizeInPCMFrames
drflac_uint32 maxFrameSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:401
ma_decoding_backend_uninit__wav
static void ma_decoding_backend_uninit__wav(void *pUserData, ma_data_source *pBackend, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41460
ma_data_source_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4502
drwav_metadata_type_list_labelled_cue_region
@ drwav_metadata_type_list_labelled_cue_region
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39654
ma_resampler_init
MA_API ma_result ma_resampler_init(const ma_resampler_config *pConfig, ma_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33099
drwav__read_smpl_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46960
ma_pcm_interleave_s24
MA_API void ma_pcm_interleave_s24(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29085
MA_COINIT_VALUE
#define MA_COINIT_VALUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:567
ma_rb_available_read
MA_API ma_uint32 ma_rb_available_read(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36740
speex_resampler_set_rate
EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:1084
drwav_open_file_and_read_pcm_frames_s16
DRWAV_API drwav_int16 * drwav_open_file_and_read_pcm_frames_s16(const char *filename, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50882
ma_rb__deconstruct_offset
static MA_INLINE void ma_rb__deconstruct_offset(ma_uint32 encodedOffset, ma_uint32 *pOffsetInBytes, ma_uint32 *pOffsetLoopFlag)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36361
MA_CHANNEL_AUX_25
#define MA_CHANNEL_AUX_25
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1646
ma_decoder__on_seek_memory
static ma_bool32 ma_decoder__on_seek_memory(ma_decoder *pDecoder, ma_int64 byteOffset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43905
ma_mp3_init
MA_API ma_result ma_mp3_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_mp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42278
DRWAV_TOO_BIG
#define DRWAV_TOO_BIG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39522
ma_linear_resampler::lpf
ma_lpf lpf
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2221
ma_channel_converter_process_pcm_frames__simple_shuffle
static ma_result ma_channel_converter_process_pcm_frames__simple_shuffle(ma_channel_converter *pConverter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34105
ma_context_config::tryStartServer
ma_bool32 tryStartServer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3184
ma_opensl_stream_type_alarm
@ ma_opensl_stream_type_alarm
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1806
drmp3_cos
static DRMP3_INLINE double drmp3_cos(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61074
ma_format_unknown
@ ma_format_unknown
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1785
ma_decoder_init_file
MA_API ma_result ma_decoder_init_file(const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44687
ma_aaudio_input_preset_voice_recognition
@ ma_aaudio_input_preset_voice_recognition
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1860
ma_device::id
ma_device_id id
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2641
ma_context::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3216
DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT
#define DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40075
ma_pcm_rb_reset
MA_API void ma_pcm_rb_reset(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36855
drwav__bswap_samples
static DRWAV_INLINE void drwav__bswap_samples(void *pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample, drwav_uint16 format)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46592
drwav_smpl_loop::lastSampleByteOffset
drwav_uint32 lastSampleByteOffset
Definition: porcupine/demo/c/dr_libs/dr_wav.h:529
ma_device::noClip
ma_bool32 noClip
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3604
drflac_subframe::wastedBitsPerSample
drflac_uint8 wastedBitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_flac.h:631
ma_log_postf
MA_API ma_result ma_log_postf(ma_log *pLog, ma_uint32 level, const char *pFormat,...)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2305
drwavGUID_W64_DATA
static const drwav_uint8 drwavGUID_W64_DATA[16]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46391
drwav::onRead
drwav_read_proc onRead
Definition: porcupine/demo/c/dr_libs/dr_wav.h:808
ma_aaudio_input_preset_default
@ ma_aaudio_input_preset_default
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1856
drwav_s32_to_s16
DRWAV_API void drwav_s32_to_s16(drwav_int16 *pOut, const drwav_int32 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50081
drmp3dec_scratch::gr_info
drmp3_L3_gr_info gr_info[4]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59506
DRFLAC_OGG_MAX_PAGE_SIZE
#define DRFLAC_OGG_MAX_PAGE_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55246
ma_dither_mode_none
@ ma_dither_mode_none
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1774
drflac_metadata::seektable
struct drflac_metadata::@0::@3 seektable
drflac__flush_crc16
static DRFLAC_INLINE drflac_uint16 drflac__flush_crc16(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51862
ma_bpf2_config_init
MA_API ma_bpf2_config ma_bpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31626
MA_PROTOCOL_FAMILY_NOT_SUPPORTED
#define MA_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1701
c89atomic_int16
signed short c89atomic_int16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2574
ma_device_audio_thread__default_read_write
static ma_result ma_device_audio_thread__default_read_write(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6034
drmp3_seek_point
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:290
ma_audio_buffer_ref_get_length_in_pcm_frames
MA_API ma_result ma_audio_buffer_ref_get_length_in_pcm_frames(const ma_audio_buffer_ref *pAudioBufferRef, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38225
DRMP3_OFFSET_PTR
#define DRMP3_OFFSET_PTR(p, offset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59332
ma_flac::pReadSeekTellUserData
void * pReadSeekTellUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41505
ma_data_source_base::rangeEndInFrames
ma_uint64 rangeEndInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4530
drflac::currentFLACFrame
drflac_frame currentFLACFrame
Definition: porcupine/demo/c/dr_libs/dr_flac.h:730
ma_notch2_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2077
ma_copy_and_apply_volume_factor_u8
MA_API void ma_copy_and_apply_volume_factor_u8(ma_uint8 *pSamplesOut, const ma_uint8 *pSamplesIn, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27824
ma_pcm_rb::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2596
ma_decoder::onSeek
ma_decoder_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5196
ma_decoding_backend_init__wav
static ma_result ma_decoding_backend_init__wav(void *pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41364
DR_WAVE_FORMAT_ALAW
#define DR_WAVE_FORMAT_ALAW
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39568
ma_decoder_init_file_mp3_w
MA_API ma_result ma_decoder_init_file_mp3_w(const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44729
drwav_guid_equal
DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51080
DRMP3_HDR_IS_LAYER_1
#define DRMP3_HDR_IS_LAYER_1(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59360
drmp3_L3_save_reservoir
static void drmp3_L3_save_reservoir(drmp3dec *h, drmp3dec_scratch *s)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60391
ma_noise::lcg
ma_lcg lcg
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5415
drwav::metadataCount
drwav_uint32 metadataCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:874
drwav_bext::pDescription
char * pDescription
Definition: porcupine/demo/c/dr_libs/dr_wav.h:686
drflac_cuesheet_track::isAudio
drflac_bool8 isAudio
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1298
ma_device_info::formats
ma_format formats[ma_format_count]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3088
ma_get_standard_channel_map_rfc3551
static void ma_get_standard_channel_map_rfc3551(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35758
drwav__is_little_endian
static DRWAV_INLINE int drwav__is_little_endian(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46392
drflac_bs::crc16Cache
drflac_cache_t crc16Cache
Definition: porcupine/demo/c/dr_libs/dr_flac.h:621
DRFLAC_CONNECTION_REFUSED
#define DRFLAC_CONNECTION_REFUSED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51405
drflac_read_pcm_frames_f32__decode_mid_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58480
DRMP3_FREE
#define DRMP3_FREE(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61035
ma_decoder__data_source_on_seek
static ma_result ma_decoder__data_source_on_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43574
ma_rb::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2575
ma_linear_resampler_process_pcm_frames
MA_API ma_result ma_linear_resampler_process_pcm_frames(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32940
c89atomic_uint16
unsigned short c89atomic_uint16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2575
ma_noise_config::duplicateChannels
ma_bool32 duplicateChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5407
ma_vfs_read
MA_API ma_result ma_vfs_read(ma_vfs *pVFS, ma_vfs_file file, void *pDst, size_t sizeInBytes, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38571
drwav__bswap32
static DRWAV_INLINE drwav_uint32 drwav__bswap32(drwav_uint32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46425
drflac__has_neon
static DRFLAC_INLINE drflac_bool32 drflac__has_neon(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51471
drwav_bext::maxTruePeakLevel
drwav_uint16 maxTruePeakLevel
Definition: porcupine/demo/c/dr_libs/dr_wav.h:707
ma_audio_buffer::_pExtraData
ma_uint8 _pExtraData[1]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4602
ma_lpf2_process_pcm_frame_s16
static MA_INLINE void ma_lpf2_process_pcm_frame_s16(ma_lpf2 *pLPF, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30868
ma_loshelf2__get_biquad_config
static MA_INLINE ma_biquad_config ma_loshelf2__get_biquad_config(const ma_loshelf2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32198
ma_aaudio_usage_assitant
@ ma_aaudio_usage_assitant
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1833
ma_peak2_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2096
ma_wav_init_file
MA_API ma_result ma_wav_init_file(const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_wav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41044
ma_pcm_s24_to_u8
MA_API void ma_pcm_s24_to_u8(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28815
ma_lpf1::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1895
ma_standard_channel_map_sound4
@ ma_standard_channel_map_sound4
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1810
drflac::seekpointCount
drflac_uint32 seekpointCount
Definition: porcupine/demo/c/dr_libs/dr_flac.h:726
drflac__read_uint16
static drflac_bool32 drflac__read_uint16(drflac_bs *bs, unsigned int bitCount, drflac_uint16 *pResult)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52046
ma_standard_channel_map_alsa
@ ma_standard_channel_map_alsa
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1806
drflac_read_pcm_frames_s16
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s16(drflac *pFlac, drflac_uint64 framesToRead, drflac_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58123
ma_channel_converter_uninit
MA_API void ma_channel_converter_uninit(ma_channel_converter *pConverter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34088
ma_decoding_backend_init_file__mp3
static ma_result ma_decoding_backend_init_file__mp3(void *pUserData, const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42652
drflac::container
drflac_container container
Definition: porcupine/demo/c/dr_libs/dr_flac.h:723
MA_CHANNEL_BACK_CENTER
#define MA_CHANNEL_BACK_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1611
DRWAV_UNAVAILABLE
#define DRWAV_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39533
ma_linear_resampler_mix_s16
static MA_INLINE ma_int16 ma_linear_resampler_mix_s16(ma_int16 x, ma_int16 y, ma_int32 a, const ma_int32 shift)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32567
ma_rand_range_f32
static MA_INLINE float ma_rand_range_f32(float lo, float hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2510
ma_aaudio_usage
ma_aaudio_usage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1822
drmp3__malloc_default
static void * drmp3__malloc_default(size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61078
device
ma_device device
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_deviceio/ma_test_deviceio.c:57
MA_CHANNEL_AUX_3
#define MA_CHANNEL_AUX_3
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1624
f
f
ma_lpf1_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1890
drwavGUID_W64_FMT
static const drwav_uint8 drwavGUID_W64_FMT[16]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46389
drwav_acid_flag_one_shot
@ drwav_acid_flag_one_shot
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39734
ma_decoder_init_file_vorbis_w
MA_API ma_result ma_decoder_init_file_vorbis_w(const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44734
ma_channel_mix_mode_simple
@ ma_channel_mix_mode_simple
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1797
drwav_init_memory_write__internal
DRWAV_PRIVATE drwav_bool32 drwav_init_memory_write__internal(drwav *pWav, void **ppData, size_t *pDataSize, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49184
ma_default_vfs::cb
ma_vfs_callbacks cb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4672
ma_log::callbackCount
ma_uint32 callbackCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:591
drwav__mulaw_to_s16
static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49858
drmp3_L3_gr_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59494
DRFLAC_FALSE
#define DRFLAC_FALSE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40016
ma_wav_ds_get_data_format
static ma_result ma_wav_ds_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40893
DRWAV_AT_END
#define DRWAV_AT_END
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39564
drflac__init_cpu_caps
static DRFLAC_NO_THREAD_SANITIZE void drflac__init_cpu_caps(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51487
drwav__metadata_parser
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46898
drwav_read_pcm_frames_f32le
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50336
MA_CHANNEL_SIDE_RIGHT
#define MA_CHANNEL_SIDE_RIGHT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1613
drwav__on_read
DRWAV_PRIVATE size_t drwav__on_read(drwav_read_proc onRead, void *pUserData, void *pBufferOut, size_t bytesToRead, drwav_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46853
c89atomic_flag_test_and_set_explicit
#define c89atomic_flag_test_and_set_explicit(ptr, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3798
drwav_read_pcm_frames_s32__ima
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ima(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50528
ma_waveform_init
MA_API ma_result ma_waveform_init(const ma_waveform_config *pConfig, ma_waveform *pWaveform)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45445
ma_default_vfs
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4670
ma_pcm_interleave_f32__reference
static void ma_pcm_interleave_f32__reference(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30176
ma_is_spatial_channel_position
static ma_bool32 ma_is_spatial_channel_position(ma_channel channelPosition)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33758
MA_PI_D
#define MA_PI_D
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:584
ma_duplex_rb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1447
MA_INTERRUPT
#define MA_INTERRUPT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1680
DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED
#define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40450
drmp3_result_from_errno
static drmp3_result drmp3_result_from_errno(int e)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61405
ma_backend_callbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2122
drmp3_open_and_read_pcm_frames_f32
DRMP3_API float * drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void *pUserData, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62491
ma_calculate_frame_count_after_resampling
MA_API ma_uint64 ma_calculate_frame_count_after_resampling(ma_uint32 sampleRateOut, ma_uint32 sampleRateIn, ma_uint64 frameCountIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4201
DRMP3_HDR_TEST_PADDING
#define DRMP3_HDR_TEST_PADDING(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59348
ma_lpf1::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1896
ma_hpf2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1976
DRFLAC_MAX_SIMD_VECTOR_SIZE
#define DRFLAC_MAX_SIMD_VECTOR_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51355
ma_peak2_config::gainDB
double gainDB
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2105
drwav_write_proc
size_t(* drwav_write_proc)(void *pUserData, const void *pData, size_t bytesToWrite)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39611
ma_decoder_init_memory_wav
MA_API ma_result ma_decoder_init_memory_wav(const void *pData, size_t dataSize, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43992
drflac_ogg_page_header::segmentCount
drflac_uint8 segmentCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54784
c89atomic_spinlock
c89atomic_flag c89atomic_spinlock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4178
ma_flac_read_pcm_frames
MA_API ma_result ma_flac_read_pcm_frames(ma_flac *pFlac, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41797
g_ma_flac_ds_vtable
static ma_data_source_vtable g_ma_flac_ds_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41549
ma_scale_to_range_f32
static MA_INLINE float ma_scale_to_range_f32(float x, float lo, float hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2393
ma_decoding_backend_vtable::onGetChannelMap
ma_result(* onGetChannelMap)(void *pUserData, ma_data_source *pBackend, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4730
drmp3_init_file_w
DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3 *pMP3, const wchar_t *pFilePath, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61931
ma_mp3_read_pcm_frames
MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3 *pMP3, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42433
drmp3dec
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:262
ma_rb__extract_offset_loop_flag
static MA_INLINE ma_uint32 ma_rb__extract_offset_loop_flag(ma_uint32 encodedOffset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36339
ma_hpf1_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1957
ma_audio_buffer_config::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4588
ma_data_converter_config_init
MA_API ma_data_converter_config ma_data_converter_config_init(ma_format formatIn, ma_format formatOut, ma_uint32 channelsIn, ma_uint32 channelsOut, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34530
drflac__read_int8
static drflac_bool32 drflac__read_int8(drflac_bs *bs, unsigned int bitCount, drflac_int8 *pResult)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52087
c89atomic_compare_exchange_strong_explicit_8
c89atomic_bool c89atomic_compare_exchange_strong_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 *expected, c89atomic_uint8 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3804
drflac__malloc_from_callbacks
static void * drflac__malloc_from_callbacks(size_t sz, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54876
ma_pcm_deinterleave_f32__optimized
static void ma_pcm_deinterleave_f32__optimized(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30219
DRFLAC_NO_SPACE
#define DRFLAC_NO_SPACE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51375
DRFLAC_BAD_SEEK
#define DRFLAC_BAD_SEEK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51382
drflac_init_info::pUserData
void * pUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54794
drflac_ogg_page_header::sequenceNumber
drflac_uint32 sequenceNumber
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54782
ma_enum_devices_callback_proc
ma_bool32(* ma_enum_devices_callback_proc)(ma_context *pContext, ma_device_type deviceType, const ma_device_info *pInfo, void *pUserData)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3208
drflac_init_info::totalPCMFrameCount
drflac_uint64 totalPCMFrameCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54799
ma_decoder_get_available_frames
MA_API ma_result ma_decoder_get_available_frames(ma_decoder *pDecoder, ma_uint64 *pAvailableFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44936
ma_bpf_init
MA_API ma_result ma_bpf_init(const ma_bpf_config *pConfig, ma_bpf *pBPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31833
DRWAV_ALREADY_CONNECTED
#define DRWAV_ALREADY_CONNECTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39557
drwav_acid_flag_root_note_set
@ drwav_acid_flag_root_note_set
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39735
drwav_read_pcm_frames_s16__ima
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav *pWav, drwav_uint64 samplesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49697
g_maFormatPriorities
static ma_format g_maFormatPriorities[]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:676
drmp3_uint32
unsigned int drmp3_uint32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40351
ma_mp3_get_data_format
MA_API ma_result ma_mp3_get_data_format(ma_mp3 *pMP3, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42524
DRWAV_IS_DIRECTORY
#define DRWAV_IS_DIRECTORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39526
ma_waveform__data_source_on_read
static ma_result ma_waveform__data_source_on_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45384
drwav_read_pcm_frames_s16
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50013
drwav_bytes_to_u32
DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51053
drwav__read_chunk_header
DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void *pUserData, drwav_container container, drwav_uint64 *pRunningBytesReadOut, drwav_chunk_header *pHeaderOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46706
ma_loshelf2_config::gainDB
double gainDB
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2133
drmp3__on_read_stdio
static size_t drmp3__on_read_stdio(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61909
ma_speex_resampler_get_expected_output_frame_count
int ma_speex_resampler_get_expected_output_frame_count(SpeexResamplerState *st, spx_uint64_t in_len, spx_uint64_t *out_len)
drwav__read_pcm_frames_and_close_s16
DRWAV_PRIVATE drwav_int16 * drwav__read_pcm_frames_and_close_s16(drwav *pWav, unsigned int *channels, unsigned int *sampleRate, drwav_uint64 *totalFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50728
drmp3_L3_decode_scalefactors
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59892
ma_device::startEvent
ma_event startEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3595
ma_waveform::advance
double advance
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5376
ma_bpf::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2053
ma_context_config::sessionCategoryOptions
ma_uint32 sessionCategoryOptions
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3179
DRMP3_CHECK_BITS
#define DRMP3_CHECK_BITS
ma_apply_volume_factor_s24
MA_API void ma_apply_volume_factor_s24(void *pSamples, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27911
c89atomic_compare_and_swap_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_compare_and_swap_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 expected, c89atomic_uint64 desired)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3473
c89atomic_compare_exchange_strong_explicit_32
c89atomic_bool c89atomic_compare_exchange_strong_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 *expected, c89atomic_uint32 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3838
ma_stream_layout
ma_stream_layout
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1766
ma_waveform_type_sawtooth
@ ma_waveform_type_sawtooth
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5362
ma_decoder::outputChannelMap
ma_channel outputChannelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5206
ma_decoder_init_file_vorbis
MA_API ma_result ma_decoder_init_file_vorbis(const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44707
drflac_open_and_read_pcm_frames_s16
DRFLAC_API drflac_int16 * drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void *pUserData, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59081
ma_aaudio_content_type_music
@ ma_aaudio_content_type_music
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1848
drflac_oggbs::currentBytePos
drflac_uint64 currentBytePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55445
DRWAV_NO_HOST
#define DRWAV_NO_HOST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39560
drwav_allocation_callbacks::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_wav.h:411
ma_semaphore_init__posix
static ma_result ma_semaphore_init__posix(int initialValue, ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4617
drwav__write_or_count_metadata
DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav *pWav, drwav_metadata *pMetadatas, drwav_uint32 metadataCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47934
drmp3::mp3FrameChannels
drmp3_uint32 mp3FrameChannels
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:350
drflac_ogg_page_header::checksum
drflac_uint32 checksum
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54783
ma_allocation_callbacks::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1825
drflac::_noBinarySearchSeek
drflac_bool32 _noBinarySearchSeek
Definition: porcupine/demo/c/dr_libs/dr_flac.h:755
ma_linear_resampler_process_pcm_frames_f32_upsample
static ma_result ma_linear_resampler_process_pcm_frames_f32_upsample(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32854
ma_powd
static MA_INLINE double ma_powd(double x, double y)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:805
drflac_uintptr
drflac_uint32 drflac_uintptr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40011
ma_peak2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2108
stb_vorbis_open_memory
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc_buffer)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:5073
ma_lcg_rand_range_f32
static MA_INLINE float ma_lcg_rand_range_f32(ma_lcg *pLCG, float lo, float hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2469
drwav_unknown_metadata::pData
drwav_uint8 * pData
Definition: porcupine/demo/c/dr_libs/dr_wav.h:780
ma_default_vfs_close__stdio
static ma_result ma_default_vfs_close__stdio(ma_vfs *pVFS, ma_vfs_file file)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39048
ma_pcm_rb_seek_write
MA_API ma_result ma_pcm_rb_seek_write(ma_pcm_rb *pRB, ma_uint32 offsetInFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36931
ma_log_lock
static void ma_log_lock(ma_log *pLog)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2043
drflac_read_pcm_frames_s16__decode_mid_side
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57989
ma_pcm_rb_seek_read
MA_API ma_result ma_pcm_rb_seek_read(ma_pcm_rb *pRB, ma_uint32 offsetInFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36922
MA_CHANNEL_AUX_13
#define MA_CHANNEL_AUX_13
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1634
ma_clip_samples_f32
MA_API void ma_clip_samples_f32(float *p, ma_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27813
ma_channel_converter_process_pcm_frames__weights
static ma_result ma_channel_converter_process_pcm_frames__weights(ma_channel_converter *pConverter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34371
drwav_init_file_w
DRWAV_API drwav_bool32 drwav_init_file_w(drwav *pWav, const wchar_t *filename, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48971
ma_max
#define ma_max(x, y)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:777
drflac_ogg_recover_on_crc_mismatch
@ drflac_ogg_recover_on_crc_mismatch
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55250
ma_next_power_of_2
static MA_INLINE unsigned int ma_next_power_of_2(unsigned int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1773
MA_FAILED_TO_START_BACKEND_DEVICE
#define MA_FAILED_TO_START_BACKEND_DEVICE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1732
g_ma_decoder_data_source_vtable
static ma_data_source_vtable g_ma_decoder_data_source_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43609
drwav_inst::lowNote
drwav_int8 lowNote
Definition: porcupine/demo/c/dr_libs/dr_wav.h:578
drwav_int32
signed int drwav_int32
Definition: porcupine/demo/c/dr_libs/dr_wav.h:138
drflac_subframe
Definition: porcupine/demo/c/dr_libs/dr_flac.h:625
drmp3_uintptr
drmp3_uint32 drmp3_uintptr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40372
MA_NO_NETWORK
#define MA_NO_NETWORK
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1694
ma_standard_channel_map_vorbis
@ ma_standard_channel_map_vorbis
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1809
DRWAV_ZERO_MEMORY
#define DRWAV_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46297
MA_BAD_PROTOCOL
#define MA_BAD_PROTOCOL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1698
drflac_read_pcm_frames_f32__decode_independent_stereo
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58831
DRWAV_SOCKET_NOT_SUPPORTED
#define DRWAV_SOCKET_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39555
drwav_open_memory_and_read_pcm_frames_f32
DRWAV_API float * drwav_open_memory_and_read_pcm_frames_f32(const void *data, size_t dataSize, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51002
drwav_bytes_to_f32
DRWAV_API float drwav_bytes_to_f32(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51057
drmp3d_synth_pair
static void drmp3d_synth_pair(drmp3d_sample_t *pcm, int nch, const float *z)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60619
drmp3_free
DRMP3_API void drmp3_free(void *p, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62549
ma_resampler
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2260
ma_resampler_get_expected_output_frame_count
MA_API ma_uint64 ma_resampler_get_expected_output_frame_count(const ma_resampler *pResampler, ma_uint64 inputFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33520
stb_vorbis_get_samples_float_interleaved
int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:5399
drflac_read_pcm_frames_f32__decode_independent_stereo__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58740
ma_decoding_backend_init_memory__wav
static ma_result ma_decoding_backend_init_memory__wav(void *pUserData, const void *pData, size_t dataSize, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41436
drflac_read_pcm_frames_s32__decode_left_side
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56893
ma_timer_get_time_in_seconds
static double ma_timer_get_time_in_seconds(ma_timer *pTimer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5558
ma_spinlock_lock_noyield
MA_API ma_result ma_spinlock_lock_noyield(volatile ma_spinlock *pSpinlock)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4296
ma_decoder_init_wav__internal
static ma_result ma_decoder_init_wav__internal(const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41489
ma_duplex_rb_init
MA_API ma_result ma_duplex_rb_init(ma_format captureFormat, ma_uint32 captureChannels, ma_uint32 sampleRate, ma_uint32 captureInternalSampleRate, ma_uint32 captureInternalPeriodSizeInFrames, const ma_allocation_callbacks *pAllocationCallbacks, ma_duplex_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37005
DRWAV_DEADLOCK
#define DRWAV_DEADLOCK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39538
DRFLAC_TOO_MANY_LINKS
#define DRFLAC_TOO_MANY_LINKS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51385
ma_audio_buffer_init_ex
static ma_result ma_audio_buffer_init_ex(const ma_audio_buffer_config *pConfig, ma_bool32 doCopy, ma_audio_buffer *pAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38280
drflac_cuesheet_track_index::offset
drflac_uint64 offset
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1287
ma_path_file_name
static const char * ma_path_file_name(const char *path)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44075
DRFLAC_NO_NETWORK
#define DRFLAC_NO_NETWORK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51392
DRWAV_CONNECTION_RESET
#define DRWAV_CONNECTION_RESET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39556
c89atomic_memory_order
int c89atomic_memory_order
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2595
drmp3__on_seek_memory
static drmp3_bool32 drmp3__on_seek_memory(void *pUserData, int byteOffset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61363
ma_aaudio_usage_assistance_navigation_guidance
@ ma_aaudio_usage_assistance_navigation_guidance
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1831
ma_device_config::capture
struct ma_device_config::@98 capture
MA_LOG_LEVEL_INFO
#define MA_LOG_LEVEL_INFO
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1589
drmp3_L3_stereo_top_band
static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3])
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60130
DRMP3_NOT_IMPLEMENTED
#define DRMP3_NOT_IMPLEMENTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40436
drwav_open_memory_and_read_pcm_frames_s16
DRWAV_API drwav_int16 * drwav_open_memory_and_read_pcm_frames_s16(const void *data, size_t dataSize, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50985
drflac_frame_header
Definition: porcupine/demo/c/dr_libs/dr_flac.h:640
DRMP3_ASSERT
#define DRMP3_ASSERT(expression)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61019
drmp3::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:348
ma_scale_buffer_size
MA_API ma_uint32 ma_scale_buffer_size(ma_uint32 baseBufferSize, float scale)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27755
ma_thread_priority
ma_thread_priority
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2812
drwav_metadata_location_inside_info_list
@ drwav_metadata_location_inside_info_list
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39796
ma_mutex_unlock
MA_API void ma_mutex_unlock(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4813
g_drmp3_pow43
static const float g_drmp3_pow43[129+16]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59950
ma_device_config::performanceProfile
ma_performance_profile performanceProfile
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3107
ma_lpf::lpf2
ma_lpf2 lpf2[MA_MAX_FILTER_ORDER/2]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1935
MA_PATH_TOO_LONG
#define MA_PATH_TOO_LONG
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1671
ma_resampler::config
ma_resampler_config config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2262
ma_aaudio_content_type
ma_aaudio_content_type
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1844
drmp3_L12_scale_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59485
ma_noise_s16_brownian
static MA_INLINE ma_int16 ma_noise_s16_brownian(ma_noise *pNoise, ma_uint32 iChannel)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46159
ma_path_extension
static const char * ma_path_extension(const char *path)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44130
ma_decoder__on_read_memory
static size_t ma_decoder__on_read_memory(ma_decoder *pDecoder, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43886
drmp3_seek_origin_start
@ drmp3_seek_origin_start
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40493
drwav_metadata::cue
drwav_cue cue
Definition: porcupine/demo/c/dr_libs/dr_wav.h:793
ma_biquad_coefficient::f32
float f32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1843
ma_lpf1::a
ma_biquad_coefficient a
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1897
ma_linear_resampler_set_rate_internal
static ma_result ma_linear_resampler_set_rate_internal(ma_linear_resampler *pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_bool32 isResamplerAlreadyInitialized)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32467
ma_device::shareMode
ma_share_mode shareMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3621
MA_COPY_MEMORY
#define MA_COPY_MEMORY(dst, src, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:754
drflac_open_with_metadata_relaxed
DRFLAC_API drflac * drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56759
drmp3::sampleRate
drmp3_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:345
drflac_init_info::sampleRate
drflac_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54796
ma_decoder_init_memory_flac
MA_API ma_result ma_decoder_init_memory_flac(const void *pData, size_t dataSize, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44010
ma_semaphore::value
int value
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:533
ma_device_config::channelMixMode
ma_channel_mix_mode channelMixMode
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1968
ma_context_init
MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config *pConfig, ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26550
drwav_fmt::channels
drwav_uint16 channels
Definition: porcupine/demo/c/dr_libs/dr_wav.h:308
drwav_write_pcm_frames
DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav *pWav, drwav_uint64 framesToWrite, const void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49558
drwav_uint8
unsigned char drwav_uint8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39451
ma_channel_converter::s16
ma_int32 s16[MA_MAX_CHANNELS][MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2378
drmp3_L3_ldexp_q2
static float drmp3_L3_ldexp_q2(float y, int exp_q2)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59881
MA_CHANNEL_AUX_1
#define MA_CHANNEL_AUX_1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1622
drwav_copy_allocation_callbacks_or_defaults
DRWAV_PRIVATE drwav_allocation_callbacks drwav_copy_allocation_callbacks_or_defaults(const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46676
ma_flac_dr_callback__seek
static drflac_bool32 ma_flac_dr_callback__seek(void *pUserData, int offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41595
drwav_metadata_type_list_info_comment
@ drwav_metadata_type_list_info_comment
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39659
python.setup.name
name
Definition: porcupine/binding/python/setup.py:69
DRWAV_BEXT_ORIGINATOR_NAME_BYTES
#define DRWAV_BEXT_ORIGINATOR_NAME_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46885
drwav__write_or_count
DRWAV_PRIVATE size_t drwav__write_or_count(drwav *pWav, const void *pData, size_t dataSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47874
drflac__swap_endian_uint64
static DRFLAC_INLINE drflac_uint64 drflac__swap_endian_uint64(drflac_uint64 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51554
ma_noise_type_pink
@ ma_noise_type_pink
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5396
ma_bpf2_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2027
drwav_smpl::manufacturerId
drwav_uint32 manufacturerId
Definition: porcupine/demo/c/dr_libs/dr_wav.h:541
drwav__seek_from_start
DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46751
drwav_metadata_type
drwav_metadata_type
Definition: porcupine/demo/c/dr_libs/dr_wav.h:444
ma_log_callback::onLog
ma_log_callback_proc onLog
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:581
drflac_init_info::container
drflac_container container
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54793
ma_resampler_config::linear
struct ma_resampler_config::@75 linear
ma_device_get_context
MA_API ma_context * ma_device_get_context(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27471
ma_vfs_write
MA_API ma_result ma_vfs_write(ma_vfs *pVFS, ma_vfs_file file, const void *pSrc, size_t sizeInBytes, size_t *pBytesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38590
drflac_uint16
unsigned short drflac_uint16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39988
DRMP3_COUNTOF
#define DRMP3_COUNTOF(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61037
drwav__on_seek_memory
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49077
ma_hpf1_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1959
ma_opensl_stream_type
ma_opensl_stream_type
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1799
ma_lcg_rand_range_s32
static MA_INLINE ma_int32 ma_lcg_rand_range_s32(ma_lcg *pLCG, ma_int32 lo, ma_int32 hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2474
DRWAV_FALSE
#define DRWAV_FALSE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39481
ma_waveform_set_sample_rate
MA_API ma_result ma_waveform_set_sample_rate(ma_waveform *pWaveform, ma_uint32 sampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45512
drwav_metadata_type_list_info_date
@ drwav_metadata_type_list_info_date
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39660
ma_path_extension_w
static const wchar_t * ma_path_extension_w(const wchar_t *path)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44155
ma_thread_proxy_data::entryProc
ma_thread_entry_proc entryProc
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4690
ma_encoder_init__internal
MA_API ma_result ma_encoder_init__internal(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void *pUserData, ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45224
ma_pcm_rb_commit_read
MA_API ma_result ma_pcm_rb_commit_read(ma_pcm_rb *pRB, ma_uint32 sizeInFrames, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36884
drflac__read_next_flac_frame_header
static drflac_bool32 drflac__read_next_flac_frame_header(drflac_bs *bs, drflac_uint8 streaminfoBitsPerSample, drflac_frame_header *header)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53981
drflac__reset_cache
static void drflac__reset_cache(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51940
drflac_read_pcm_frames_f32__decode_mid_side
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58712
ma_decoder::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5217
ma_audio_buffer_get_length_in_pcm_frames
MA_API ma_result ma_audio_buffer_get_length_in_pcm_frames(const ma_audio_buffer *pAudioBuffer, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38483
DRMP3_BAD_ADDRESS
#define DRMP3_BAD_ADDRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40431
DRFLAC_OUT_OF_MEMORY
#define DRFLAC_OUT_OF_MEMORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51361
ma_vfs_callbacks::onTell
ma_result(* onTell)(ma_vfs *pVFS, ma_vfs_file file, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4656
drmp3_init_memory
DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3 *pMP3, const void *pData, size_t dataSize, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61387
drflac_cache_t
drflac_uint32 drflac_cache_t
Definition: porcupine/demo/c/dr_libs/dr_flac.h:337
DRMP3_NO_SPACE
#define DRMP3_NO_SPACE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40425
drwav_fmt::extendedSize
drwav_uint16 extendedSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:323
ma_hpf2_init
MA_API ma_result ma_hpf2_init(const ma_hpf2_config *pConfig, ma_hpf2 *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31337
drwav_init_memory_write_sequential_pcm_frames
DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav *pWav, void **ppData, size_t *pDataSize, const drwav_data_format *pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49209
drflac_has_sse2
static DRFLAC_INLINE drflac_bool32 drflac_has_sse2(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51228
drwav::dataChunkDataSize
drwav_uint64 dataChunkDataSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:847
ma_get_backend_name
const MA_API char * ma_get_backend_name(ma_backend backend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5055
ma_backend_dsound
@ ma_backend_dsound
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2796
ma_loshelf2_process_pcm_frames
MA_API ma_result ma_loshelf2_process_pcm_frames(ma_loshelf2 *pFilter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32284
ma_notch2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2075
ma_stream_layout_interleaved
@ ma_stream_layout_interleaved
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1768
MA_CHANNEL_AUX_27
#define MA_CHANNEL_AUX_27
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1648
DRWAV_SUCCESS
#define DRWAV_SUCCESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39511
drmp3_hdr_compare
static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59539
ma_linear_resampler::inAdvanceFrac
ma_uint32 inAdvanceFrac
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2208
ma_device_info::maxChannels
ma_uint32 maxChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3090
MA_MEMORY_ALREADY_MAPPED
#define MA_MEMORY_ALREADY_MAPPED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1711
ma_channel_converter::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2369
ma_hpf2_process_pcm_frame_f32
static MA_INLINE void ma_hpf2_process_pcm_frame_f32(ma_hpf2 *pHPF, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31384
c89atomic_exchange_explicit_f32
static C89ATOMIC_INLINE float c89atomic_exchange_explicit_f32(volatile float *dst, float src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4154
DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED
#define DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51399
drwav_metadata_location
drwav_metadata_location
Definition: porcupine/demo/c/dr_libs/dr_wav.h:767
ma_mutex_unlock__posix
static void ma_mutex_unlock__posix(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4559
ma_decoder_init_file_mp3
MA_API ma_result ma_decoder_init_file_mp3(const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44702
ma_linear_resampler_config::lpfOrder
ma_uint32 lpfOrder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2211
ma_encoder_write_pcm_frames
MA_API ma_uint64 ma_encoder_write_pcm_frames(ma_encoder *pEncoder, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45351
MA_CHANNEL_AUX_23
#define MA_CHANNEL_AUX_23
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1644
ma_linear_resampler
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2204
DRMP3_MIN_DATA_CHUNK_SIZE
#define DRMP3_MIN_DATA_CHUNK_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61013
ma_path_file_name_w
static const wchar_t * ma_path_file_name_w(const wchar_t *path)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44102
ma_pcm_sample_u8_to_s16_no_scale
static MA_INLINE ma_int16 ma_pcm_sample_u8_to_s16_no_scale(ma_uint8 x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28017
DRFLAC_SUBFRAME_LPC
#define DRFLAC_SUBFRAME_LPC
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51415
drmp3_L12_scale_info::stereo_bands
drmp3_uint8 stereo_bands
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59488
ma_encoder__on_write_pcm_frames_wav
static ma_uint64 ma_encoder__on_write_pcm_frames_wav(ma_encoder *pEncoder, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45170
ma_result
int ma_result
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1658
ma_device__on_data
static void ma_device__on_data(ma_device *pDevice, void *pFramesOut, const void *pFramesIn, ma_uint32 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5685
ma_flac_get_length_in_pcm_frames
MA_API ma_result ma_flac_get_length_in_pcm_frames(ma_flac *pFlac, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41968
ma_audio_buffer_ref_get_cursor_in_pcm_frames
MA_API ma_result ma_audio_buffer_ref_get_cursor_in_pcm_frames(const ma_audio_buffer_ref *pAudioBufferRef, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38208
ma_wav::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40860
MA_CHANNEL_LEFT
#define MA_CHANNEL_LEFT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1653
drwav__write
DRWAV_PRIVATE size_t drwav__write(drwav *pWav, const void *pData, size_t dataSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47821
ma_pcm_rb_get_subbuffer_ptr
MA_API void * ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb *pRB, ma_uint32 subbufferIndex, void *pBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36994
ma_loshelf2_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2132
ma_device_config::noPreZeroedOutputBuffer
ma_bool32 noPreZeroedOutputBuffer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3108
ma_lpf2_process_pcm_frame_f32
static MA_INLINE void ma_lpf2_process_pcm_frame_f32(ma_lpf2 *pLPF, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30873
ma_context::callbacks
ma_backend_callbacks callbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2199
ma_bpf2_reinit
MA_API ma_result ma_bpf2_reinit(const ma_bpf2_config *pConfig, ma_bpf2 *pBPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31700
drwav_bext::timeReference
drwav_uint64 timeReference
Definition: porcupine/demo/c/dr_libs/dr_wav.h:691
ma_lcg_seed
static MA_INLINE void ma_lcg_seed(ma_lcg *pLCG, ma_int32 seed)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2437
drflac_int16
signed short drflac_int16
Definition: porcupine/demo/c/dr_libs/dr_flac.h:243
ma_data_converter::hasChannelConverter
ma_bool32 hasChannelConverter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2436
drmp3::pData
drmp3_uint8 * pData
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:362
drmp3_bs
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59480
ma_decoder__preinit_memory
static ma_result ma_decoder__preinit_memory(const void *pData, size_t dataSize, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43958
drflac_ogg_page_header::headerType
drflac_uint8 headerType
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54779
drwav_seek_origin_current
@ drwav_seek_origin_current
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39578
ma_device_info::id
ma_device_id id
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3076
MA_CHANNEL_AUX_19
#define MA_CHANNEL_AUX_19
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1640
ma_mp3_get_length_in_pcm_frames
MA_API ma_result ma_mp3_get_length_in_pcm_frames(ma_mp3 *pMP3, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42600
ma_vfs_or_default_close
MA_API ma_result ma_vfs_or_default_close(ma_vfs *pVFS, ma_vfs_file file)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39375
ma_pcm_rb_get_bpf
static MA_INLINE ma_uint32 ma_pcm_rb_get_bpf(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36807
drflac_frame_header::pcmFrameNumber
drflac_uint64 pcmFrameNumber
Definition: porcupine/demo/c/dr_libs/dr_flac.h:646
ma_hishelf2_reinit
MA_API ma_result ma_hishelf2_reinit(const ma_hishelf2_config *pConfig, ma_hishelf2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32382
ma_context::threadStackSize
size_t threadStackSize
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2205
ma_lcg::state
ma_int32 state
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5390
ma_deinterleave_pcm_frames
MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void *pInterleavedPCMFrames, void **ppDeinterleavedPCMFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30312
drmp3_bs_get_bits
static drmp3_uint32 drmp3_bs_get_bits(drmp3_bs *bs, int n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59516
ma_biquad
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1857
ma_linear_resampler_uninit
MA_API void ma_linear_resampler_uninit(ma_linear_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32560
ma_decoder_config_init
MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint32 outputChannels, ma_uint32 outputSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40646
drflac_read_pcm_frames_s16__decode_right_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57614
ma_default_vfs_info__stdio
static ma_result ma_default_vfs_info__stdio(ma_vfs *pVFS, ma_vfs_file file, ma_file_info *pInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39173
ma_decoder_init_mp3__internal
static ma_result ma_decoder_init_mp3__internal(const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42753
ma_worker_thread
static ma_thread_result MA_THREADCALL ma_worker_thread(void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26273
drflac_bool8
drflac_uint8 drflac_bool8
Definition: porcupine/demo/c/dr_libs/dr_flac.h:269
ma_linear_resampler_get_input_latency
MA_API ma_uint64 ma_linear_resampler_get_input_latency(const ma_linear_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33041
drwav__bswap_f32
static DRWAV_INLINE float drwav__bswap_f32(float n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46512
drflac__seek_to_pcm_frame__seek_table
static drflac_bool32 drflac__seek_to_pcm_frame__seek_table(drflac *pFlac, drflac_uint64 pcmFrameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54660
drwav_alaw_to_f32
DRWAV_API void drwav_alaw_to_f32(float *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50416
drwav_metadata::inst
drwav_inst inst
Definition: porcupine/demo/c/dr_libs/dr_wav.h:796
ma_peak2_config_init
MA_API ma_peak2_config ma_peak2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32054
ma_linear_resampler_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2208
drwav_bool32
drwav_uint32 drwav_bool32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39479
drmp3d_synth_granule
static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, drmp3d_sample_t *pcm, float *lins)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60782
drwav_fmt
Definition: porcupine/demo/c/dr_libs/dr_wav.h:299
ma_encoder__internal_on_write_wav
static size_t ma_encoder__internal_on_write_wav(void *pUserData, const void *pData, size_t bytesToWrite)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45104
ma_opensl_recording_preset_default
@ ma_opensl_recording_preset_default
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1813
c89atomic_fetch_add_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_fetch_add_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3547
ma_data_source_seek_pcm_frames
MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source *pDataSource, ma_uint64 frameCount, ma_uint64 *pFramesSeeked, ma_bool32 loop)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37544
ma_bpf2_init
MA_API ma_result ma_bpf2_init(const ma_bpf2_config *pConfig, ma_bpf2 *pBPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31676
drmp3__on_read
static size_t drmp3__on_read(drmp3 *pMP3, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61150
ma_default_vfs_open_w
static ma_result ma_default_vfs_open_w(ma_vfs *pVFS, const wchar_t *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39219
drwav_fourcc_equal
DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8 *a, const char *b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51090
drwav_init_file_write_sequential_w
DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav *pWav, const wchar_t *filename, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49049
c89atomic_compare_exchange_strong_explicit_ptr
static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_ptr(volatile void **dst, volatile void **expected, void *desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3923
MA_BAD_PIPE
#define MA_BAD_PIPE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1685
drmp3::memory
struct drmp3::@7 memory
ma_event::cond
pthread_cond_t cond
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:523
drwav__metadata_parser::onRead
drwav_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46900
ma_channel_converter::isPassthrough
ma_bool32 isPassthrough
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2380
ma_data_source_get_cursor_in_pcm_frames
MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37655
MA_DEVICE_NOT_INITIALIZED
#define MA_DEVICE_NOT_INITIALIZED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1724
drflac_crc8_byte
static DRFLAC_INLINE drflac_uint8 drflac_crc8_byte(drflac_uint8 crc, drflac_uint8 data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51666
drflac_seek_origin
drflac_seek_origin
Definition: porcupine/demo/c/dr_libs/dr_flac.h:380
ma_data_converter_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2397
drwav_list_labelled_cue_region::pString
char * pString
Definition: porcupine/demo/c/dr_libs/dr_wav.h:755
drflac_allocation_callbacks::onRealloc
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_flac.h:568
ma_event_init__posix
static ma_result ma_event_init__posix(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4565
ma_noise__data_source_on_read
static ma_result ma_noise__data_source_on_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45820
ma_standard_sample_rate_min
@ ma_standard_sample_rate_min
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:431
ma_device_info::formatCount
ma_uint32 formatCount
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3087
ma_dither_s32
static MA_INLINE ma_int32 ma_dither_s32(ma_dither_mode ditherMode, ma_int32 ditherMin, ma_int32 ditherMax)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2545
drflac_cuesheet_track_iterator
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1277
ma_offset_ptr
#define ma_offset_ptr(p, offset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:781
MA_IN_PROGRESS
#define MA_IN_PROGRESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1709
drflac__decode_samples__verbatim
static drflac_bool32 drflac__decode_samples__verbatim(drflac_bs *bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53910
ma_device::linear
struct ma_device::@114::@119 linear
ma_device_id::oss
char oss[64]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3066
drflac_init_info::bitsPerSample
drflac_uint8 bitsPerSample
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54798
DRMP3_TRUE
#define DRMP3_TRUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40376
drflac__decode_samples_with_residual__rice
static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs *bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pSamplesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53714
ma_device_id::alsa
char alsa[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3060
drwav_data_format::format
drwav_uint32 format
Definition: porcupine/demo/c/dr_libs/dr_wav.h:438
drwav_init_file_with_metadata_w
DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav *pWav, const wchar_t *filename, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48991
drmp3_L3_read_side_info
static int drmp3_L3_read_side_info(drmp3_bs *bs, drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59730
drflac_frame_header::bitsPerSample
drflac_uint8 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_flac.h:667
DRMP3_BUSY
#define DRMP3_BUSY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40426
MA_THREADCALL
#define MA_THREADCALL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4265
DRMP3_IO_ERROR
#define DRMP3_IO_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40427
drflac_read_pcm_frames_s32__decode_right_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56925
drwav_list_label_or_note
Definition: porcupine/demo/c/dr_libs/dr_wav.h:661
ma_event_wait
MA_API ma_result ma_event_wait(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4898
drflac::firstFLACFramePosInBytes
drflac_uint64 firstFLACFramePosInBytes
Definition: porcupine/demo/c/dr_libs/dr_flac.h:737
drwav_read_pcm_frames_f32be
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50344
drflac_bs
Definition: porcupine/demo/c/dr_libs/dr_flac.h:581
ma_semaphore_wait__posix
static ma_result ma_semaphore_wait__posix(ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4651
c89atomic_load_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_load_explicit_16(volatile const c89atomic_uint16 *ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3770
DRWAV_SIZE_MAX
#define DRWAV_SIZE_MAX
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46334
TRUE
#define TRUE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:641
DRFLAC_BAD_PIPE
#define DRFLAC_BAD_PIPE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51383
ma_copy_and_apply_volume_factor_s24
MA_API void ma_copy_and_apply_volume_factor_s24(void *pSamplesOut, const void *pSamplesIn, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27850
ma_context_config::alsa
struct ma_context_config::@104 alsa
drwav::cachedFrames
drwav_int32 cachedFrames[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:888
drflac_open_relaxed
DRFLAC_API drflac * drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56751
ma_decoder_config::ppCustomBackendVTables
ma_decoding_backend_vtable ** ppCustomBackendVTables
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4761
ma_pcm_f32_to_u8__reference
static MA_INLINE void ma_pcm_f32_to_u8__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29494
DRMP3_BITS_DEQUANTIZER_OUT
#define DRMP3_BITS_DEQUANTIZER_OUT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59361
ma_copy_and_apply_volume_factor_s32
MA_API void ma_copy_and_apply_volume_factor_s32(ma_int32 *pSamplesOut, const ma_int32 *pSamplesIn, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27875
drwav__metadata_parser::pReadSeekUserData
void * pReadSeekUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46902
drwav_cue_point
Definition: porcupine/demo/c/dr_libs/dr_wav.h:590
ma_hpf1::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1963
ma_mutex_lock__posix
static void ma_mutex_lock__posix(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4554
ma_lpf1_process_pcm_frame_f32
static MA_INLINE void ma_lpf1_process_pcm_frame_f32(ma_lpf1 *pLPF, float *pY, const float *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30710
drwav__malloc_default
DRWAV_PRIVATE void * drwav__malloc_default(size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46617
ma_device_descriptor::pDeviceID
const ma_device_id * pDeviceID
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2046
ma_thread_entry_proc
ma_thread_result(MA_THREADCALL * ma_thread_entry_proc)(void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4268
ma_pcm_s24_to_f32__reference
static MA_INLINE void ma_pcm_s24_to_f32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28990
drwav_read_pcm_frames_s32__mulaw
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50586
drwav_data_format::channels
drwav_uint32 channels
Definition: porcupine/demo/c/dr_libs/dr_wav.h:439
drwav_bext::pOriginationDate
char pOriginationDate[10]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:689
DRMP3_HDR_TEST_I_STEREO
#define DRMP3_HDR_TEST_I_STEREO(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59351
ma_standard_channel_map_microsoft
@ ma_standard_channel_map_microsoft
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1805
DRWAV_NOT_IMPLEMENTED
#define DRWAV_NOT_IMPLEMENTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39540
ma_encoder::pInternalEncoder
void * pInternalEncoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5333
ma_result_from_errno
static ma_result ma_result_from_errno(int e)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1184
ma_decode_file
MA_API ma_result ma_decode_file(const char *pFilePath, ma_decoder_config *pConfig, ma_uint64 *pFrameCountOut, void **ppPCMFramesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45067
ma_backend_winmm
@ ma_backend_winmm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2797
ma_decoder_seek_proc
ma_bool32(* ma_decoder_seek_proc)(ma_decoder *pDecoder, int byteOffset, ma_seek_origin origin)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5164
drmp3_L3_intensity_stereo_band
static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60121
drwav_smpl_loop::playCount
drwav_uint32 playCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:535
drmp3__free_from_callbacks
static void drmp3__free_from_callbacks(void *p, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61128
drflac_read_pcm_frames_f32__decode_right_side
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58449
ma_clip_s16
static MA_INLINE ma_int16 ma_clip_s16(ma_int32 x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28040
ma_copy_and_apply_volume_factor_pcm_frames_u8
MA_API void ma_copy_and_apply_volume_factor_pcm_frames_u8(ma_uint8 *pPCMFramesOut, const ma_uint8 *pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27926
ma_audio_buffer_config::pData
const void * pData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4591
MA_CHANNEL_AUX_4
#define MA_CHANNEL_AUX_4
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1625
ma_pcm_interleave_s32__optimized
static MA_INLINE void ma_pcm_interleave_s32__optimized(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29449
drwav_metadata::infoText
drwav_list_info_text infoText
Definition: porcupine/demo/c/dr_libs/dr_wav.h:800
drmp3_L12_dequantize_granule
static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59682
drmp3_seek_to_pcm_frame
DRMP3_API drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3 *pMP3, drmp3_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62199
ma_wav_init_internal
static ma_result ma_wav_init_internal(const ma_decoding_backend_config *pConfig, ma_wav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40976
MA_DIRECTORY_NOT_EMPTY
#define MA_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1675
ma_vfs_or_default_open
MA_API ma_result ma_vfs_or_default_open(ma_vfs *pVFS, const char *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39357
ma_dither_f32
static MA_INLINE float ma_dither_f32(ma_dither_mode ditherMode, float ditherMin, float ditherMax)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2533
ma_event_init
MA_API ma_result ma_event_init(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4829
DRWAV_METADATA_ALIGNMENT
#define DRWAV_METADATA_ALIGNMENT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46892
ma_flac_init
MA_API ma_result ma_flac_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_flac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41646
drwav__bswap64
static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46454
ma_decoding_backend_init_file__wav
static ma_result ma_decoding_backend_init_file__wav(void *pUserData, const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41388
ma_channel_converter_config_init
MA_API ma_channel_converter_config ma_channel_converter_config_init(ma_format format, ma_uint32 channelsIn, const ma_channel *pChannelMapIn, ma_uint32 channelsOut, const ma_channel *pChannelMapOut, ma_channel_mix_mode mixingMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33734
ma_waveform_config::amplitude
double amplitude
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5367
DRFLAC_BAD_MESSAGE
#define DRFLAC_BAD_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51388
ma_data_source_unmap
MA_API ma_result ma_data_source_unmap(ma_data_source *pDataSource, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37595
drmp3dec_f32_to_s16
DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60945
ma_default_vfs::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4673
drflac__crc16_table
static drflac_uint16 drflac__crc16_table[]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51632
ma_decoder_internal_on_read__custom
static ma_result ma_decoder_internal_on_read__custom(void *pUserData, void *pBufferOut, size_t bytesToRead, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40762
drwav_metadata_type_list_info_artist
@ drwav_metadata_type_list_info_artist
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39658
ma_lpf1_get_latency
MA_API ma_uint32 ma_lpf1_get_latency(const ma_lpf1 *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30786
c89atomic_load_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_load_explicit_32(volatile const c89atomic_uint32 *ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3775
DRMP3_MAX
#define DRMP3_MAX(a, b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59365
drwav_chunk_header::paddingSize
unsigned int paddingSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:296
drflac_read_pcm_frames_s16__decode_mid_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57758
DRMP3_BSPOS
#define DRMP3_BSPOS
drflac_ogg__get_page_body_size
static DRFLAC_INLINE drflac_uint32 drflac_ogg__get_page_body_size(drflac_ogg_page_header *pHeader)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55362
MA_STATE_UNINITIALIZED
#define MA_STATE_UNINITIALIZED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1625
ma_device_descriptor::periodSizeInFrames
ma_uint32 periodSizeInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2052
drwav_read_pcm_frames_s16__pcm
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49913
drflac_open_file_w
DRFLAC_API drflac * drflac_open_file_w(const wchar_t *pFileName, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56615
fileno
int fileno(FILE *stream)
ma_rb_get_subbuffer_ptr
MA_API void * ma_rb_get_subbuffer_ptr(ma_rb *pRB, size_t subbufferIndex, void *pBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36796
drmp3_L3_imdct_short
static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60355
DRFLAC_METADATA_BLOCK_TYPE_APPLICATION
#define DRFLAC_METADATA_BLOCK_TYPE_APPLICATION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40073
drwav_fmt::sampleRate
drwav_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_wav.h:311
python.util.log
log
Definition: porcupine/binding/python/util.py:18
DRWAV_BEXT_DESCRIPTION_BYTES
#define DRWAV_BEXT_DESCRIPTION_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46884
drwav_inst::midiUnityNote
drwav_int8 midiUnityNote
Definition: porcupine/demo/c/dr_libs/dr_wav.h:575
DRMP3_S0
#define DRMP3_S0(k)
drflac_allocation_callbacks::onFree
void(* onFree)(void *p, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_flac.h:569
ma_context_config::pApplicationName
const char * pApplicationName
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3172
ma_encoder_init_file
MA_API ma_result ma_encoder_init_file(const char *pFilePath, const ma_encoder_config *pConfig, ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45279
ma_share_mode_shared
@ ma_share_mode_shared
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3020
ma_clip_f32
static MA_INLINE float ma_clip_f32(float x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2339
drwav_smpl::samplerSpecificDataSizeInBytes
drwav_uint32 samplerSpecificDataSizeInBytes
Definition: porcupine/demo/c/dr_libs/dr_wav.h:561
drwav_result
drwav_int32 drwav_result
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39510
ma_aaudio_usage_media
@ ma_aaudio_usage_media
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1835
DRFLAC_PROTOCOL_UNAVAILABLE
#define DRFLAC_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51397
ma_opensl_recording_preset_voice_recognition
@ ma_opensl_recording_preset_voice_recognition
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1816
drflac_seek_origin_current
@ drflac_seek_origin_current
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40109
drflac_oggbs::currentPageHeader
drflac_ogg_page_header currentPageHeader
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55449
drwav_metadata_type_list_info_copyright
@ drwav_metadata_type_list_info_copyright
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39656
drwav__bswap_f64
static DRWAV_INLINE double drwav__bswap_f64(double n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46529
RESAMPLER_ERR_PTR_OVERLAP
@ RESAMPLER_ERR_PTR_OVERLAP
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:108
ma_thread_proxy_data::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4692
ma_resampler_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2243
g_ma_decoding_backend_vtable_mp3
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_mp3
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42743
DRFLAC_METADATA_BLOCK_TYPE_PADDING
#define DRFLAC_METADATA_BLOCK_TYPE_PADDING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40072
ma_opensl_stream_type_media
@ ma_opensl_stream_type_media
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1805
drflac::pDecodedSamples
drflac_int32 * pDecodedSamples
Definition: porcupine/demo/c/dr_libs/dr_flac.h:745
drwav_cue_point::id
drwav_uint32 id
Definition: porcupine/demo/c/dr_libs/dr_wav.h:593
MA_CHANNEL_TOP_BACK_RIGHT
#define MA_CHANNEL_TOP_BACK_RIGHT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1620
ma_resampler_process_pcm_frames__seek
static ma_result ma_resampler_process_pcm_frames__seek(ma_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33369
drwav_read_pcm_frames_s16__ieee
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49938
DRMP3_CONNECTION_REFUSED
#define DRMP3_CONNECTION_REFUSED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40455
ma_device__send_frames_to_client
static void ma_device__send_frames_to_client(ma_device *pDevice, ma_uint32 frameCountInDeviceFormat, const void *pFramesInDeviceFormat)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5801
ma_decoder_init_file_wav_w
MA_API ma_result ma_decoder_init_file_wav_w(const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44719
ma_pcm_rb_get_subbuffer_offset
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_offset(ma_pcm_rb *pRB, ma_uint32 subbufferIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36985
ma_hpf::hpf1Count
ma_uint32 hpf1Count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2000
SpeexResamplerState_
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:116
ma_device_info::maxSampleRate
ma_uint32 maxSampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3092
ma_context::threadPriority
ma_thread_priority threadPriority
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3214
drwav_write_raw
DRWAV_API size_t drwav_write_raw(drwav *pWav, size_t bytesToWrite, const void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49480
ma_hpf1_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1958
ma_context::pLog
ma_log * pLog
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2201
drmp3_int64
signed long long drmp3_int64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40363
drmp3_L3_midside_stereo
static void drmp3_L3_midside_stereo(float *left, int n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60100
c89atomic_fetch_add_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_fetch_add_explicit_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3569
drflac::_noBruteForceSeek
drflac_bool32 _noBruteForceSeek
Definition: porcupine/demo/c/dr_libs/dr_flac.h:756
ma_vfs_open_and_read_file
MA_API ma_result ma_vfs_open_and_read_file(ma_vfs *pVFS, const char *pFilePath, void **ppData, size_t *pSize, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38732
MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY
#define MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:616
drflac_open
DRFLAC_API drflac * drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56747
drflac_open_file_and_read_pcm_frames_s16
DRFLAC_API drflac_int16 * drflac_open_file_and_read_pcm_frames_s16(const char *filename, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59136
drflac__memory_stream::currentReadPos
size_t currentReadPos
Definition: porcupine/demo/c/dr_libs/dr_flac.h:577
ma_waveform_config::frequency
double frequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5368
drflac::pUserDataMD
void * pUserDataMD
Definition: porcupine/demo/c/dr_libs/dr_flac.h:694
ma_thread_entry_proxy
static ma_thread_result MA_THREADCALL ma_thread_entry_proxy(void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4695
ma_noise_f32_white
static MA_INLINE float ma_noise_f32_white(ma_noise *pNoise)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45953
ma_context_init_backend_apis__nix
static ma_result ma_context_init_backend_apis__nix(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26440
DRMP3_FLUSH_BITS
#define DRMP3_FLUSH_BITS(n)
ma_pcm_rb_acquire_write
MA_API ma_result ma_pcm_rb_acquire_write(ma_pcm_rb *pRB, ma_uint32 *pSizeInFrames, void **ppBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36893
ma_dlopen
MA_API ma_handle ma_dlopen(ma_context *pContext, const char *filename)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5580
drwav__data_chunk_size_rf64
DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48264
ma_data_source_vtable::onGetDataFormat
ma_result(* onGetDataFormat)(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4508
drflac_read_pcm_frames_s32__decode_independent_stereo
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57367
drflac_seekpoint
Definition: porcupine/demo/c/dr_libs/dr_flac.h:388
ma__free_from_callbacks
static void ma__free_from_callbacks(void *p, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1900
ma_waveform_square_f32
static float ma_waveform_square_f32(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45534
ma_channel_converter_config::channelsOut
ma_uint32 channelsOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2362
drflac__read_and_decode_metadata
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void *pUserData, void *pUserDataMD, drflac_uint64 *pFirstFramePos, drflac_uint64 *pSeektablePos, drflac_uint32 *pSeektableSize, drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54920
ma_hishelf2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2166
ma_linear_resampler_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2192
drflac_cuesheet_track::indexCount
drflac_uint8 indexCount
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1300
ma_strcat_s
MA_API int ma_strcat_s(char *dst, size_t dstSizeInBytes, const char *src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:959
ma_post_log_message
static void ma_post_log_message(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5422
drwav_bext::version
drwav_uint16 version
Definition: porcupine/demo/c/dr_libs/dr_wav.h:692
g_ma_wav_ds_vtable
static ma_data_source_vtable g_ma_wav_ds_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40908
ma_pcm_rb_init
MA_API ma_result ma_pcm_rb_init(ma_format format, ma_uint32 channels, ma_uint32 bufferSizeInFrames, void *pOptionalPreallocatedBuffer, const ma_allocation_callbacks *pAllocationCallbacks, ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36841
drmp3_int16
signed short drmp3_int16
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:106
ma_mix_f32
static MA_INLINE float ma_mix_f32(float x, float y, float a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2346
MA_CHANNEL_FRONT_RIGHT_CENTER
#define MA_CHANNEL_FRONT_RIGHT_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1610
ma_wav_init_file_w
MA_API ma_result ma_wav_init_file_w(const wchar_t *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_wav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41075
ma_waveform_triangle_s16
static ma_int16 ma_waveform_triangle_s16(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45563
ma_noise_config::type
ma_noise_type type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5404
ma_encoder::pFile
void * pFile
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5334
ma_pcm_interleave_f32__optimized
static void ma_pcm_interleave_f32__optimized(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30190
ma_encoder_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5318
ma_decoder_config::ditherMode
ma_dither_mode ditherMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5177
drwav_read_pcm_frames_f32
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50305
drflac_open_file_and_read_pcm_frames_f32
DRFLAC_API float * drflac_open_file_and_read_pcm_frames_f32(const char *filename, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59154
MA_CHANNEL_TOP_FRONT_CENTER
#define MA_CHANNEL_TOP_FRONT_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1616
ma_backend_coreaudio
@ ma_backend_coreaudio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2798
ma_mp3::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42138
ma_noise_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5403
ma_hpf_reinit
MA_API ma_result ma_hpf_reinit(const ma_hpf_config *pConfig, ma_hpf *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31530
drflac_oggbs::pageDataSize
drflac_uint32 pageDataSize
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55451
MA_TIMEOUT
#define MA_TIMEOUT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1693
drwav__read_inst_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_inst_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47035
speex_resampler_process_interleaved_float
EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:1038
drflac_frame::header
drflac_frame_header header
Definition: porcupine/demo/c/dr_libs/dr_flac.h:676
drwav__write_u16ne_to_le
DRWAV_PRIVATE size_t drwav__write_u16ne_to_le(drwav *pWav, drwav_uint16 value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47833
DRWAV_CANCELLED
#define DRWAV_CANCELLED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39562
drwav_bytes_to_s32
DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51066
ma_decoder_init_wav
MA_API ma_result ma_decoder_init_wav(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43687
ma_decoding_backend_init_memory__flac
static ma_result ma_decoding_backend_init_memory__flac(void *pUserData, const void *pData, size_t dataSize, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42068
ma_bpf2_get_latency
MA_API ma_uint32 ma_bpf2_get_latency(const ma_bpf2 *pBPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31737
ma_peak2__get_biquad_config
static MA_INLINE ma_biquad_config ma_peak2__get_biquad_config(const ma_peak2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32074
ma_duplex_rb_uninit
MA_API ma_result ma_duplex_rb_uninit(ma_duplex_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37026
drwav__metadata_request_extra_memory_for_stage_2
DRWAV_PRIVATE void drwav__metadata_request_extra_memory_for_stage_2(drwav__metadata_parser *pParser, size_t bytes, size_t align)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46933
DRMP3_VERSION_MAJOR
#define DRMP3_VERSION_MAJOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40341
ma_audio_buffer_ref::pData
const void * pData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4569
DRWAV_NO_MESSAGE
#define DRWAV_NO_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39541
drflac_oggbs::serialNumber
drflac_uint32 serialNumber
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55447
ma_wav_uninit
MA_API void ma_wav_uninit(ma_wav *pWav, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41138
drwav_cue::cuePointCount
drwav_uint32 cuePointCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:613
ma_context_enumerate_devices__null
static ma_result ma_context_enumerate_devices__null(ma_context *pContext, ma_enum_devices_callback_proc callback, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6333
DRWAV_PATH_TOO_LONG
#define DRWAV_PATH_TOO_LONG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39523
MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE
#define MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:621
ma_bpf_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2043
ma_device_config::pStreamNamePlayback
const char * pStreamNamePlayback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3155
ma_clip_u8
static MA_INLINE ma_uint8 ma_clip_u8(ma_int16 x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28035
drwav__memory_stream_write::dataCapacity
size_t dataCapacity
Definition: porcupine/demo/c/dr_libs/dr_wav.h:431
ma_hpf1_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1955
ma_noise::config
ma_noise_config config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5414
DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
#define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51421
ma_resampler_get_required_input_frame_count
MA_API ma_uint64 ma_resampler_get_required_input_frame_count(const ma_resampler *pResampler, ma_uint64 outputFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33480
drflac::_noSeekTableSeek
drflac_bool32 _noSeekTableSeek
Definition: porcupine/demo/c/dr_libs/dr_flac.h:754
MA_NAME_TOO_LONG
#define MA_NAME_TOO_LONG
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1672
count
size_t count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_common/ma_test_common.c:31
c89atomic_fetch_sub_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_fetch_sub_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3598
drflac::currentPCMFrame
drflac_uint64 currentPCMFrame
Definition: porcupine/demo/c/dr_libs/dr_flac.h:734
drwav_open_file_and_read_pcm_frames_s16_w
DRWAV_API drwav_int16 * drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t *filename, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50933
drwav::isSequentialWrite
drwav_bool32 isSequentialWrite
Definition: porcupine/demo/c/dr_libs/dr_wav.h:866
c89atomic_store_explicit_32
#define c89atomic_store_explicit_32(dst, src, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3787
drmp3_L12_subband_alloc
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59490
ma_hishelf2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2158
DRFLAC_SUBFRAME_RESERVED
#define DRFLAC_SUBFRAME_RESERVED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51416
DRWAV_OUT_OF_RANGE
#define DRWAV_OUT_OF_RANGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39516
drflac__read_and_decode_next_flac_frame
static drflac_bool32 drflac__read_and_decode_next_flac_frame(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54365
ma_lpf_process_pcm_frame_f32
static MA_INLINE void ma_lpf_process_pcm_frame_f32(ma_lpf *pLPF, float *pY, const void *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31024
DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE
#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, _bitCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51843
ma_data_source_vtable::onMap
ma_result(* onMap)(ma_data_source *pDataSource, void **ppFramesOut, ma_uint64 *pFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4506
ma_peak2_process_pcm_frame_s16
static MA_INLINE void ma_peak2_process_pcm_frame_s16(ma_peak2 *pFilter, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32148
ma_lpf::lpf1
ma_lpf1 lpf1[1]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1934
MA_CHANNEL_AUX_2
#define MA_CHANNEL_AUX_2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1623
DRWAV_NOT_SOCKET
#define DRWAV_NOT_SOCKET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39548
ma_audio_buffer_map
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer *pAudioBuffer, void **ppFramesOut, ma_uint64 *pFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38439
ma_audio_buffer
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4597
DRMP3_HDR_TEST_MPEG1
#define DRMP3_HDR_TEST_MPEG1(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59349
ma_noise_uninit
MA_API void ma_noise_uninit(ma_noise *pNoise)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45913
ma_default_vfs_write__stdio
static ma_result ma_default_vfs_write__stdio(ma_vfs *pVFS, ma_vfs_file file, const void *pSrc, size_t sizeInBytes, size_t *pBytesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39085
DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
#define DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40071
ma_audio_buffer_ref_init
MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void *pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref *pAudioBufferRef)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38040
ma_standard_sample_rate_22050
@ ma_standard_sample_rate_22050
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:417
ma_is_big_endian
static MA_INLINE ma_bool32 ma_is_big_endian(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:455
ma_waveform_type_triangle
@ ma_waveform_type_triangle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5361
drmp3_L3_gr_info::count1_table
drmp3_uint8 count1_table
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59500
ma_aaudio_usage_assistance_accessibility
@ ma_aaudio_usage_assistance_accessibility
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1830
C89ATOMIC_INLINE
#define C89ATOMIC_INLINE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2641
MA_CHANNEL_AUX_26
#define MA_CHANNEL_AUX_26
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1647
ma_device_descriptor
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2044
DRMP3_MAX_SCFI
#define DRMP3_MAX_SCFI
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59363
DRFLAC_TIMEOUT
#define DRFLAC_TIMEOUT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51391
MA_LCG_A
#define MA_LCG_A
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2432
ma_vfs_close
MA_API ma_result ma_vfs_close(ma_vfs *pVFS, ma_vfs_file file)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38556
drwav_bext::pOriginatorReference
char * pOriginatorReference
Definition: porcupine/demo/c/dr_libs/dr_wav.h:688
drmp3d_synth
static void drmp3d_synth(float *xl, drmp3d_sample_t *dstl, int nch, float *lins)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60642
ma_bpf_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2042
ma_lpf_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1917
ma_device_do_operation__null
static ma_result ma_device_do_operation__null(ma_device *pDevice, ma_uint32 operation)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6283
ma_noise_f32_pink
static MA_INLINE float ma_noise_f32_pink(ma_noise *pNoise, ma_uint32 iChannel)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46055
MA_IS_DIRECTORY
#define MA_IS_DIRECTORY
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1674
ma_semaphore_uninit
MA_API void ma_semaphore_uninit(ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4944
ma_audio_buffer_seek_to_pcm_frame
MA_API ma_result ma_audio_buffer_seek_to_pcm_frame(ma_audio_buffer *pAudioBuffer, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38430
ma_lpf_config::order
ma_uint32 order
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1923
c89atomic_compare_exchange_weak_explicit_64
#define c89atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3874
DRMP3_MAX_FRAME_SYNC_MATCHES
#define DRMP3_MAX_FRAME_SYNC_MATCHES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59335
ma_device_get_total_run_time_in_frames__null
static ma_uint64 ma_device_get_total_run_time_in_frames__null(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6321
drmp3__on_seek_64
static drmp3_bool32 drmp3__on_seek_64(drmp3 *pMP3, drmp3_uint64 offset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61169
drmp3__realloc_default
static void * drmp3__realloc_default(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61083
ma_device_set_master_volume
MA_API ma_result ma_device_set_master_volume(ma_device *pDevice, float volume)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27617
c89atomic_int8
signed char c89atomic_int8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2572
c89atomic_is_lock_free_32
static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_32(volatile void *ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3887
DRMP3_NOT_CONNECTED
#define DRMP3_NOT_CONNECTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40454
ma_biquad::b2
ma_biquad_coefficient b2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1863
drmp3_L3_stereo_process
static void drmp3_L3_stereo_process(float *left, const drmp3_uint8 *ist_pos, const drmp3_uint8 *sfb, const drmp3_uint8 *hdr, int max_band[3], int mpeg2_sh)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60147
ma_device_config::recordingPreset
ma_opensl_recording_preset recordingPreset
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2007
ma_data_source_vtable::onRead
ma_result(* onRead)(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4504
drflac__le2host_32
static DRFLAC_INLINE drflac_uint32 drflac__le2host_32(drflac_uint32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51598
ma_aaudio_usage_vehicle_status
@ ma_aaudio_usage_vehicle_status
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1828
ma_noise_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5402
drwav_list_labelled_cue_region::purposeId
drwav_uint8 purposeId[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:743
DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED
#define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39553
ma_data_converter_process_pcm_frames__resample_only
static ma_result ma_data_converter_process_pcm_frames__resample_only(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34885
DRMP3_ERROR
#define DRMP3_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40408
ma_default_vfs_write
static ma_result ma_default_vfs_write(ma_vfs *pVFS, ma_vfs_file file, const void *pSrc, size_t sizeInBytes, size_t *pBytesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39268
ma_waveform::config
ma_waveform_config config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5375
drwav__alaw_to_s16
static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49854
DRWAV_BAD_SEEK
#define DRWAV_BAD_SEEK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39536
ma_encoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5324
ma_loshelf2_process_pcm_frame_f32
static MA_INLINE void ma_loshelf2_process_pcm_frame_f32(ma_loshelf2 *pFilter, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32279
ma_biquad_process_pcm_frame_f32
static MA_INLINE void ma_biquad_process_pcm_frame_f32(ma_biquad *pBQ, float *pY, const float *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30533
ma_strcpy_s
MA_API int ma_strcpy_s(char *dst, size_t dstSizeInBytes, const char *src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:868
drmp3dec::reserv_buf
drmp3_uint8 reserv_buf[511]
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:266
drmp3_L3_reorder
static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60197
ma_format_s16
@ ma_format_s16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1787
ma_encoder_init
MA_API ma_result ma_encoder_init(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void *pUserData, const ma_encoder_config *pConfig, ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45321
drmp3::pcmFramesRemainingInMP3Frame
drmp3_uint32 pcmFramesRemainingInMP3Frame
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:353
MA_PROTOCOL_UNAVAILABLE
#define MA_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1699
drwav_fmt::formatTag
drwav_uint16 formatTag
Definition: porcupine/demo/c/dr_libs/dr_wav.h:305
ma_vfs_file
ma_handle ma_vfs_file
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4631
ma_hpf_reinit__internal
static ma_result ma_hpf_reinit__internal(const ma_hpf_config *pConfig, ma_hpf *pHPF, ma_bool32 isNew)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31422
drwav_init_memory_write
DRWAV_API drwav_bool32 drwav_init_memory_write(drwav *pWav, void **ppData, size_t *pDataSize, const drwav_data_format *pFormat, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49201
drwav_s24_to_f32
DRWAV_API void drwav_s24_to_f32(float *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50381
ma_thread_wait
static void ma_thread_wait(ma_thread *pThread)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4754
ma_context_config::noAudioSessionActivate
ma_bool32 noAudioSessionActivate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2160
drmp3_L3_gr_info::region_count
drmp3_uint8 region_count[3]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59499
DRMP3_HDR_IS_FRAME_576
#define DRMP3_HDR_IS_FRAME_576(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59359
ma_device_id::sndio
char sndio[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3064
MA_CHANNEL_AUX_5
#define MA_CHANNEL_AUX_5
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1626
drwav::readCursorInPCMFrames
drwav_uint64 readCursorInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_wav.h:856
ma_decoder_init_memory_mp3
MA_API ma_result ma_decoder_init_memory_mp3(const void *pData, size_t dataSize, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44028
ma_lpf1_init
MA_API ma_result ma_lpf1_init(const ma_lpf1_config *pConfig, ma_lpf1 *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30655
drwav::onSeek
drwav_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/dr_wav.h:814
ma_context::log
ma_log log
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2202
DRMP3_PROTOCOL_NOT_SUPPORTED
#define DRMP3_PROTOCOL_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40448
ma_channel_map_valid
MA_API ma_bool32 ma_channel_map_valid(ma_uint32 channels, const ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36210
ma_log10d
static MA_INLINE double ma_log10d(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:823
ma_notch2_config::frequency
double frequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2079
drmp3_get_pcm_frame_count
DRMP3_API drmp3_uint64 drmp3_get_pcm_frame_count(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62253
ma_device_info
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3073
ma_ios_session_category_play_and_record
@ ma_ios_session_category_play_and_record
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3033
ma_pcm_u8_to_u8
MA_API void ma_pcm_u8_to_u8(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28063
drflac_int8
signed char drflac_int8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39985
DRMP3_ALREADY_IN_USE
#define DRMP3_ALREADY_IN_USE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40430
drwav__read_list_label_or_note_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_list_label_or_note_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata, drwav_uint64 chunkSize, drwav_metadata_type type)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47147
DRFLAC_DEFINE_FULL_READ_AND_CLOSE
#define DRFLAC_DEFINE_FULL_READ_AND_CLOSE(extension, type)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58993
drflac_metadata::vorbis_comment
struct drflac_metadata::@0::@4 vorbis_comment
DRFLAC_DOES_NOT_EXIST
#define DRFLAC_DOES_NOT_EXIST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51364
ma_flac_uninit
MA_API void ma_flac_uninit(ma_flac *pFlac, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41775
ma_noise_f32_brownian
static MA_INLINE float ma_noise_f32_brownian(ma_noise *pNoise, ma_uint32 iChannel)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46146
ma_linear_resampler_process_pcm_frames_f32
static ma_result ma_linear_resampler_process_pcm_frames_f32(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32928
drflac_init_info::onRead
drflac_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54790
DRWAV_REALLOC
#define DRWAV_REALLOC(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46288
DRWAV_BEXT_ORIGINATOR_REF_BYTES
#define DRWAV_BEXT_ORIGINATOR_REF_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46886
ma_hpf_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1987
drmp3_L12_scale_info::bitalloc
drmp3_uint8 bitalloc[64]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59488
drwav_list_labelled_cue_region::language
drwav_uint16 language
Definition: porcupine/demo/c/dr_libs/dr_wav.h:747
ma_decoder_init_vfs_w
MA_API ma_result ma_decoder_init_vfs_w(ma_vfs *pVFS, const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44509
ma_hpf1_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1956
ma_data_source_base::onGetNext
ma_data_source_get_next_proc onGetNext
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4535
MA_LOG_LEVEL_WARNING
#define MA_LOG_LEVEL_WARNING
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1590
drflac_init_info::oggSerial
drflac_uint32 oggSerial
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54807
MA_DOES_NOT_EXIST
#define MA_DOES_NOT_EXIST
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1666
ma_hpf2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1974
drmp3_uint8
unsigned char drmp3_uint8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40347
ma_device::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3592
ma_linear_resampler::x0
union ma_linear_resampler::@73 x0
ma_loshelf2_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2124
ma_device::thread
ma_thread thread
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3597
d
d
drmp3::onSeek
drmp3_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:347
drmp3d_find_frame
static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60820
drflac_oggbs::pUserData
void * pUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55444
ma_bpf2__get_biquad_config
static MA_INLINE ma_biquad_config ma_bpf2__get_biquad_config(const ma_bpf2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31646
ma_hpf_config_init
MA_API ma_hpf_config ma_hpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31408
ma_encoder::onInit
ma_encoder_init_proc onInit
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5329
ma_bpf_reinit
MA_API ma_result ma_bpf_reinit(const ma_bpf_config *pConfig, ma_bpf *pBPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31848
ma_encoder::onWrite
ma_encoder_write_proc onWrite
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5327
drwav_read_pcm_frames_f32__ieee
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50238
ma_data_converter_config::sampleRateIn
ma_uint32 sampleRateIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2407
ma_dither_f32_rectangle
static MA_INLINE float ma_dither_f32_rectangle(float ditherMin, float ditherMax)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2521
DRWAV_INLINE
#define DRWAV_INLINE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46326
drmp3dec::header
drmp3_uint8 header[4]
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:266
ma_device_id::opensl
ma_uint32 opensl
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3068
ma_rand_u32
static MA_INLINE ma_uint32 ma_rand_u32(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2495
drmp3::mp3FrameSampleRate
drmp3_uint32 mp3FrameSampleRate
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:351
ma_device_id
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3055
drmp3_uint16
unsigned short drmp3_uint16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40349
DRMP3_NO_MESSAGE
#define DRMP3_NO_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40437
ma_bpf::bpf2
ma_bpf2 bpf2[MA_MAX_FILTER_ORDER/2]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2055
ma_audio_buffer_config::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4592
drflac_int32
signed int drflac_int32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39989
ma_resampler_config::lpfOrder
ma_uint32 lpfOrder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2249
drmp3_L12_read_scalefactors
static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59617
ma_wav_dr_callback__seek
static drwav_bool32 ma_wav_dr_callback__seek(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40954
drwav_write_pcm_frames_be
DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav *pWav, drwav_uint64 framesToWrite, const void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49519
MA_SIMD_ALIGNMENT
#define MA_SIMD_ALIGNMENT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1584
ma_pcm_sample_f32_to_s16
static MA_INLINE ma_int16 ma_pcm_sample_f32_to_s16(float x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28012
ma_device_config::allowNominalSampleRateChange
ma_bool32 allowNominalSampleRateChange
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2002
DRFLAC_CACHE_L1_SIZE_BITS
#define DRFLAC_CACHE_L1_SIZE_BITS(bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51837
drflac_ogg_page_header::structureVersion
drflac_uint8 structureVersion
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54778
drwav::dataChunkDataPos
drwav_uint64 dataChunkDataPos
Definition: porcupine/demo/c/dr_libs/dr_wav.h:850
c89atomic_fetch_add_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_fetch_add_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3558
ma_linear_resampler_adjust_timer_for_new_rate
static void ma_linear_resampler_adjust_timer_for_new_rate(ma_linear_resampler *pResampler, ma_uint32 oldSampleRateOut, ma_uint32 newSampleRateOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32449
ma_device_config::algorithm
ma_resample_algorithm algorithm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3115
ma_data_converter::config
ma_data_converter_config config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2431
ma_free
MA_API void ma_free(void *p, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37139
drwav::memoryStream
drwav__memory_stream memoryStream
Definition: porcupine/demo/c/dr_libs/dr_wav.h:878
ma_pcm_s24_to_s16__optimized
static MA_INLINE void ma_pcm_s24_to_s16__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28871
ma_device::onData
ma_device_callback_proc onData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3590
DRWAV_DIRECTORY_NOT_EMPTY
#define DRWAV_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39527
ma_decoding_backend_get_channel_map__flac
static ma_result ma_decoding_backend_get_channel_map__flac(void *pUserData, ma_data_source *pBackend, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42102
ma_mutex_init__posix
static ma_result ma_mutex_init__posix(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4539
ma_mix_f64_fast
static MA_INLINE double ma_mix_f64_fast(double x, double y, double a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2388
ma_decoder_config::customBackendCount
ma_uint32 customBackendCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4762
drflac_ogg_crc_mismatch_recovery
drflac_ogg_crc_mismatch_recovery
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55248
drwav__metadata_parser::metadataCursor
drwav_uint64 metadataCursor
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46908
ma_backend_callbacks::onContextUninit
ma_result(* onContextUninit)(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2125
drflac__swap_endian_uint16
static DRFLAC_INLINE drflac_uint16 drflac__swap_endian_uint16(drflac_uint16 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51506
ma_data_source_vtable::onUnmap
ma_result(* onUnmap)(ma_data_source *pDataSource, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4507
ma_audio_buffer_ref__data_source_on_read
static ma_result ma_audio_buffer_ref__data_source_on_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37969
ma_device::channelMap
ma_channel channelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3627
ma_data_source_base::rangeBegInFrames
ma_uint64 rangeBegInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4529
ma_pcm_rb_uninit
MA_API void ma_pcm_rb_uninit(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36846
ma_data_converter_get_output_latency
MA_API ma_uint64 ma_data_converter_get_output_latency(const ma_data_converter *pConverter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35417
ma_device_config::opensl
struct ma_device_config::@178 opensl
python.setup.description
description
Definition: porcupine/binding/python/setup.py:73
drwav_write_pcm_frames_le
DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav *pWav, drwav_uint64 framesToWrite, const void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49490
ma_decoder::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4768
drwav_list_labelled_cue_region::dialect
drwav_uint16 dialect
Definition: porcupine/demo/c/dr_libs/dr_wav.h:748
drwav__bswap_samples_f32
static DRWAV_INLINE void drwav__bswap_samples_f32(float *pSamples, drwav_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46522
ma_decoder_config::channelMap
ma_channel channelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5175
ma_aaudio_usage_default
@ ma_aaudio_usage_default
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1824
ma_data_converter_config::channelWeights
float channelWeights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2413
ma_data_converter_get_input_latency
MA_API ma_uint64 ma_data_converter_get_input_latency(const ma_data_converter *pConverter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35404
DRFLAC_IN_PROGRESS
#define DRFLAC_IN_PROGRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51407
drmp3_bind_seek_table
DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3 *pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point *pSeekPoints)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62375
ma_noise__data_source_on_seek
static ma_result ma_noise__data_source_on_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45835
MA_CHANNEL_AUX_14
#define MA_CHANNEL_AUX_14
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1635
ma_pcm_u8_to_s16__optimized
static MA_INLINE void ma_pcm_u8_to_s16__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28086
drflac_next_cuesheet_track
DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator *pIter, drflac_cuesheet_track *pCuesheetTrack)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59271
DRMP3_S2
#define DRMP3_S2(k)
DRMP3_HDR_IS_MONO
#define DRMP3_HDR_IS_MONO(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59344
ma_waveform::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4986
ma_gcf_u32
static MA_INLINE ma_uint32 ma_gcf_u32(ma_uint32 a, ma_uint32 b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2402
DRFLAC_METADATA_BLOCK_TYPE_CUESHEET
#define DRFLAC_METADATA_BLOCK_TYPE_CUESHEET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40076
ma_wfopen
MA_API ma_result ma_wfopen(FILE **ppFile, const wchar_t *pFilePath, const wchar_t *pOpenMode, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1648
MA_SHARE_MODE_NOT_SUPPORTED
#define MA_SHARE_MODE_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1717
ma_decoder_config_init_default
MA_API ma_decoder_config ma_decoder_config_init_default()
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40663
ma_device_descriptor::periodCount
ma_uint32 periodCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2054
ma_decoding_backend_vtable::onUninit
void(* onUninit)(void *pUserData, ma_data_source *pBackend, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4729
ma_context_is_backend_asynchronous
static ma_bool32 ma_context_is_backend_asynchronous(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26526
ma_audio_buffer::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4600
ma_aaudio_usage_voice_communication
@ ma_aaudio_usage_voice_communication
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1839
DRMP3_HDR_TEST_NOT_MPEG25
#define DRMP3_HDR_TEST_NOT_MPEG25(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59350
drflac::maxBlockSizeInPCMFrames
drflac_uint16 maxBlockSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:713
ma_pcm_interleave_s24__reference
static MA_INLINE void ma_pcm_interleave_s24__reference(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29064
DRWAV_TIMEOUT
#define DRWAV_TIMEOUT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39545
drwav__read_pcm_frames_and_close_s32
DRWAV_PRIVATE drwav_int32 * drwav__read_pcm_frames_and_close_s32(drwav *pWav, unsigned int *channels, unsigned int *sampleRate, drwav_uint64 *totalFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50796
MA_OPEN_MODE_READ
#define MA_OPEN_MODE_READ
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4633
ma_device_init__null
static ma_result ma_device_init__null(ma_device *pDevice, const ma_device_config *pConfig, ma_device_descriptor *pDescriptorPlayback, ma_device_descriptor *pDescriptorCapture)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6410
MA_VERSION_REVISION
#define MA_VERSION_REVISION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:23
g_ma_waveform_data_source_vtable
static ma_data_source_vtable g_ma_waveform_data_source_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45434
stb_vorbis_open_pushdata
stb_vorbis * stb_vorbis_open_pushdata(const unsigned char *datablock, int datablock_length_in_bytes, int *datablock_memory_consumed_in_bytes, int *error, const stb_vorbis_alloc *alloc_buffer)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4489
drmp3_seek_origin
drmp3_seek_origin
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:284
ma_encoder__on_write_stdio
MA_API size_t ma_encoder__on_write_stdio(ma_encoder *pEncoder, const void *pBufferIn, size_t bytesToWrite)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45269
ma_pcm_s32_to_f32__reference
static MA_INLINE void ma_pcm_s32_to_f32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29363
ma_encoder_config::resourceFormat
ma_resource_format resourceFormat
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5315
DRFLAC_SUBFRAME_VERBATIM
#define DRFLAC_SUBFRAME_VERBATIM
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51413
MA_DEVICE_ALREADY_INITIALIZED
#define MA_DEVICE_ALREADY_INITIALIZED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1725
drflac__seek_to_pcm_frame__binary_search_internal
static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac *pFlac, drflac_uint64 pcmFrameIndex, drflac_uint64 byteRangeLo, drflac_uint64 byteRangeHi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54569
ma_thread_priority_idle
@ ma_thread_priority_idle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2814
DRFLAC_CRC_MISMATCH
#define DRFLAC_CRC_MISMATCH
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51411
ma_decoder::converter
ma_data_converter converter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5207
ma_wav_dr_callback__read
static size_t ma_wav_dr_callback__read(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40940
ma_timer_init
static void ma_timer_init(ma_timer *pTimer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5550
drwav__is_compressed_format_tag
static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46689
DRMP3_MAX_BITRESERVOIR_BYTES
#define DRMP3_MAX_BITRESERVOIR_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59338
ma_decoder_seek_bytes
static ma_result ma_decoder_seek_bytes(ma_decoder *pDecoder, ma_int64 byteOffset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40609
drmp3_calculate_seek_points
DRMP3_API drmp3_bool32 drmp3_calculate_seek_points(drmp3 *pMP3, drmp3_uint32 *pSeekPointCount, drmp3_seek_point *pSeekPoints)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62286
MA_INVALID_OPERATION
#define MA_INVALID_OPERATION
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1662
ma_pcm_s32_to_s32
MA_API void ma_pcm_s32_to_s32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29355
drmp3_seek_to_start_of_stream
static drmp3_bool32 drmp3_seek_to_start_of_stream(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62109
drwav__metadata_parser_read
DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser *pParser, void *pBufferOut, size_t bytesToRead, drwav_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46952
ma_encoding_format_vorbis
@ ma_encoding_format_vorbis
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4698
ma_decoder__init_data_converter
static ma_result ma_decoder__init_data_converter(ma_decoder *pDecoder, const ma_decoder_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40680
drmp3_L12_subband_alloc_table
static const drmp3_L12_subband_alloc * drmp3_L12_subband_alloc_table(const drmp3_uint8 *hdr, drmp3_L12_scale_info *sci)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59577
DRFLAC_NO_ADDRESS
#define DRFLAC_NO_ADDRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51395
ma_lpf1::r1
ma_biquad_coefficient r1[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1898
DRFLAC_ALREADY_IN_USE
#define DRFLAC_ALREADY_IN_USE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51380
drwav_seek_to_pcm_frame
DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav *pWav, drwav_uint64 targetFrameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49385
drwav_read_proc
size_t(* drwav_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39610
DRFLAC_TOO_MANY_OPEN_FILES
#define DRFLAC_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51366
ma_encoder_init_file_w
MA_API ma_result ma_encoder_init_file_w(const wchar_t *pFilePath, const ma_encoder_config *pConfig, ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45300
DRWAV_ASSERT
#define DRWAV_ASSERT(expression)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46282
ma_get_standard_channel_map_alsa
static void ma_get_standard_channel_map_alsa(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35671
ma_get_standard_channel_map_sndio
static void ma_get_standard_channel_map_sndio(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36083
c89atomic_flag_clear_explicit
#define c89atomic_flag_clear_explicit(ptr, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3799
drmp3_init_internal
static drmp3_bool32 drmp3_init_internal(drmp3 *pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void *pUserData, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61319
ma_decoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5193
ma_pcm_interleave_u8__optimized
static MA_INLINE void ma_pcm_interleave_u8__optimized(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28348
c89atomic_fetch_xor_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_fetch_xor_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3697
ma_decoder__full_decode_and_uninit
static ma_result ma_decoder__full_decode_and_uninit(ma_decoder *pDecoder, ma_decoder_config *pConfigOut, ma_uint64 *pFrameCountOut, void **ppPCMFramesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44965
drflac_bool32
drflac_uint32 drflac_bool32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:270
ma_device_write__null
static ma_result ma_device_write__null(ma_device *pDevice, const void *pPCMFrames, ma_uint32 frameCount, ma_uint32 *pFramesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6494
drflac_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/dr_flac.h:564
ma_get_standard_channel_map_flac
static void ma_get_standard_channel_map_flac(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35821
drflac_init_info::pUserDataMD
void * pUserDataMD
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54795
ma_decoder_init_flac
MA_API ma_result ma_decoder_init_flac(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43706
ma_decoder_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5172
drwav_metadata_location_invalid
@ drwav_metadata_location_invalid
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39794
DRMP3_CANCELLED
#define DRMP3_CANCELLED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40458
ma_opensl_recording_preset_voice_communication
@ ma_opensl_recording_preset_voice_communication
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1817
ma_data_converter_process_pcm_frames
MA_API ma_result ma_data_converter_process_pcm_frames(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35303
ma_noise::state
union ma_noise::@126 state
L
#define L
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:5102
MA_ASSERT
#define MA_ASSERT(condition)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:770
ma_encoder__on_seek_stdio
MA_API ma_bool32 ma_encoder__on_seek_stdio(ma_encoder *pEncoder, int byteOffset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45274
ma_default_vfs_tell__stdio
static ma_result ma_default_vfs_tell__stdio(ma_vfs *pVFS, ma_vfs_file file, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39145
DRWAV_ZERO_OBJECT
#define DRWAV_ZERO_OBJECT(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46300
ma_noise::pink
struct ma_noise::@126::@127 pink
ma_copy_and_apply_volume_factor_pcm_frames_f32
MA_API void ma_copy_and_apply_volume_factor_pcm_frames_f32(float *pPCMFramesOut, const float *pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27946
ma_pcm_deinterleave_s24__reference
static MA_INLINE void ma_pcm_deinterleave_s24__reference(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29095
c89atomic_exchange_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_exchange_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3488
ma_device_descriptor::shareMode
ma_share_mode shareMode
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2047
ma_lpf2_process_pcm_frames
MA_API ma_result ma_lpf2_process_pcm_frames(ma_lpf2 *pLPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30878
ma_biquad_process_pcm_frames
MA_API ma_result ma_biquad_process_pcm_frames(ma_biquad *pBQ, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30570
drwav__bswap_s16
static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46475
drflac__seek_subframe
static drflac_bool32 drflac__seek_subframe(drflac_bs *bs, drflac_frame *frame, int subframeIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54214
drflac__decode_flac_frame_and_seek_forward_by_pcm_frames
static drflac_bool32 drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(drflac *pFlac, drflac_uint64 offset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54558
DRFLAC_MALLOC
#define DRFLAC_MALLOC(sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51338
ma_context::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3215
drflac__is_little_endian
static DRFLAC_INLINE drflac_bool32 drflac__is_little_endian(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51495
drwav_acid_flag_acidizer
@ drwav_acid_flag_acidizer
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39738
drwav_list_label_or_note::cuePointId
drwav_uint32 cuePointId
Definition: porcupine/demo/c/dr_libs/dr_wav.h:664
drwav_metadata::smpl
drwav_smpl smpl
Definition: porcupine/demo/c/dr_libs/dr_wav.h:794
ma_loshelf2_reinit
MA_API ma_result ma_loshelf2_reinit(const ma_loshelf2_config *pConfig, ma_loshelf2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32256
ma_ios_session_category
ma_ios_session_category
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3025
drmp3d_scale_pcm
static drmp3_int16 drmp3d_scale_pcm(float sample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60597
drwav_metadata
Definition: porcupine/demo/c/dr_libs/dr_wav.h:786
drflac_bs::crc16
drflac_uint16 crc16
Definition: porcupine/demo/c/dr_libs/dr_flac.h:620
stb_vorbis
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:768
ma_decoder_read_proc
size_t(* ma_decoder_read_proc)(ma_decoder *pDecoder, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5163
ma_data_converter_config::allowDynamicSampleRate
ma_bool32 allowDynamicSampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2417
ma_decoder_get_length_in_pcm_frames
MA_API ma_uint64 ma_decoder_get_length_in_pcm_frames(ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44780
ma_pcm_s32_to_s16__reference
static MA_INLINE void ma_pcm_s32_to_s16__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29210
drwav_data_format::container
drwav_container container
Definition: porcupine/demo/c/dr_libs/dr_wav.h:437
drflac__realloc_from_callbacks
static void * drflac__realloc_from_callbacks(void *p, size_t szNew, size_t szOld, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54889
drwav_int16
signed short drwav_int16
Definition: porcupine/demo/c/dr_libs/dr_wav.h:136
DRMP3_HDR_GET_LAYER
#define DRMP3_HDR_GET_LAYER(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59355
ma_aaudio_content_type_movie
@ ma_aaudio_content_type_movie
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1847
ma_linear_resampler_init
MA_API ma_result ma_linear_resampler_init(const ma_linear_resampler_config *pConfig, ma_linear_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32528
ma_notch2_process_pcm_frame_f32
static MA_INLINE void ma_notch2_process_pcm_frame_f32(ma_notch2 *pFilter, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32024
DRMP3_TIMEOUT
#define DRMP3_TIMEOUT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40441
drmp3_bool32
drmp3_uint32 drmp3_bool32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40375
ma_channel_converter_config::channelMapIn
ma_channel channelMapIn[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2363
ma_waveform_sawtooth_f32
static float ma_waveform_sawtooth_f32(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45568
drwav_acid::meterDenominator
drwav_uint16 meterDenominator
Definition: porcupine/demo/c/dr_libs/dr_wav.h:647
speex_resampler_process_interleaved_int
EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:1061
ma_backend_custom
@ ma_backend_custom
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1657
drwav_uint8
unsigned char drwav_uint8
Definition: porcupine/demo/c/dr_libs/dr_wav.h:135
ma_waveform__update_advance
static void ma_waveform__update_advance(ma_waveform *pWaveform)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45429
drflac_metadata::picture
struct drflac_metadata::@0::@6 picture
ma_channel_converter_process_pcm_frames__passthrough
static ma_result ma_channel_converter_process_pcm_frames__passthrough(ma_channel_converter *pConverter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34095
ma_logd
static MA_INLINE double ma_logd(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:799
ma_default_vfs_open_w__stdio
static ma_result ma_default_vfs_open_w__stdio(ma_vfs *pVFS, const wchar_t *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39016
DRMP3_DATA_CHUNK_SIZE
#define DRMP3_DATA_CHUNK_SIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61015
drwav_uintptr
drwav_uint32 drwav_uintptr
Definition: porcupine/demo/c/dr_libs/dr_wav.h:160
drflac_frame::pcmFramesRemaining
drflac_uint32 pcmFramesRemaining
Definition: porcupine/demo/c/dr_libs/dr_flac.h:682
DRWAV_INTERRUPT
#define DRWAV_INTERRUPT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39532
ma_log
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:588
drflac_crc8
static DRFLAC_INLINE drflac_uint8 drflac_crc8(drflac_uint8 crc, drflac_uint32 data, drflac_uint32 count)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51670
DRFLAC_DIRECTORY_NOT_EMPTY
#define DRFLAC_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51373
drmp3_seek_point::seekPosInBytes
drmp3_uint64 seekPosInBytes
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:292
ma_data_source_base::pNext
ma_data_source * pNext
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4534
ma_pcm_deinterleave_u8__optimized
static MA_INLINE void ma_pcm_deinterleave_u8__optimized(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28397
ma_pcm_interleave_u8
MA_API void ma_pcm_interleave_u8(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28373
ma_vfs_info
MA_API ma_result ma_vfs_info(ma_vfs *pVFS, ma_vfs_file file, ma_file_info *pInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38645
ma_device_config::usage
ma_aaudio_usage usage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2011
ma_offset_pcm_frames_ptr
MA_API void * ma_offset_pcm_frames_ptr(void *p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27802
ma_waveform_square_s16
static ma_int16 ma_waveform_square_s16(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45548
ma_mp3_ds_seek
static ma_result ma_mp3_ds_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42161
ma_standard_sample_rate_176400
@ ma_standard_sample_rate_176400
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:421
DRFLAC_CACHE_L1_SIZE_BYTES
#define DRFLAC_CACHE_L1_SIZE_BYTES(bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51836
drwav_init_file_write_w__internal
DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(drwav *pWav, const wchar_t *filename, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49022
drmp3d_match_frame
static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60807
ma_notch2_init
MA_API ma_result ma_notch2_init(const ma_notch2_config *pConfig, ma_notch2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31977
drflac__read_and_seek_residual
static drflac_bool32 drflac__read_and_seek_residual(drflac_bs *bs, drflac_uint32 blockSize, drflac_uint32 order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53834
ma_device__set_state
static MA_INLINE void ma_device__set_state(ma_device *pDevice, ma_uint32 newState)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5981
ma_context::captureDeviceInfoCount
ma_uint32 captureDeviceInfoCount
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3221
MA_CHANNEL_RIGHT
#define MA_CHANNEL_RIGHT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1654
drmp3_L3_imdct_gr
static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60374
MA_ALREADY_IN_USE
#define MA_ALREADY_IN_USE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1682
ma_bpf_config::order
ma_uint32 order
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2045
ma_pcm_s24_to_u8__optimized
static MA_INLINE void ma_pcm_s24_to_u8__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28791
DRFLAC_PROTOCOL_NOT_SUPPORTED
#define DRFLAC_PROTOCOL_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51398
ma_device_info::name
char name[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3077
ma_log_callback
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:579
ma_wav_ds_get_length
static ma_result ma_wav_ds_get_length(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40903
ma_int32
int32_t ma_int32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1502
drwav_smpl_loop_type
drwav_smpl_loop_type
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39679
ma_linear_resampler_interpolate_frame_s16
static void ma_linear_resampler_interpolate_frame_s16(ma_linear_resampler *pResampler, ma_int16 *MA_RESTRICT pFrameOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32582
drwav_bext::pCodingHistory
char * pCodingHistory
Definition: porcupine/demo/c/dr_libs/dr_wav.h:698
drmp3_allocation_callbacks::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:328
DRFLAC_NO_THREAD_SANITIZE
#define DRFLAC_NO_THREAD_SANITIZE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51447
ma_context::deviceEnumLock
ma_mutex deviceEnumLock
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3217
drmp3_L3_gr_info::scalefac_scale
drmp3_uint8 scalefac_scale
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59500
RESAMPLER_ERR_OVERFLOW
@ RESAMPLER_ERR_OVERFLOW
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:109
drflac_align
#define drflac_align(x, a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51423
drwav::cachedFrameCount
drwav_uint32 cachedFrameCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:889
ma_backend_callbacks::onContextEnumerateDevices
ma_result(* onContextEnumerateDevices)(ma_context *pContext, ma_enum_devices_callback_proc callback, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2126
drwav_open_and_read_pcm_frames_s16
DRWAV_API drwav_int16 * drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void *pUserData, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50830
ma_standard_sample_rate_24000
@ ma_standard_sample_rate_24000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:416
drwav_smpl_loop::cuePointId
drwav_uint32 cuePointId
Definition: porcupine/demo/c/dr_libs/dr_wav.h:520
DRWAV_CONNECTION_REFUSED
#define DRWAV_CONNECTION_REFUSED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39559
ma_default_vfs_close
static ma_result ma_default_vfs_close(ma_vfs *pVFS, ma_vfs_file file)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39238
MA_DEFAULT_PERIODS
#define MA_DEFAULT_PERIODS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:611
drwav__memory_stream_write::pDataSize
size_t * pDataSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:429
MA_DEADLOCK
#define MA_DEADLOCK
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1686
MA_CHANNEL_FRONT_LEFT_CENTER
#define MA_CHANNEL_FRONT_LEFT_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1609
ma_peak2_init
MA_API ma_result ma_peak2_init(const ma_peak2_config *pConfig, ma_peak2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32106
drwav_smpl_loop_type_backward
@ drwav_smpl_loop_type_backward
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39683
ma_factor_to_gain_db
MA_API float ma_factor_to_gain_db(float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27995
drmp3_L3_change_sign
static void drmp3_L3_change_sign(float *grbuf)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60367
drwav_container_w64
@ drwav_container_w64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39583
drmp3::dataConsumed
size_t dataConsumed
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:361
ma_lpf2_reinit
MA_API ma_result ma_lpf2_reinit(const ma_lpf2_config *pConfig, ma_lpf2 *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30850
ma_event
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2868
ma_blend_f32
MA_API void ma_blend_f32(float *pOut, float *pInA, float *pInB, float factor, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37190
drflac_close
DRFLAC_API void drflac_close(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56763
ma_aligned_malloc
MA_API void * ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37148
ma_pcm_f32_to_s24__reference
static MA_INLINE void ma_pcm_f32_to_s24__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30014
ma_opensl_recording_preset_camcorder
@ ma_opensl_recording_preset_camcorder
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1815
ma_data_converter_config::channelMapOut
ma_channel channelMapOut[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2410
c89atomic_store_explicit_ptr
static C89ATOMIC_INLINE void c89atomic_store_explicit_ptr(volatile void **dst, void *src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3915
drflac__on_read_stdio
static size_t drflac__on_read_stdio(void *pUserData, void *bufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56592
ma_audio_buffer_get_cursor_in_pcm_frames
MA_API ma_result ma_audio_buffer_get_cursor_in_pcm_frames(const ma_audio_buffer *pAudioBuffer, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38474
drflac__decode_samples__lpc
static drflac_bool32 drflac__decode_samples__lpc(drflac_bs *bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_uint8 lpcOrder, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53944
MA_CHANNEL_AUX_22
#define MA_CHANNEL_AUX_22
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1643
ma_notch2_get_latency
MA_API ma_uint32 ma_notch2_get_latency(const ma_notch2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32038
ma_data_converter_config::algorithm
ma_resample_algorithm algorithm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2416
ma_timer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3049
MA_NOT_SOCKET
#define MA_NOT_SOCKET
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1696
ma_rb_get_subbuffer_offset
MA_API size_t ma_rb_get_subbuffer_offset(ma_rb *pRB, size_t subbufferIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36787
ma_pcm_sample_s24_to_s32_no_scale
static MA_INLINE ma_int64 ma_pcm_sample_s24_to_s32_no_scale(const ma_uint8 *x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28022
drflac__read_uint8
static drflac_bool32 drflac__read_uint8(drflac_bs *bs, unsigned int bitCount, drflac_uint8 *pResult)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52074
ma_copy_and_apply_volume_factor_s16
MA_API void ma_copy_and_apply_volume_factor_s16(ma_int16 *pSamplesOut, const ma_int16 *pSamplesIn, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27837
drwav_list_labelled_cue_region
Definition: porcupine/demo/c/dr_libs/dr_wav.h:734
ma_waveform_read_pcm_frames__sawtooth
static void ma_waveform_read_pcm_frames__sawtooth(ma_waveform *pWaveform, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45709
ma_bpf_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2044
ma_context_get_device_info
MA_API ma_result ma_context_get_device_info(ma_context *pContext, ma_device_type deviceType, const ma_device_id *pDeviceID, ma_share_mode shareMode, ma_device_info *pDeviceInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26916
drwav_metadata_type_list_info_album
@ drwav_metadata_type_list_info_album
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39662
ma_context::logCallback
ma_log_proc logCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3213
ma_pcm_s24_to_s16__reference
static MA_INLINE void ma_pcm_s24_to_s16__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28840
ma_hishelf2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2164
drflac_read_pcm_frames_s16__decode_left_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57467
drwav_f64_to_f32
DRWAV_API void drwav_f64_to_f32(float *pOut, const double *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50406
MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT
#define MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33626
MA_NO_BACKEND
#define MA_NO_BACKEND
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1718
drflac__malloc_default
static void * drflac__malloc_default(size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54861
ma_aaudio_input_preset_camcorder
@ ma_aaudio_input_preset_camcorder
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1858
ma_thread_priority_high
@ ma_thread_priority_high
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2818
MA_ALREADY_CONNECTED
#define MA_ALREADY_CONNECTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1705
drwav_uint32
unsigned int drwav_uint32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39455
ma_standard_channel_map_webaudio
@ ma_standard_channel_map_webaudio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1812
DRWAV_PROTOCOL_UNAVAILABLE
#define DRWAV_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39551
drflac__be2host_32
static DRFLAC_INLINE drflac_uint32 drflac__be2host_32(drflac_uint32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51584
ma_linear_resampler_process_pcm_frames_s16
static ma_result ma_linear_resampler_process_pcm_frames_s16(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32768
ma_device__is_initialized
static ma_bool32 ma_device__is_initialized(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26366
DRFLAC_CANCELLED
#define DRFLAC_CANCELLED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51408
drwav__riff_chunk_size_w64
DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48247
ma_pcm_s32_to_u8
MA_API void ma_pcm_s32_to_u8(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29185
drflac_bool32
drflac_uint32 drflac_bool32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40014
drflac_read_pcm_frames_s32
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s32(drflac *pFlac, drflac_uint64 framesToRead, drflac_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57386
ma_clip_s32
static MA_INLINE ma_int32 ma_clip_s32(ma_int64 x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28050
MA_AT_END
#define MA_AT_END
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1712
g_maChannelPlaneRatios
static float g_maChannelPlaneRatios[MA_CHANNEL_POSITION_COUNT][6]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33636
ma_backend_callbacks::onDeviceDataLoopWakeup
ma_result(* onDeviceDataLoopWakeup)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2135
ma_performance_profile
ma_performance_profile
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1816
ma_waveform_type_sine
@ ma_waveform_type_sine
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5359
drwav__write_or_count_byte
DRWAV_PRIVATE size_t drwav__write_or_count_byte(drwav *pWav, drwav_uint8 byte)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47881
ma_ios_session_category_multi_route
@ ma_ios_session_category_multi_route
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3034
ma_apply_volume_factor_s16
MA_API void ma_apply_volume_factor_s16(ma_int16 *pSamples, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27906
drmp3__accumulate_running_pcm_frame_count
static void drmp3__accumulate_running_pcm_frame_count(drmp3 *pMP3, drmp3_uint32 pcmFrameCountIn, drmp3_uint64 *pRunningPCMFrameCount, float *pRunningPCMFrameCountFractionalPart)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62269
drwav__read_pcm_frames_and_close_f32
DRWAV_PRIVATE float * drwav__read_pcm_frames_and_close_f32(drwav *pWav, unsigned int *channels, unsigned int *sampleRate, drwav_uint64 *totalFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50762
g_ma_mp3_ds_vtable
static ma_data_source_vtable g_ma_mp3_ds_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42181
ma_flac::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41501
ma_encoding_format_unknown
@ ma_encoding_format_unknown
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4694
RESAMPLER_ERR_BAD_STATE
@ RESAMPLER_ERR_BAD_STATE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:106
ma_data_converter_process_pcm_frames__resampling_first
static ma_result ma_data_converter_process_pcm_frames__resampling_first(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35017
ma_opensl_recording_preset_generic
@ ma_opensl_recording_preset_generic
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1814
ma_linear_resampler_config::lpfNyquistFactor
double lpfNyquistFactor
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2212
drflac::bs
drflac_bs bs
Definition: porcupine/demo/c/dr_libs/dr_flac.h:759
ma_resampler_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2240
ai
drflac_oggbs__goto_next_page
static drflac_bool32 drflac_oggbs__goto_next_page(drflac_oggbs *oggbs, drflac_ogg_crc_mismatch_recovery recoveryMethod)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55491
ma_lpf::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:707
ma_device_config::periodSizeInMilliseconds
ma_uint32 periodSizeInMilliseconds
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3105
ma_notch2_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2069
drwav__metadata_parser_stage
drwav__metadata_parser_stage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46893
DRMP3_DIRECTORY_NOT_EMPTY
#define DRMP3_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40423
ma_bpf2_process_pcm_frames
MA_API ma_result ma_bpf2_process_pcm_frames(ma_bpf2 *pBPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31728
ma_pcm_deinterleave_s24
MA_API void ma_pcm_deinterleave_s24(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29116
drwav__metadata_process_info_text_chunk
DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_info_text_chunk(drwav__metadata_parser *pParser, drwav_uint64 chunkSize, drwav_metadata_type type)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47202
MA_CHANNEL_AUX_28
#define MA_CHANNEL_AUX_28
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1649
MA_CHANNEL_AUX_8
#define MA_CHANNEL_AUX_8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1629
drwav_list_labelled_cue_region::cuePointId
drwav_uint32 cuePointId
Definition: porcupine/demo/c/dr_libs/dr_wav.h:737
drwav_data_format::bitsPerSample
drwav_uint32 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_wav.h:441
ma_bpf_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2039
DRWAV_MALLOC
#define DRWAV_MALLOC(sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46285
c89atomic_load_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_load_explicit_64(volatile const c89atomic_uint64 *ptr, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3780
drwav__free_default
DRWAV_PRIVATE void drwav__free_default(void *p, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46627
drflac__decode_samples__constant
static drflac_bool32 drflac__decode_samples__constant(drflac_bs *bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53898
c89atomic_fetch_xor_explicit_64
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_fetch_xor_explicit_64(volatile c89atomic_uint64 *dst, c89atomic_uint64 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3708
ma_decoder::vfs
struct ma_decoder::@207::@208 vfs
drflac_vorbis_comment_iterator::pRunningData
const char * pRunningData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1260
drwav::channels
drwav_uint16 channels
Definition: porcupine/demo/c/dr_libs/dr_wav.h:834
ma_linear_resampler_process_pcm_frames_f32_downsample
static ma_result ma_linear_resampler_process_pcm_frames_f32_downsample(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32780
ma_semaphore_wait
MA_API ma_result ma_semaphore_wait(ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4959
MA_CONNECTION_RESET
#define MA_CONNECTION_RESET
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1704
DRMP3_OUT_OF_MEMORY
#define DRMP3_OUT_OF_MEMORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40411
ma_pcm_deinterleave_s24__optimized
static MA_INLINE void ma_pcm_deinterleave_s24__optimized(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29111
DR_WAVE_FORMAT_DVI_ADPCM
#define DR_WAVE_FORMAT_DVI_ADPCM
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39570
ma_data_converter_config::speex
struct ma_data_converter_config::@80::@82 speex
DRFLAC_CACHE_L1_BITS_REMAINING
#define DRFLAC_CACHE_L1_BITS_REMAINING(bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51838
ma_clamp
#define ma_clamp(x, lo, hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:780
ma_noise::brownian
struct ma_noise::@126::@128 brownian
drwav_int8
signed char drwav_int8
Definition: porcupine/demo/c/dr_libs/dr_wav.h:134
python.pvrecorder.CALLBACK
CALLBACK
Definition: porcupine/demo/c/pvrecorder/sdk/python/pvrecorder.py:17
ma_context::posix
struct ma_context::@110::@113 posix
MA_VERSION_MINOR
#define MA_VERSION_MINOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:22
ma_flac_get_cursor_in_pcm_frames
MA_API ma_result ma_flac_get_cursor_in_pcm_frames(ma_flac *pFlac, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41941
drmp3_open_memory_and_read_pcm_frames_f32
DRMP3_API float * drmp3_open_memory_and_read_pcm_frames_f32(const void *pData, size_t dataSize, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62507
drwav_init_file__internal_FILE
DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(drwav *pWav, FILE *pFile, drwav_chunk_proc onChunk, void *pChunkUserData, drwav_uint32 flags, drwav_metadata_type allowedMetadataTypes, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48947
drflac_oggbs__read_physical
static size_t drflac_oggbs__read_physical(drflac_oggbs *oggbs, void *bufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55454
drwav_bytes_to_u16
DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51045
ppnrespeakerdemo.porcupine_demo.driver
driver
Definition: porcupine_demo.py:47
DRFLAC_DEADLOCK
#define DRFLAC_DEADLOCK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51384
ma_is_loopback_supported
MA_API ma_bool32 ma_is_loopback_supported(ma_backend backend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5215
ma_notch2_reinit
MA_API ma_result ma_notch2_reinit(const ma_notch2_config *pConfig, ma_notch2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32001
drmp3_L3_gr_info::subblock_gain
drmp3_uint8 subblock_gain[3]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59499
drwav_smpl::midiPitchFraction
drwav_uint32 midiPitchFraction
Definition: porcupine/demo/c/dr_libs/dr_wav.h:551
ma_wcscpy_s
MA_API int ma_wcscpy_s(wchar_t *dst, size_t dstCap, const wchar_t *src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:896
ma_vfs_open
MA_API ma_result ma_vfs_open(ma_vfs *pVFS, const char *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38514
ma_channel_map_get_channel
MA_API ma_channel ma_channel_map_get_channel(const ma_channel *pChannelMap, ma_uint32 channelCount, ma_uint32 channelIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35551
drwav_cue_point::blockStart
drwav_uint32 blockStart
Definition: porcupine/demo/c/dr_libs/dr_wav.h:605
DRMP3_MODE_MONO
#define DRMP3_MODE_MONO
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59341
DRFLAC_ALREADY_CONNECTED
#define DRFLAC_ALREADY_CONNECTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51403
ma_standard_channel_map
ma_standard_channel_map
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1803
ma_device::internalSampleRate
ma_uint32 internalSampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3630
DRMP3_INVALID_ARGS
#define DRMP3_INVALID_ARGS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40409
DRFLAC_REALLOC
#define DRFLAC_REALLOC(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51341
ma_bpf::bpf2Count
ma_uint32 bpf2Count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2054
ma_backend_sndio
@ ma_backend_sndio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2799
ma_hpf
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1996
ma_decoder__postinit
static ma_result ma_decoder__postinit(const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43659
ma_lpf_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1919
ma_rb::encodedWriteOffset
volatile ma_uint32 encodedWriteOffset
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2572
drwav_list_labelled_cue_region::stringLength
drwav_uint32 stringLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:752
ma_read_proc
ma_result(* ma_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4680
ma_device_info::nativeDataFormats
struct ma_device_info::@170 nativeDataFormats[/*ma_format_count *ma_standard_sample_rate_count *MA_MAX_CHANNELS */64]
drwav__read_list_labelled_cue_region_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_list_labelled_cue_region_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata, drwav_uint64 chunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47170
drwav_smpl::midiUnityNote
drwav_uint32 midiUnityNote
Definition: porcupine/demo/c/dr_libs/dr_wav.h:548
g_ma_decoding_backend_vtable_flac
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_flac
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42111
ma_device::name
char name[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3620
add
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
drmp3_L3_gr_info::mixed_block_flag
drmp3_uint8 mixed_block_flag
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
drflac__calculate_prediction_64
static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_64(drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52459
ma_audio_buffer_ref__data_source_on_seek
static ma_result ma_audio_buffer_ref__data_source_on_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37985
stb_vorbis_info::sample_rate
unsigned int sample_rate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:126
ma_hishelf2_get_latency
MA_API ma_uint32 ma_hishelf2_get_latency(const ma_hishelf2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32419
ma_encoding_format_flac
@ ma_encoding_format_flac
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4696
ma_decoder::currentReadPos
size_t currentReadPos
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5218
c89atomic_memory_order_relaxed
#define c89atomic_memory_order_relaxed
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3288
DRFLAC_NOT_DIRECTORY
#define DRFLAC_NOT_DIRECTORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51371
drflac__reload_cache
static drflac_bool32 drflac__reload_cache(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51910
DRWAV_BUSY
#define DRWAV_BUSY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39530
drwav_smpl_loop::sampleFraction
drwav_uint32 sampleFraction
Definition: porcupine/demo/c/dr_libs/dr_wav.h:532
DRFLAC_UNAVAILABLE
#define DRFLAC_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51379
ma_biquad::a2
ma_biquad_coefficient a2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1865
drflac::bitsPerSample
drflac_uint8 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_flac.h:710
drwav_clamp
#define drwav_clamp(x, lo, hi)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46306
ma_uint32
uint32_t ma_uint32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1503
ma_rand_s32
static MA_INLINE ma_int32 ma_rand_s32(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2490
ma_device_handle_backend_data_callback
MA_API ma_result ma_device_handle_backend_data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27678
ma_encoder__on_uninit_wav
static void ma_encoder__on_uninit_wav(ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45157
ma_bpf
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2050
drwav_uninit
DRWAV_API drwav_result drwav_uninit(drwav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49216
ma_notch2_config_init
MA_API ma_notch2_config ma_notch2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31928
ma_pcm_interleave_f32
MA_API void ma_pcm_interleave_f32(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30195
drmp3_gcf_u32
static DRMP3_INLINE drmp3_uint32 drmp3_gcf_u32(drmp3_uint32 a, drmp3_uint32 b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61053
c89atomic_fetch_or_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_fetch_or_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3730
ma_decoder_config::encodingFormat
ma_encoding_format encodingFormat
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4760
ma_pcm_s32_to_f32
MA_API void ma_pcm_s32_to_f32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29410
ma_bpf2_process_pcm_frame_s16
static MA_INLINE void ma_bpf2_process_pcm_frame_s16(ma_bpf2 *pBPF, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31718
c89atomic_int64
signed long long c89atomic_int64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2589
ma_apply_volume_factor_pcm_frames_u8
MA_API void ma_apply_volume_factor_pcm_frames_u8(ma_uint8 *pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27964
drwav__on_seek_memory_write
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49129
ma_apply_volume_factor_u8
MA_API void ma_apply_volume_factor_u8(ma_uint8 *pSamples, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27901
drflac__decode_samples_with_residual__rice__scalar
static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar(drflac_bs *bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pSamplesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52919
ma_rb_commit_read
MA_API ma_result ma_rb_commit_read(ma_rb *pRB, size_t sizeInBytes, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36493
drflac__read_and_seek_residual__rice
static drflac_bool32 drflac__read_and_seek_residual__rice(drflac_bs *bs, drflac_uint32 count, drflac_uint8 riceParam)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53733
ma_log_proc
void(* ma_log_proc)(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3008
ma_bpf_reinit__internal
static ma_result ma_bpf_reinit__internal(const ma_bpf_config *pConfig, ma_bpf *pBPF, ma_bool32 isNew)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31761
ma_waveform
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5373
ma_context_config::logCallback
ma_log_proc logCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3162
ma_pcm_rb_init_ex
MA_API ma_result ma_pcm_rb_init_ex(ma_format format, ma_uint32 channels, ma_uint32 subbufferSizeInFrames, ma_uint32 subbufferCount, ma_uint32 subbufferStrideInFrames, void *pOptionalPreallocatedBuffer, const ma_allocation_callbacks *pAllocationCallbacks, ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36814
drmp3_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:326
ma_resampler_process_pcm_frames
MA_API ma_result ma_resampler_process_pcm_frames(ma_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33398
MA_NO_HOST
#define MA_NO_HOST
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1708
ma_context_config::pServerName
const char * pServerName
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3173
ma_decoder__init_allocation_callbacks
static ma_result ma_decoder__init_allocation_callbacks(const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43547
ma_pcm_f32_to_s32
MA_API void ma_pcm_f32_to_s32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30143
ma_resampler_process_pcm_frames__seek__linear
static ma_result ma_resampler_process_pcm_frames__seek__linear(ma_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33286
drwav_uint32
unsigned int drwav_uint32
Definition: porcupine/demo/c/dr_libs/dr_wav.h:139
drwav_smpl
Definition: porcupine/demo/c/dr_libs/dr_wav.h:538
ma_copy_and_apply_volume_factor_f32
MA_API void ma_copy_and_apply_volume_factor_f32(float *pSamplesOut, const float *pSamplesIn, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27888
ma_device::duplexRB
ma_duplex_rb duplexRB
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2626
DRFLAC_METADATA_BLOCK_TYPE_INVALID
#define DRFLAC_METADATA_BLOCK_TYPE_INVALID
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40078
drflac__init_from_info
static void drflac__init_from_info(drflac *pFlac, const drflac_init_info *pInit)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55920
ma_decoder_tell_proc
ma_result(* ma_decoder_tell_proc)(ma_decoder *pDecoder, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4737
ma_audio_buffer_ref
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4562
drwav_read_pcm_frames_s16__msadpcm
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav *pWav, drwav_uint64 samplesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49566
ma_decoding_backend_init_memory__mp3
static ma_result ma_decoding_backend_init_memory__mp3(void *pUserData, const void *pData, size_t dataSize, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42700
ma__realloc_default
static void * ma__realloc_default(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1829
ma_encoder::onSeek
ma_encoder_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5328
ma_linear_resampler::inTimeFrac
ma_uint32 inTimeFrac
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2210
MA_VERSION_MAJOR
#define MA_VERSION_MAJOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:21
MA_STATE_STOPPED
#define MA_STATE_STOPPED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1626
ma_pcm_s24_to_f32__optimized
static MA_INLINE void ma_pcm_s24_to_f32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29015
ma_decoder_init_file_w
MA_API ma_result ma_decoder_init_file_w(const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44714
ma_waveform_sawtooth_s16
static ma_int16 ma_waveform_sawtooth_s16(double time, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45578
drflac_cuesheet_track_index
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1285
ma_bpf_get_latency
MA_API ma_uint32 ma_bpf_get_latency(const ma_bpf *pBPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31913
ma_copy_and_apply_volume_factor_pcm_frames_s32
MA_API void ma_copy_and_apply_volume_factor_pcm_frames_s32(ma_int32 *pPCMFramesOut, const ma_int32 *pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27941
ma_context_uninit__null
static ma_result ma_context_uninit__null(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6645
drmp3_seek_origin_current
@ drmp3_seek_origin_current
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40494
MA_SIZE_MAX
#define MA_SIZE_MAX
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1549
drflac_oggbs::onRead
drflac_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55442
drwav_read_pcm_frames_f32__msadpcm
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50206
ma_wav_ds_get_cursor
static ma_result ma_wav_ds_get_cursor(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40898
drwav__read_cue_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47001
drflac__decode_samples_with_residual
static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs *bs, drflac_uint32 bitsPerSample, drflac_uint32 blockSize, drflac_uint32 order, drflac_int32 shift, const drflac_int32 *coefficients, drflac_int32 *pDecodedSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:53766
drmp3_uint64
unsigned long long drmp3_uint64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40364
drwav_uintptr
drwav_uint32 drwav_uintptr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39476
drwav_init_write
DRWAV_API drwav_bool32 drwav_init_write(drwav *pWav, const drwav_data_format *pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void *pUserData, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48378
ma_device_id::winmm
ma_uint32 winmm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3059
ma_hpf2_config_init
MA_API ma_hpf2_config ma_hpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31146
drflac_frame_header::blockSizeInPCMFrames
drflac_uint16 blockSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:658
drflac_fopen
static drflac_result drflac_fopen(FILE **ppFile, const char *pFilePath, const char *pOpenMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56489
ma_tzcnt32
static MA_INLINE unsigned int ma_tzcnt32(unsigned int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46027
ma_opensl_recording_preset
ma_opensl_recording_preset
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1811
ma__is_channel_map_valid
static ma_bool32 ma__is_channel_map_valid(const ma_channel *channelMap, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26141
ma_format_u8
@ ma_format_u8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1786
ma_allocation_callbacks_init_copy
static ma_result ma_allocation_callbacks_init_copy(ma_allocation_callbacks *pDst, const ma_allocation_callbacks *pSrc)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1922
drmp3_hdr_frame_samples
static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59559
drflac_init_info::hasMetadataBlocks
drflac_bool32 hasMetadataBlocks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54803
DRFLAC_PATH_TOO_LONG
#define DRFLAC_PATH_TOO_LONG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51369
drwav_init_memory_write_sequential
DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav *pWav, void **ppData, size_t *pDataSize, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49205
DRWAV_BAD_MESSAGE
#define DRWAV_BAD_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39542
ma_loshelf2_config::frequency
double frequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2135
drwav_metadata_type_list_note
@ drwav_metadata_type_list_note
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39653
DRWAV_DOES_NOT_EXIST
#define DRWAV_DOES_NOT_EXIST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39518
ma_lcg_rand_f32
static MA_INLINE float ma_lcg_rand_f32(ma_lcg *pLCG)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2464
ma_data_source_map
MA_API ma_result ma_data_source_map(ma_data_source *pDataSource, void **ppFramesOut, ma_uint64 *pFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37581
ma_apply_volume_factor_s32
MA_API void ma_apply_volume_factor_s32(ma_int32 *pSamples, ma_uint64 sampleCount, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27916
ma_device_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3128
c89atomic_exchange_explicit_f64
static C89ATOMIC_INLINE double c89atomic_exchange_explicit_f64(volatile double *dst, double src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4162
DRMP3_COPY_MEMORY
#define DRMP3_COPY_MEMORY(dst, src, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61022
c89atomic_compare_exchange_strong_explicit_16
c89atomic_bool c89atomic_compare_exchange_strong_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 *expected, c89atomic_uint16 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3821
ma_pcm_rb
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2593
stb_vorbis_flush_pushdata
void stb_vorbis_flush_pushdata(stb_vorbis *f)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4316
ma_loshelf2_process_pcm_frame_s16
static MA_INLINE void ma_loshelf2_process_pcm_frame_s16(ma_loshelf2 *pFilter, ma_int16 *pFrameOut, const ma_int16 *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32274
ma_waveform_set_frequency
MA_API ma_result ma_waveform_set_frequency(ma_waveform *pWaveform, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45490
ma_data_converter_set_rate_ratio
MA_API ma_result ma_data_converter_set_rate_ratio(ma_data_converter *pConverter, float ratioInOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35365
DRMP3_PEEK_BITS
#define DRMP3_PEEK_BITS(n)
drwav_metadata_type_smpl
@ drwav_metadata_type_smpl
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39647
DRMP3_FALSE
#define DRMP3_FALSE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40377
DRWAV_PROTOCOL_NOT_SUPPORTED
#define DRWAV_PROTOCOL_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39552
ma_data_source_base::loopEndInFrames
ma_uint64 loopEndInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4532
DRMP3_SUCCESS
#define DRMP3_SUCCESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40407
drwav_fmt::blockAlign
drwav_uint16 blockAlign
Definition: porcupine/demo/c/dr_libs/dr_wav.h:317
ma_lpf1_process_pcm_frame_s16
static MA_INLINE void ma_lpf1_process_pcm_frame_s16(ma_lpf1 *pLPF, ma_int16 *pY, const ma_int16 *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30730
ma_round_to_power_of_2
static MA_INLINE unsigned int ma_round_to_power_of_2(unsigned int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1791
ma_noise_init
MA_API ma_result ma_noise_init(const ma_noise_config *pConfig, ma_noise *pNoise)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45865
ma_pcm_s16_to_s24__optimized
static MA_INLINE void ma_pcm_s16_to_s24__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28517
DRWAV_NO_NETWORK
#define DRWAV_NO_NETWORK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39546
ma_channel_map_get_default_channel
MA_API ma_channel ma_channel_map_get_default_channel(ma_uint32 channelCount, ma_uint32 channelIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35437
drflac_subframe::pSamplesS32
drflac_int32 * pSamplesS32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:637
drflac_bs::cache
drflac_cache_t cache
Definition: porcupine/demo/c/dr_libs/dr_flac.h:614
ma_rb_seek_read
MA_API ma_result ma_rb_seek_read(ma_rb *pRB, size_t offsetInBytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36626
ma_timer::counterD
double counterD
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3052
ma_bpf2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2028
ma_context_init_backend_apis
static ma_result ma_context_init_backend_apis(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26501
ma__malloc_default
static void * ma__malloc_default(size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1823
DRFLAC_SUBFRAME_FIXED
#define DRFLAC_SUBFRAME_FIXED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51414
ma_seek_proc
ma_result(* ma_seek_proc)(void *pUserData, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4681
ma_decoder_init__internal
static ma_result ma_decoder_init__internal(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43765
ma_context_config::pClientName
const char * pClientName
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3183
drmp3_L3_gr_info::sfbtab
const drmp3_uint8 * sfbtab
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59496
drmp3_read_proc
size_t(* drmp3_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40503
DRFLAC_INVALID_ARGS
#define DRFLAC_INVALID_ARGS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51359
ma_device::pContext
ma_context * pContext
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3586
drflac_read_pcm_frames_s32__decode_independent_stereo__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57291
ma_channel_converter::isSimpleShuffle
ma_bool32 isSimpleShuffle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2381
ma_lpf
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1928
c89atomic_exchange_explicit_ptr
static C89ATOMIC_INLINE void * c89atomic_exchange_explicit_ptr(volatile void **dst, void *src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3919
ma_audio_buffer_init
MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config *pConfig, ma_audio_buffer *pAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38352
drwav_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/dr_wav.h:409
ma_rb::ownsBuffer
ma_bool32 ownsBuffer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2573
ma_hpf1_process_pcm_frame_s16
static MA_INLINE void ma_hpf1_process_pcm_frame_s16(ma_hpf1 *pHPF, ma_int16 *pY, const ma_int16 *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31241
ma_path_extension_equal_w
static ma_bool32 ma_path_extension_equal_w(const wchar_t *path, const wchar_t *extension)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44200
ma_aaudio_content_type_default
@ ma_aaudio_content_type_default
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1846
drmp3__seeking_mp3_frame_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62281
drflac__on_read_memory
static size_t drflac__on_read_memory(void *pUserData, void *bufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56658
ma_mp3_dr_callback__seek
static drmp3_bool32 ma_mp3_dr_callback__seek(void *pUserData, int offset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42227
drwav_uint64
unsigned long long drwav_uint64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39468
ma_encoder__internal_on_seek_wav
static drwav_bool32 ma_encoder__internal_on_seek_wav(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45112
drflac__crc32_table
static drflac_uint32 drflac__crc32_table[]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55254
DRMP3_TOO_BIG
#define DRMP3_TOO_BIG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40418
ma_data_source_get_length_in_pcm_frames
MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37710
drwav_bext::maxMomentaryLoudness
drwav_uint16 maxMomentaryLoudness
Definition: porcupine/demo/c/dr_libs/dr_wav.h:708
ma_wav_ds_read
static ma_result ma_wav_ds_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40883
MA_DEVICE_OP_START__NULL
#define MA_DEVICE_OP_START__NULL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6219
MA_DEVICE_NOT_STOPPED
#define MA_DEVICE_NOT_STOPPED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1727
ma_wav_get_cursor_in_pcm_frames
MA_API ma_result ma_wav_get_cursor_in_pcm_frames(ma_wav *pWav, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41303
ma_bpf2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2030
ma_pcm_s32_to_s24
MA_API void ma_pcm_s32_to_s24(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29330
c89atomic_is_lock_free_64
static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_64(volatile void *ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3892
DRFLAC_METADATA_BLOCK_TYPE_PICTURE
#define DRFLAC_METADATA_BLOCK_TYPE_PICTURE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40077
ma_waveform_config::type
ma_waveform_type type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5366
drwav__memory_stream::data
const drwav_uint8 * data
Definition: porcupine/demo/c/dr_libs/dr_wav.h:420
c89atomic_load_f32
#define c89atomic_load_f32(ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4174
drwav_read_pcm_frames
DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav *pWav, drwav_uint64 framesToRead, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49356
ma_pcm_interleave_s16
MA_API void ma_pcm_interleave_s16(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28721
ma_pcm_deinterleave_f32
MA_API void ma_pcm_deinterleave_f32(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30224
ma_hpf1::r1
ma_biquad_coefficient r1[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1966
ma_pcm_deinterleave_s32__optimized
static MA_INLINE void ma_pcm_deinterleave_s32__optimized(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29478
ma_device_config::periods
ma_uint32 periods
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3106
ma_decoding_backend_config::preferredFormat
ma_format preferredFormat
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4717
drmp3_config::sampleRate
drmp3_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:337
ma_hpf1_init
MA_API ma_result ma_hpf1_init(const ma_hpf1_config *pConfig, ma_hpf1 *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31166
drwav_s16_to_s32
DRWAV_API void drwav_s16_to_s32(drwav_int32 *pOut, const drwav_int16 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50664
drmp3_hdr_sample_rate_hz
static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59554
drflac_ogg_page_header::capturePattern
drflac_uint8 capturePattern[4]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54777
DRWAV_API
#define DRWAV_API
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39506
ma_pcm_s16_to_u8__optimized
static MA_INLINE void ma_pcm_s16_to_u8__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28446
ma_default_vfs_seek
static ma_result ma_default_vfs_seek(ma_vfs *pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39285
ma_decoder__on_seek_vfs
static ma_bool32 ma_decoder__on_seek_vfs(ma_decoder *pDecoder, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44257
ma_channel_converter_process_pcm_frames__stereo_to_mono
static ma_result ma_channel_converter_process_pcm_frames__stereo_to_mono(ma_channel_converter *pConverter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34301
ma_device::startStopLock
ma_mutex startStopLock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2616
c89atomic_store_explicit_16
#define c89atomic_store_explicit_16(dst, src, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3786
MA_DEVICE_OP_SUSPEND__NULL
#define MA_DEVICE_OP_SUSPEND__NULL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6220
ma_mp3_uninit
MA_API void ma_mp3_uninit(ma_mp3 *pMP3, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42411
drmp3_L3_decode
static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60415
drmp3_L12_subband_alloc::band_count
drmp3_uint8 band_count
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59492
ma_audio_buffer_ref_read_pcm_frames
MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref *pAudioBufferRef, void *pFramesOut, ma_uint64 frameCount, ma_bool32 loop)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38090
drwav
Definition: porcupine/demo/c/dr_libs/dr_wav.h:805
ma_biquad_config::b2
double b2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1849
stb_vorbis_info::channels
int channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:127
ma_context_config::noAudioSessionDeactivate
ma_bool32 noAudioSessionDeactivate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2161
drwav_metadata_type_cue
@ drwav_metadata_type_cue
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39649
ma_device_set_master_gain_db
MA_API ma_result ma_device_set_master_gain_db(ma_device *pDevice, float gainDB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27648
ma_resampler_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2242
ma_standard_channel_map_default
@ ma_standard_channel_map_default
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1813
ma_data_source_base::loopBegInFrames
ma_uint64 loopBegInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4531
c89atomic_uint64
unsigned long long c89atomic_uint64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2590
DRMP3_BAD_PROTOCOL
#define DRMP3_BAD_PROTOCOL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40446
ma_context_get_device_info__null
static ma_result ma_context_get_device_info__null(ma_context *pContext, ma_device_type deviceType, const ma_device_id *pDeviceID, ma_device_info *pDeviceInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6363
ma_pcm_u8_to_s24__reference
static MA_INLINE void ma_pcm_u8_to_s24__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28135
ma_rb__get_read_ptr
static MA_INLINE void * ma_rb__get_read_ptr(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36344
drwav_bext::pUMID
drwav_uint8 * pUMID
Definition: porcupine/demo/c/dr_libs/dr_wav.h:702
ma_decoder_config::algorithm
ma_resample_algorithm algorithm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5180
ma_post_error
static ma_result ma_post_error(ma_device *pDevice, ma_uint32 logLevel, const char *message, ma_result resultCode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5456
ma_backend_null
@ ma_backend_null
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2808
ma_device_info_add_native_data_format
MA_API void ma_device_info_add_native_data_format(ma_device_info *pDeviceInfo, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 flags)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5039
drwav_allocation_callbacks_from_miniaudio
static drwav_allocation_callbacks drwav_allocation_callbacks_from_miniaudio(const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40921
ma_performance_profile_low_latency
@ ma_performance_profile_low_latency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1818
drmp3_int8
signed char drmp3_int8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40346
ma_radians_to_degrees
static MA_INLINE double ma_radians_to_degrees(double radians)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:844
ma_clip_pcm_frames_f32
MA_INLINE void ma_clip_pcm_frames_f32(float *p, ma_uint32 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5091
ma_notch2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2080
ma_mutex
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2846
drwav__write_or_count_f32ne_to_le
DRWAV_PRIVATE size_t drwav__write_or_count_f32ne_to_le(drwav *pWav, float value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47911
drwav_read_pcm_frames_s32__alaw
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50565
DRMP3_TOO_MANY_LINKS
#define DRMP3_TOO_MANY_LINKS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40435
ma_decoder_init_flac__internal
static ma_result ma_decoder_init_flac__internal(const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42121
ma_wav::onTell
ma_tell_proc onTell
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40863
ma_resample_algorithm_linear
@ ma_resample_algorithm_linear
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2236
DRWAV_SMPL_BYTES
#define DRWAV_SMPL_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46878
ma_device::isOwnerOfContext
ma_bool32 isOwnerOfContext
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3602
ma_data_source_base::vtable
const ma_data_source_vtable * vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4528
ma_audio_buffer_ref::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4564
DRWAV_IO_ERROR
#define DRWAV_IO_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39531
DRWAV_INVALID_DATA
#define DRWAV_INVALID_DATA
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39544
drwav_read_pcm_frames_s16__alaw
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49963
ma_mp3_seek_to_pcm_frame
MA_API ma_result ma_mp3_seek_to_pcm_frame(ma_mp3 *pMP3, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42495
drflac_read_pcm_frames_f32__decode_left_side
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58310
drwav_init_file_write__internal
DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal(drwav *pWav, const char *filename, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49014
ma_pcm_u8_to_s16
MA_API void ma_pcm_u8_to_s16(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28110
ma_waveform__data_source_on_get_data_format
static ma_result ma_waveform__data_source_on_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45404
drwav_mulaw_to_s16
DRWAV_API void drwav_mulaw_to_s16(drwav_int16 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50126
stb_vorbis_decode_frame_pushdata
int stb_vorbis_decode_frame_pushdata(stb_vorbis *f, const unsigned char *datablock, int datablock_length_in_bytes, int *channels, float ***output, int *samples)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4419
drmp3__free_default
static void drmp3__free_default(void *p, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61088
ma_copy_pcm_frames
MA_API void ma_copy_pcm_frames(void *dst, const void *src, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27780
drwav__metadata_parser::extraCapacity
drwav_uint64 extraCapacity
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46909
ma_channel_converter_config::mixingMode
ma_channel_mix_mode mixingMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2365
ma_rb::pBuffer
void * pBuffer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2567
ma_decoder_read_bytes
static ma_result ma_decoder_read_bytes(ma_decoder *pDecoder, void *pBufferOut, size_t bytesToRead, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40588
DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED
#define DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51400
DRFLAC_CACHE_L2_LINE_COUNT
#define DRFLAC_CACHE_L2_LINE_COUNT(bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51845
ma_lpf1_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1891
drwav__ieee_to_f32
DRWAV_PRIVATE void drwav__ieee_to_f32(float *pOut, const drwav_uint8 *pIn, size_t sampleCount, unsigned int bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50169
ma_bpf_config_init
MA_API ma_bpf_config ma_bpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31747
ma_decoder__preinit_vfs_w
static ma_result ma_decoder__preinit_vfs_w(ma_vfs *pVFS, const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44484
ma_offset_pcm_frames_const_ptr
const MA_API void * ma_offset_pcm_frames_const_ptr(const void *p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27807
ma_sqrtd
static MA_INLINE double ma_sqrtd(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:811
ma_vfs_callbacks::onInfo
ma_result(* onInfo)(ma_vfs *pVFS, ma_vfs_file file, ma_file_info *pInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4657
drmp3_L3_intensity_stereo
static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60179
ma_lpf2__get_biquad_config
static MA_INLINE ma_biquad_config ma_lpf2__get_biquad_config(const ma_lpf2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30796
drwav_read_pcm_frames_f32__alaw
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50263
drwav_inst::lowVelocity
drwav_int8 lowVelocity
Definition: porcupine/demo/c/dr_libs/dr_wav.h:580
drwav_read_pcm_frames_be
DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav *pWav, drwav_uint64 framesToRead, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49348
ma_biquad_coefficient::s32
ma_int32 s32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1844
drwav__bswap_s32
static DRWAV_INLINE drwav_int32 drwav__bswap_s32(drwav_int32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46501
drflac_init_info::oggBosHeader
drflac_ogg_page_header oggBosHeader
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54809
drwav_acid::meterNumerator
drwav_uint16 meterNumerator
Definition: porcupine/demo/c/dr_libs/dr_wav.h:648
drmp3_read_pcm_frames_raw
static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3 *pMP3, drmp3_uint64 framesToRead, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62008
DRFLAC_IO_ERROR
#define DRFLAC_IO_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51377
ma_decoder_init_vfs_flac
MA_API ma_result ma_decoder_init_vfs_flac(ma_vfs *pVFS, const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44428
DRMP3_STOP_BLOCK_TYPE
#define DRMP3_STOP_BLOCK_TYPE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59340
drmp3_open_file_and_read_pcm_frames_f32
DRMP3_API float * drmp3_open_file_and_read_pcm_frames_f32(const char *filePath, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62524
drwav_read_pcm_frames_s32le
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50638
ma_notch2_process_pcm_frames
MA_API ma_result ma_notch2_process_pcm_frames(ma_notch2 *pFilter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32029
ma_pcm_interleave_s32
MA_API void ma_pcm_interleave_s32(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29454
ma_flac::onTell
ma_tell_proc onTell
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41504
ma_opensl_stream_type_system
@ ma_opensl_stream_type_system
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1803
ma_version
MA_API void ma_version(ma_uint32 *pMajor, ma_uint32 *pMinor, ma_uint32 *pRevision)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:692
DRFLAC_CACHE_L2_SIZE_BYTES
#define DRFLAC_CACHE_L2_SIZE_BYTES(bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51844
drwav_init_file_with_metadata
DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav *pWav, const char *filename, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48983
c89atomic_fetch_xor_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_fetch_xor_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3675
DRFLAC_VERSION_STRING
#define DRFLAC_VERSION_STRING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39983
drwavGUID_W64_FACT
static const drwav_uint8 drwavGUID_W64_FACT[16]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46390
drwav__metadata_parser::metadataCount
drwav_uint32 metadataCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46905
drwav_read_pcm_frames_s32__msadpcm
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50512
MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE
#define MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1901
ma_audio_buffer_unmap
MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer *pAudioBuffer, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38456
ma_aaudio_input_preset_voice_communication
@ ma_aaudio_input_preset_voice_communication
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1861
MA_ASSUME
#define MA_ASSUME(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:408
ma_peak2_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2106
g_maStandardSampleRatePriorities
static ma_uint32 g_maStandardSampleRatePriorities[]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:640
ma_pcm_u8_to_f32__optimized
static MA_INLINE void ma_pcm_u8_to_f32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28284
drflac_streaminfo::totalPCMFrameCount
drflac_uint64 totalPCMFrameCount
Definition: porcupine/demo/c/dr_libs/dr_flac.h:405
drmp3_L3_gr_info::scalefac_compress
drmp3_uint16 scalefac_compress
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59497
ma_flac_ds_get_data_format
static ma_result ma_flac_ds_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41534
ma_opensl_stream_type_default
@ ma_opensl_stream_type_default
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1801
MA_LOG_LEVEL_ERROR
#define MA_LOG_LEVEL_ERROR
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1591
c89atomic_flag
c89atomic_uint8 c89atomic_flag
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3797
drflac_oggbs__seek_physical
static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs *oggbs, drflac_uint64 offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55460
ma_backend_callbacks::onDeviceStart
ma_result(* onDeviceStart)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2130
drmp3_L3_gr_info::preflag
drmp3_uint8 preflag
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59500
drwav__metadata_parser_stage_count
@ drwav__metadata_parser_stage_count
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46895
ma_data_converter_process_pcm_frames__format_only
static ma_result ma_data_converter_process_pcm_frames__format_only(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34720
drflac_version_string
const DRFLAC_API char * drflac_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51436
drwav__read_fmt
DRWAV_PRIVATE drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSeek, void *pUserData, drwav_container container, drwav_uint64 *pRunningBytesReadOut, drwav_fmt *fmtOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46770
drflac_init_info::runningFilePos
drflac_uint64 runningFilePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54801
ma_resource_format
ma_resource_format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5145
ma_audio_buffer_ref__data_source_on_get_data_format
static ma_result ma_audio_buffer_ref__data_source_on_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38000
ma_device_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3129
DRMP3_VERSION_REVISION
#define DRMP3_VERSION_REVISION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40343
ma_data_converter_process_pcm_frames__resample_with_format_conversion
static ma_result ma_data_converter_process_pcm_frames__resample_with_format_conversion(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34759
ma_resampler_config::lpfNyquistFactor
double lpfNyquistFactor
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2250
drmp3_int32
signed int drmp3_int32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40350
DRWAV_BEXT_RESERVED_BYTES
#define DRWAV_BEXT_RESERVED_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46887
DRFLAC_OGG_CAPTURE_PATTERN_CRC32
#define DRFLAC_OGG_CAPTURE_PATTERN_CRC32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55247
DRWAV_ACID_BYTES
#define DRWAV_ACID_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46881
ma_audio_buffer_config_init
MA_API ma_audio_buffer_config ma_audio_buffer_config_init(ma_format format, ma_uint32 channels, ma_uint64 sizeInFrames, const void *pData, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38266
ma_expd
static MA_INLINE double ma_expd(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:793
drflac_open_and_read_pcm_frames_f32
DRFLAC_API float * drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void *pUserData, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59099
ma_decoder::outputChannels
ma_uint32 outputChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5204
drflac_open_and_read_pcm_frames_s32
DRFLAC_API drflac_int32 * drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void *pUserData, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59063
MA_CHANNEL_AUX_6
#define MA_CHANNEL_AUX_6
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1627
ma_pcm_s16_to_s24__reference
static MA_INLINE void ma_pcm_s16_to_s24__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28502
drwav_metadata_type_acid
@ drwav_metadata_type_acid
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39650
ma_version_string
const MA_API char * ma_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:707
drwav__metadata_parser::stage
drwav__metadata_parser_stage stage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46903
ma_device_config::noAutoResample
ma_bool32 noAutoResample
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1993
MA_MIN_CHANNELS
#define MA_MIN_CHANNELS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1752
drflac_ogg_page_header::serialNumber
drflac_uint32 serialNumber
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54781
ma_audio_buffer_uninit_ex
static void ma_audio_buffer_uninit_ex(ma_audio_buffer *pAudioBuffer, ma_bool32 doFree)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38335
ma_context
struct ma_context ma_context
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1597
drflac_seek_to_pcm_frame
DRFLAC_API drflac_bool32 drflac_seek_to_pcm_frame(drflac *pFlac, drflac_uint64 pcmFrameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58917
drflac_cuesheet_track::preEmphasis
drflac_bool8 preEmphasis
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1299
ma_hishelf2_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2160
ma_data_converter_config::linear
struct ma_data_converter_config::@80::@81 linear
ma_linear_resampler::s16
ma_int16 s16[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2214
ma_hpf1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1961
ma_biquad_config::a2
double a2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1852
ma_pcm_f32_to_s32__reference
static MA_INLINE void ma_pcm_f32_to_s32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30093
DRFLAC_BUSY
#define DRFLAC_BUSY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51376
MA_CHANNEL_AUX_15
#define MA_CHANNEL_AUX_15
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1636
drwav_inst::fineTuneCents
drwav_int8 fineTuneCents
Definition: porcupine/demo/c/dr_libs/dr_wav.h:576
python.setup.version
version
Definition: porcupine/binding/python/setup.py:70
drmp3_mix_f32
static DRMP3_INLINE float drmp3_mix_f32(float x, float y, float a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61043
MA_ERROR
#define MA_ERROR
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1660
ma_degrees_to_radians_f
static MA_INLINE float ma_degrees_to_radians_f(float degrees)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:849
DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT
#define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51419
ma_aaudio_input_preset_generic
@ ma_aaudio_input_preset_generic
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1857
ma_device_id::jack
int jack
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3062
ma_standard_sample_rate_96000
@ ma_standard_sample_rate_96000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:420
ma_waveform_type
ma_waveform_type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5353
ma_device_config::pulse
struct ma_device_config::@101 pulse
c89atomic_store_explicit_f64
static C89ATOMIC_INLINE void c89atomic_store_explicit_f64(volatile double *dst, double src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4136
ma_get_standard_channel_map
MA_API void ma_get_standard_channel_map(ma_standard_channel_map standardChannelMap, ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36147
ma_decoding_backend_get_channel_map__wav
static ma_result ma_decoding_backend_get_channel_map__wav(void *pUserData, ma_data_source *pBackend, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41470
drmp3_uint32
unsigned int drmp3_uint32
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:109
drflac__read_int32
static drflac_bool32 drflac__read_int32(drflac_bs *bs, unsigned int bitCount, drflac_int32 *pResult)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51996
MA_CHANNEL_AUX_30
#define MA_CHANNEL_AUX_30
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1651
drflac_read_pcm_frames_s16__decode_right_side
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57727
ma_default_vfs_init
MA_API ma_result ma_default_vfs_init(ma_default_vfs *pVFS, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39337
drflac__unsynchsafe_32
static DRFLAC_INLINE drflac_uint32 drflac__unsynchsafe_32(drflac_uint32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51605
ma_hpf::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1998
ma_decoder_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5173
ma_audio_buffer_ref__data_source_on_get_length
static ma_result ma_audio_buffer_ref__data_source_on_get_length(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38020
DRFLAC_INTERRUPT
#define DRFLAC_INTERRUPT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51378
ma_interleave_pcm_frames
MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void **ppDeinterleavedPCMFrames, void *pInterleavedPCMFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30362
drwav_uint16
unsigned short drwav_uint16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39453
ma_loshelf2_config::shelfSlope
double shelfSlope
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2134
ma_hpf_config::order
ma_uint32 order
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1991
ma_copy_memory_64
static MA_INLINE void ma_copy_memory_64(void *dst, const void *src, ma_uint64 sizeInBytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1732
drwav_init_file_write_sequential_pcm_frames_w
DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav *pWav, const wchar_t *filename, const drwav_data_format *pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49053
drmp3::decoder
drmp3dec decoder
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:342
drflac_metadata::type
drflac_uint32 type
Definition: porcupine/demo/c/dr_libs/dr_flac.h:415
ma_copy_and_apply_volume_factor_pcm_frames_s16
MA_API void ma_copy_and_apply_volume_factor_pcm_frames_s16(ma_int16 *pPCMFramesOut, const ma_int16 *pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27931
drflac__read_utf8_coded_number
static drflac_result drflac__read_utf8_coded_number(drflac_bs *bs, drflac_uint64 *pNumberOut, drflac_uint8 *pCRCOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52367
drwav_open_file_and_read_pcm_frames_f32_w
DRWAV_API float * drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t *filename, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50950
ma_data_converter_config::formatIn
ma_format formatIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2403
drmp3_L3_imdct36
static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60278
drwav__on_read_stdio
DRWAV_PRIVATE size_t drwav__on_read_stdio(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48931
ma_hpf_process_pcm_frames
MA_API ma_result ma_hpf_process_pcm_frames(ma_hpf *pHPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31535
drflac_read_pcm_frames_s32__decode_mid_side
static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int32 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:57263
ma_thread_wait__posix
static void ma_thread_wait__posix(ma_thread *pThread)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4532
drwav_unknown_metadata::dataSizeInBytes
drwav_uint32 dataSizeInBytes
Definition: porcupine/demo/c/dr_libs/dr_wav.h:779
drwav_bext
Definition: porcupine/demo/c/dr_libs/dr_wav.h:679
ma_notch2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2082
ma_hpf_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1988
ma_wav_get_data_format
MA_API ma_result ma_wav_get_data_format(ma_wav *pWav, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41254
drmp3_uint8
unsigned char drmp3_uint8
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:105
DRWAV_LIST_LABEL_OR_NOTE_BYTES
#define DRWAV_LIST_LABEL_OR_NOTE_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46890
MA_STATE_STOPPING
#define MA_STATE_STOPPING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1629
ma_audio_buffer::ref
ma_audio_buffer_ref ref
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4599
ma_itoa_s
MA_API int ma_itoa_s(int value, char *dst, size_t dstSizeInBytes, int radix)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1047
ma_thread_create
static ma_result ma_thread_create(ma_thread *pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void *pData, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4721
RESAMPLER_ERR_SUCCESS
@ RESAMPLER_ERR_SUCCESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:104
ma_noise_s16_white
static MA_INLINE ma_int16 ma_noise_s16_white(ma_noise *pNoise)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45958
drmp3dec_frame_info::frame_bytes
int frame_bytes
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:259
drflac__reload_l1_cache_from_l2
static DRFLAC_INLINE drflac_bool32 drflac__reload_l1_cache_from_l2(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51874
ma_channel_map_contains_channel_position
MA_API ma_bool32 ma_channel_map_contains_channel_position(ma_uint32 channels, const ma_channel *pChannelMap, ma_channel channelPosition)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36269
DRMP3_HDR_GET_STEREO_MODE
#define DRMP3_HDR_GET_STEREO_MODE(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59353
c89atomic_int32
signed int c89atomic_int32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2576
MA_ALREADY_EXISTS
#define MA_ALREADY_EXISTS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1667
ma_standard_sample_rate_88200
@ ma_standard_sample_rate_88200
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:419
ma_calculate_buffer_size_in_milliseconds_from_frames
MA_API ma_uint32 ma_calculate_buffer_size_in_milliseconds_from_frames(ma_uint32 bufferSizeInFrames, ma_uint32 sampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27760
MA_NO_SPACE
#define MA_NO_SPACE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1677
drflac_container
drflac_container
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40100
ma_pcm_s32_to_f32__optimized
static MA_INLINE void ma_pcm_s32_to_f32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29386
drflac_cache_t
drflac_uint32 drflac_cache_t
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40069
ma_event::lock
pthread_mutex_t lock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:522
drflac_uint8
unsigned char drflac_uint8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39986
drwav::prevFrames
drwav_int32 prevFrames[2][2]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:890
drmp3dec_frame_info::channels
int channels
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:259
drwav_uint16
unsigned short drwav_uint16
Definition: porcupine/demo/c/dr_libs/dr_wav.h:137
ma_aaudio_content_type_speech
@ ma_aaudio_content_type_speech
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1850
drflac__seek_past_next_set_bit
static DRFLAC_INLINE drflac_bool32 drflac__seek_past_next_set_bit(drflac_bs *bs, unsigned int *pOffsetOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52321
DRFLAC_CACHE_L1_SELECT_AND_SHIFT
#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51842
ma_device__handle_duplex_callback_playback
static ma_result ma_device__handle_duplex_callback_playback(ma_device *pDevice, ma_uint32 frameCount, void *pFramesInInternalFormat, ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5902
DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
#define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51422
ma_has_sse2
static MA_INLINE ma_bool32 ma_has_sse2(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:229
drwav_cue::pCuePoints
drwav_cue_point * pCuePoints
Definition: porcupine/demo/c/dr_libs/dr_wav.h:614
ma_vfs_callbacks::onOpenW
ma_result(* onOpenW)(ma_vfs *pVFS, const wchar_t *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4651
stb_vorbis_close
void stb_vorbis_close(stb_vorbis *f)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:4246
drwav__write_f32ne_to_le
DRWAV_PRIVATE size_t drwav__write_f32ne_to_le(drwav *pWav, float value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47860
drwav_init_memory_ex
DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav *pWav, const void *data, size_t dataSize, drwav_chunk_proc onChunk, void *pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49157
drflac_crc16_cache
static DRFLAC_INLINE drflac_uint16 drflac_crc16_cache(drflac_uint16 crc, drflac_cache_t data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51715
c89atomic_if64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4123
drflac__be2host_64
static DRFLAC_INLINE drflac_uint64 drflac__be2host_64(drflac_uint64 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51591
drwav_read_pcm_frames_s16be
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50052
ma_decoding_backend_init_file_w__mp3
static ma_result ma_decoding_backend_init_file_w__mp3(void *pUserData, const wchar_t *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42676
ma_ios_session_category_solo_ambient
@ ma_ios_session_category_solo_ambient
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3030
ma_backend_callbacks::onDeviceStop
ma_result(* onDeviceStop)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2131
ma_lpf2_get_latency
MA_API ma_uint32 ma_lpf2_get_latency(const ma_lpf2 *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30887
drmp3::allocationCallbacks
drmp3_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:349
drwav__riff_chunk_size_rf64
DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize, drwav_metadata *metadata, drwav_uint32 numMetadata)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48256
drflac_frame_header::sampleRate
drflac_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_flac.h:655
ma_get_format_priority_index
MA_API ma_uint32 ma_get_format_priority_index(ma_format format)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5996
ma_pcm_f32_to_s32__optimized
static MA_INLINE void ma_pcm_f32_to_s32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30119
drflac_read_pcm_frames_f32__decode_right_side__scalar
static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__scalar(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, float *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58342
c89atoimc_flag_load_explicit
#define c89atoimc_flag_load_explicit(ptr, order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3800
drmp3_allocation_callbacks::onFree
void(* onFree)(void *p, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:331
drflac_uint32
unsigned int drflac_uint32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:246
ma_default_vfs_open
static ma_result ma_default_vfs_open(ma_vfs *pVFS, const char *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39200
ma_hishelf2_init
MA_API ma_result ma_hishelf2_init(const ma_hishelf2_config *pConfig, ma_hishelf2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32358
DR_WAVE_FORMAT_PCM
#define DR_WAVE_FORMAT_PCM
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39565
ma_context_config::pulse
struct ma_context_config::@105 pulse
ma_context
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3210
ma_pcm_s32_to_s16
MA_API void ma_pcm_s32_to_s16(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29265
drmp3::atEnd
drmp3_bool32 atEnd
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:363
ma_aaudio_content_type_sonification
@ ma_aaudio_content_type_sonification
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1849
ma_lcg
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5388
drwav_alaw_to_s32
DRWAV_API void drwav_alaw_to_s32(drwav_int32 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50708
ma_device_config::linear
struct ma_device_config::@96::@102 linear
ma_noise_s16_pink
static MA_INLINE ma_int16 ma_noise_s16_pink(ma_noise *pNoise, ma_uint32 iChannel)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46077
ma_device::algorithm
ma_resample_algorithm algorithm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3608
ma_decoder_internal_on_seek__custom
static ma_result ma_decoder_internal_on_seek__custom(void *pUserData, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40770
ma_rb::encodedReadOffset
volatile ma_uint32 encodedReadOffset
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2571
drwav_data_format::sampleRate
drwav_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_wav.h:440
drflac_bs::unalignedCache
drflac_cache_t unalignedCache
Definition: porcupine/demo/c/dr_libs/dr_flac.h:601
DRWAV_ALREADY_IN_USE
#define DRWAV_ALREADY_IN_USE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39534
drwav__metadata_process_chunk
DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser *pParser, const drwav_chunk_header *pChunkHeader, drwav_uint64 allowedMetadataTypes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47264
ma_flac_init_file
MA_API ma_result ma_flac_init_file(const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_flac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41684
drwav_list_labelled_cue_region::sampleLength
drwav_uint32 sampleLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:740
drwav_metadata_type_unknown
@ drwav_metadata_type_unknown
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39646
ma_pcm_s32_to_u8__optimized
static MA_INLINE void ma_pcm_s32_to_u8__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29161
ma_rand_f64
static MA_INLINE double ma_rand_f64(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2500
drflac_streaminfo::md5
drflac_uint8 md5[16]
Definition: porcupine/demo/c/dr_libs/dr_flac.h:406
ma_rb_reset
MA_API void ma_rb_reset(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36440
ma_backend_pulseaudio
@ ma_backend_pulseaudio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2802
c89atomic_memory_order_acquire
#define c89atomic_memory_order_acquire
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3290
drflac_uint64
unsigned long long drflac_uint64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40003
drmp3_copy_allocation_callbacks_or_defaults
static drmp3_allocation_callbacks drmp3_copy_allocation_callbacks_or_defaults(const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61137
ma_decoder__data_source_on_get_cursor
static ma_result ma_decoder__data_source_on_get_cursor(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43590
DRFLAC_BAD_ADDRESS
#define DRFLAC_BAD_ADDRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51381
drflac__on_seek_memory
static drflac_bool32 drflac__on_seek_memory(void *pUserData, int offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56674
RESAMPLER_ERR_INVALID_ARG
@ RESAMPLER_ERR_INVALID_ARG
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:107
drflac__update_crc16
static DRFLAC_INLINE void drflac__update_crc16(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51853
drwav_unknown_metadata
Definition: porcupine/demo/c/dr_libs/dr_wav.h:775
drwav_open_file_and_read_pcm_frames_s32
DRWAV_API drwav_int32 * drwav_open_file_and_read_pcm_frames_s32(const char *filename, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50916
ma_device
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3584
drwav_allocation_callbacks::onMalloc
void *(* onMalloc)(size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:412
ma_lpf2_config_init
MA_API ma_lpf2_config ma_lpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30635
init
void init(const M_string &remappings)
error
static int error(vorb *f, enum STBVorbisError e)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:896
ma_device_config::coreaudio
struct ma_device_config::@177 coreaudio
ma_audio_buffer_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4586
ma_data_converter::hasPreFormatConversion
ma_bool32 hasPreFormatConversion
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2434
drflac__decode_subframe
static drflac_bool32 drflac__decode_subframe(drflac_bs *bs, drflac_frame *frame, int subframeIndex, drflac_int32 *pDecodedSamplesOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54171
DRWAV_NO_SPACE
#define DRWAV_NO_SPACE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39529
ma_resampler_config_init
MA_API ma_resampler_config ma_resampler_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_resample_algorithm algorithm)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33078
ma_flac::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41506
ma_lpf_config_init
MA_API ma_lpf_config ma_lpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30897
ma_thread_priority_low
@ ma_thread_priority_low
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2816
drmp3_L3_idct3
static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60330
MA_BAD_SEEK
#define MA_BAD_SEEK
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1684
ma_data_converter_uninit
MA_API void ma_data_converter_uninit(ma_data_converter *pConverter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34671
DRMP3_ALREADY_EXISTS
#define DRMP3_ALREADY_EXISTS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40415
ma_standard_sample_rate_32000
@ ma_standard_sample_rate_32000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:415
ma_resampler::linear
ma_linear_resampler linear
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2265
drwav_acid::midiUnityNote
drwav_uint16 midiUnityNote
Definition: porcupine/demo/c/dr_libs/dr_wav.h:637
ma_allocation_callbacks::onRealloc
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1827
ma_decoder__data_source_on_get_data_format
static ma_result ma_decoder__data_source_on_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43579
drflac__read_streaminfo
static drflac_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void *pUserData, drflac_streaminfo *pStreamInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54829
ma_data_source_vtable::onGetCursor
ma_result(* onGetCursor)(ma_data_source *pDataSource, ma_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4509
drflac__reset_crc16
static DRFLAC_INLINE void drflac__reset_crc16(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51848
ma_context_init__null
static ma_result ma_context_init__null(ma_context *pContext, const ma_context_config *pConfig, ma_backend_callbacks *pCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6654
ma_hishelf2_config::gainDB
double gainDB
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2161
ma_data_source_config::vtable
const ma_data_source_vtable * vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4517
ma_device_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3100
drwav_metadata_type_list_info_tracknumber
@ drwav_metadata_type_list_info_tracknumber
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39663
drwav__metadata_process_unknown_chunk
DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_unknown_chunk(drwav__metadata_parser *pParser, const drwav_uint8 *pChunkId, drwav_uint64 chunkSize, drwav_metadata_location location)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47229
ma_yield
static MA_INLINE void ma_yield()
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:533
ma_log_init
MA_API ma_result ma_log_init(const ma_allocation_callbacks *pAllocationCallbacks, ma_log *pLog)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2003
ma_encoder_preinit
MA_API ma_result ma_encoder_preinit(const ma_encoder_config *pConfig, ma_encoder *pEncoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45196
ma_device__handle_duplex_callback_capture
static ma_result ma_device__handle_duplex_callback_capture(ma_device *pDevice, ma_uint32 frameCountInDeviceFormat, const void *pFramesInDeviceFormat, ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5845
ma_pcm_f32_to_f32
MA_API void ma_pcm_f32_to_f32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30168
ma_device_get_state
MA_API ma_uint32 ma_device_get_state(const ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27608
ma__calloc_from_callbacks
static MA_INLINE void * ma__calloc_from_callbacks(size_t sz, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1890
ma_device_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3103
ma_rb_init_ex
MA_API ma_result ma_rb_init_ex(size_t subbufferSizeInBytes, size_t subbufferCount, size_t subbufferStrideInBytes, void *pOptionalPreallocatedBuffer, const ma_allocation_callbacks *pAllocationCallbacks, ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36371
ma_linear_resampler_process_pcm_frames_s16_downsample
static ma_result ma_linear_resampler_process_pcm_frames_s16_downsample(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32620
drwav__free_from_callbacks
DRWAV_PRIVATE void drwav__free_from_callbacks(void *p, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46667
drflac_open_with_metadata
DRFLAC_API drflac * drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56755
drflac_init_info::channels
drflac_uint8 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54797
MA_MAX_CHANNELS
#define MA_MAX_CHANNELS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1753
ma_waveform_seek_to_pcm_frame
MA_API ma_result ma_waveform_seek_to_pcm_frame(ma_waveform *pWaveform, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45789
c89atomic_memory_order_seq_cst
#define c89atomic_memory_order_seq_cst
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3293
ma_device_info::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1931
ma_biquad_config::a1
double a1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1851
ma_hpf::hpf2
ma_hpf2 hpf2[MA_MAX_FILTER_ORDER/2]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2003
ma_audio_buffer_ref__data_source_on_unmap
static ma_result ma_audio_buffer_ref__data_source_on_unmap(ma_data_source *pDataSource, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37995
ma_decoding_backend_uninit__flac
static void ma_decoding_backend_uninit__flac(void *pUserData, ma_data_source *pBackend, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42092
ma_waveform_type_square
@ ma_waveform_type_square
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5360
drmp3_open_memory_and_read_pcm_frames_s16
DRMP3_API drmp3_int16 * drmp3_open_memory_and_read_pcm_frames_s16(const void *pData, size_t dataSize, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62515
ma_pcm_s16_to_u8
MA_API void ma_pcm_s16_to_u8(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28470
ma_lpf::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1930
drwav__metadata_parser::pDataCursor
drwav_uint8 * pDataCursor
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46907
drwav__memory_stream::currentReadPos
size_t currentReadPos
Definition: porcupine/demo/c/dr_libs/dr_wav.h:422
ma_pcm_s24_to_s32__reference
static MA_INLINE void ma_pcm_s24_to_s32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28928
ma_data_converter_config::channelsOut
ma_uint32 channelsOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2406
ma_device::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3588
ma_resampler::state
union ma_resampler::@77 state
ma_channel_converter::weights
union ma_channel_converter::@79 weights
ma_device::capture
struct ma_device::@116 capture
ma_encoder_config::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5319
ma_channel_mix_mode
ma_channel_mix_mode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1794
drwav::ima
struct drwav::@11 ima
ma_thread_proxy_data::pData
void * pData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4691
DRMP3_IN_PROGRESS
#define DRMP3_IN_PROGRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40457
drflac_streaminfo::sampleRate
drflac_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_flac.h:402
ma_hpf_get_latency
MA_API ma_uint32 ma_hpf_get_latency(const ma_hpf *pHPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31611
ma_device_thread__null
static ma_thread_result MA_THREADCALL ma_device_thread__null(void *pData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6223
drflac_oggbs::onSeek
drflac_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55443
MA_NOT_IMPLEMENTED
#define MA_NOT_IMPLEMENTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1688
drflac::_oggbs
void * _oggbs
Definition: porcupine/demo/c/dr_libs/dr_flac.h:751
ma_audio_buffer_init_copy
MA_API ma_result ma_audio_buffer_init_copy(const ma_audio_buffer_config *pConfig, ma_audio_buffer *pAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38357
drmp3_exp
static DRMP3_INLINE double drmp3_exp(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61070
drflac::sampleRate
drflac_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_flac.h:701
ma_log_level_to_string
const MA_API char * ma_log_level_to_string(ma_uint32 logLevel)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1953
DRWAV_TRUE
#define DRWAV_TRUE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39480
c89atomic_fetch_xor_explicit_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_fetch_xor_explicit_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3686
ma_resample_algorithm_speex
@ ma_resample_algorithm_speex
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2237
ma_linear_resampler_get_required_input_frame_count
MA_API ma_uint64 ma_linear_resampler_get_required_input_frame_count(const ma_linear_resampler *pResampler, ma_uint64 outputFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32981
ma_seek_origin_current
@ ma_seek_origin_current
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5142
drwav::bytesRemainingInBlock
drwav_uint32 bytesRemainingInBlock
Definition: porcupine/demo/c/dr_libs/dr_wav.h:885
drflac_streaminfo
Definition: porcupine/demo/c/dr_libs/dr_flac.h:396
drflac_uint32
unsigned int drflac_uint32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39990
ma_device::onStop
ma_stop_proc onStop
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3591
ma_notch2__get_biquad_config
static MA_INLINE ma_biquad_config ma_notch2__get_biquad_config(const ma_notch2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31947
drwav_read_pcm_frames_s16le
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav *pWav, drwav_uint64 framesToRead, drwav_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50044
ma_log_callback_proc
void(* ma_log_callback_proc)(void *pUserData, ma_uint32 level, const char *pMessage)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:577
ma_decoder__preinit_vfs
static ma_result ma_decoder__preinit_vfs(ma_vfs *pVFS, const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44278
drwav_acid::reserved2
float reserved2
Definition: porcupine/demo/c/dr_libs/dr_wav.h:641
drwav_fmt_get_format
DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt *pFMT)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47478
drmp3_bs::buf
const drmp3_uint8 * buf
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59482
drflac_init_info::maxBlockSizeInPCMFrames
drflac_uint16 maxBlockSizeInPCMFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54800
ma_device_type
ma_device_type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3010
ma_hpf2__get_biquad_config
static MA_INLINE ma_biquad_config ma_hpf2__get_biquad_config(const ma_hpf2_config *pConfig)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31307
ma_spinlock
ma_uint32 ma_spinlock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:499
drwav::allocationCallbacks
drwav_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/dr_wav.h:820
MA_CHANNEL_AUX_29
#define MA_CHANNEL_AUX_29
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1650
DRMP3_PI_D
#define DRMP3_PI_D
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61040
ma_handle
void * ma_handle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1533
MA_CHANNEL_FRONT_CENTER
#define MA_CHANNEL_FRONT_CENTER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1605
ma_device_uninit
MA_API void ma_device_uninit(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27425
DRWAV_VERSION_STRING
#define DRWAV_VERSION_STRING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39448
drwav_fmt::avgBytesPerSec
drwav_uint32 avgBytesPerSec
Definition: porcupine/demo/c/dr_libs/dr_wav.h:314
ma_event_uninit__posix
static void ma_event_uninit__posix(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4584
drflac_uint16
unsigned short drflac_uint16
Definition: porcupine/demo/c/dr_libs/dr_flac.h:244
ma_device::internalChannelMap
ma_channel internalChannelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3631
ma_decoding_backend_vtable::onInit
ma_result(* onInit)(void *pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4725
drflac_open_memory_and_read_pcm_frames_s32
DRFLAC_API drflac_int32 * drflac_open_memory_and_read_pcm_frames_s32(const void *data, size_t dataSize, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59173
DRMP3_HDR_GET_BITRATE
#define DRMP3_HDR_GET_BITRATE(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59356
MA_DEVICE_NOT_STARTED
#define MA_DEVICE_NOT_STARTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1726
drmp3_hdr_padding
static int drmp3_hdr_padding(const drmp3_uint8 *h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59572
drflac_cuesheet_track::ISRC
char ISRC[12]
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1297
drflac_init_cuesheet_track_iterator
DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator *pIter, drflac_uint32 trackCount, const void *pTrackData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59263
drwav_metadata_type_bext
@ drwav_metadata_type_bext
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39651
ma_context_config::pLog
ma_log * pLog
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2141
drflac_frame::subframes
drflac_subframe subframes[8]
Definition: porcupine/demo/c/dr_libs/dr_flac.h:685
drwav_f64_to_s16
DRWAV_API void drwav_f64_to_s16(drwav_int16 *pOut, const double *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50105
ma_cosd
static MA_INLINE double ma_cosd(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:818
ma_thread_proxy_data
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4688
ma_zero_memory_64
static MA_INLINE void ma_zero_memory_64(void *dst, ma_uint64 sizeInBytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1752
drwav_metadata::acid
drwav_acid acid
Definition: porcupine/demo/c/dr_libs/dr_wav.h:795
drwav_get_cursor_in_pcm_frames
DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav *pWav, drwav_uint64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49456
ma_context::pDeviceInfos
ma_device_info * pDeviceInfos
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3222
config
static sai_transceiver_t config
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:75
ma_is_little_endian
static MA_INLINE ma_bool32 ma_is_little_endian(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:445
ma_loshelf2_init
MA_API ma_result ma_loshelf2_init(const ma_loshelf2_config *pConfig, ma_loshelf2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32232
drwav::container
drwav_container container
Definition: porcupine/demo/c/dr_libs/dr_wav.h:824
drflac_streaminfo::bitsPerSample
drflac_uint8 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_flac.h:404
ma_vfs
void ma_vfs
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4630
__attribute__
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
Reverse byte order (16 bit)
Definition: imxrt1050/imxrt1050-evkb/CMSIS/cmsis_armcc.h:492
drwav_list_info_text::stringLength
drwav_uint32 stringLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:722
MA_TRUE
#define MA_TRUE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1530
drmp3_L12_scale_info::scf
float scf[3 *64]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59487
c89atomic_exchange_f32
#define c89atomic_exchange_f32(dst, src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4176
drflac__be2host_16
static DRFLAC_INLINE drflac_uint16 drflac__be2host_16(drflac_uint16 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51577
drwav__data_chunk_size_w64
DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48252
ma_pcm_deinterleave_s32__reference
static MA_INLINE void ma_pcm_deinterleave_s32__reference(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29464
drwav_init_file_write_sequential
DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav *pWav, const char *filename, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49034
ma_pcm_s24_to_s32
MA_API void ma_pcm_s24_to_s32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28965
DRMP3_API
#define DRMP3_API
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40402
DRFLAC_INVALID_OPERATION
#define DRFLAC_INVALID_OPERATION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51360
drwav_metadata::unknown
drwav_unknown_metadata unknown
Definition: porcupine/demo/c/dr_libs/dr_wav.h:801
ma_data_converter_config::formatOut
ma_format formatOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2404
DRWAV_VERSION_REVISION
#define DRWAV_VERSION_REVISION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39447
ma_hpf1::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1964
DRMP3_DQ
#define DRMP3_DQ(x)
ma_device::workResult
ma_result workResult
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3598
drwav_chunk_proc
drwav_uint64(* drwav_chunk_proc)(void *pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek, void *pReadSeekUserData, const drwav_chunk_header *pChunkHeader, drwav_container container, const drwav_fmt *pFMT)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39613
ma_pcm_s16_to_f32__optimized
static MA_INLINE void ma_pcm_s16_to_f32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28653
ma_vfs_callbacks::onWrite
ma_result(* onWrite)(ma_vfs *pVFS, ma_vfs_file file, const void *pSrc, size_t sizeInBytes, size_t *pBytesWritten)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4654
ma_log_postv
MA_API ma_result ma_log_postv(ma_log *pLog, ma_uint32 level, const char *pFormat, va_list args)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2187
ma_context_config::coreaudio
struct ma_context_config::@106 coreaudio
MA_DEVICE_OP_KILL__NULL
#define MA_DEVICE_OP_KILL__NULL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6221
drwav__write_or_count_u16ne_to_le
DRWAV_PRIVATE size_t drwav__write_or_count_u16ne_to_le(drwav *pWav, drwav_uint16 value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47888
MA_CHANNEL_AUX_9
#define MA_CHANNEL_AUX_9
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1630
drwav_init__internal
DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav *pWav, drwav_chunk_proc onChunk, void *pChunkUserData, drwav_uint32 flags)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47504
c89atomic_if32::i
c89atomic_uint32 i
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4120
DRMP3_CONNECTION_RESET
#define DRMP3_CONNECTION_RESET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40452
MA_BAD_MESSAGE
#define MA_BAD_MESSAGE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1690
MA_SUCCESS
#define MA_SUCCESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1659
ma_copy_and_apply_volume_factor_pcm_frames_s24
MA_API void ma_copy_and_apply_volume_factor_pcm_frames_s24(void *pPCMFramesOut, const void *pPCMFramesIn, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27936
ma_decoding_backend_init_file_w__flac
static ma_result ma_decoding_backend_init_file_w__flac(void *pUserData, const wchar_t *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_data_source **ppBackend)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42044
ma_waveform_read_pcm_frames__triangle
static void ma_waveform_read_pcm_frames__triangle(ma_waveform *pWaveform, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45667
ma_abs
#define ma_abs(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:779
drflac_crc32_buffer
static DRFLAC_INLINE drflac_uint32 drflac_crc32_buffer(drflac_uint32 crc32, drflac_uint8 *pData, drflac_uint32 dataSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55346
ma_ios_session_category_ambient
@ ma_ios_session_category_ambient
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3029
ma_biquad::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1859
args
ma_linear_resampler_config_init
MA_API ma_linear_resampler_config ma_linear_resampler_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32435
drmp3_L3_huffman
static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59971
drwav__realloc_default
DRWAV_PRIVATE void * drwav__realloc_default(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46622
ma_waveform_read_pcm_frames
MA_API ma_uint64 ma_waveform_read_pcm_frames(ma_waveform *pWaveform, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45751
drwav_unknown_metadata::id
drwav_uint8 id[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:777
c89atomic_bool
unsigned char c89atomic_bool
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2596
ma_backend_oss
@ ma_backend_oss
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2801
c89atomic_spinlock_unlock
static C89ATOMIC_INLINE void c89atomic_spinlock_unlock(volatile c89atomic_spinlock *pSpinlock)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4189
drwav_init_write_with_metadata
DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav *pWav, const drwav_data_format *pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void *pUserData, const drwav_allocation_callbacks *pAllocationCallbacks, drwav_metadata *pMetadata, drwav_uint32 metadataCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48399
drwav_metadata_type_all
@ drwav_metadata_type_all
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39676
DR_WAVE_FORMAT_EXTENSIBLE
#define DR_WAVE_FORMAT_EXTENSIBLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39571
drmp3_decode_next_frame_ex
static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3 *pMP3, drmp3d_sample_t *pPCMFrames)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61291
ma_bpf_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2041
ma_device_config::pStreamNameCapture
const char * pStreamNameCapture
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3156
ma_lpf::lpf1Count
ma_uint32 lpf1Count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1932
drflac_cuesheet_track::offset
drflac_uint64 offset
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1295
DRFLAC_AT_END
#define DRFLAC_AT_END
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51410
ma_semaphore::cond
pthread_cond_t cond
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:535
drwav__bswap_s24
static DRWAV_INLINE void drwav__bswap_s24(drwav_uint8 *p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46486
drflac_int64
signed long long drflac_int64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40002
ma_linear_resampler::inTimeInt
ma_uint32 inTimeInt
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2209
ma_path_extension_equal
static ma_bool32 ma_path_extension_equal(const char *path, const char *extension)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44181
DRMP3_ZERO_OBJECT
#define DRMP3_ZERO_OBJECT(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61027
ma_standard_sample_rate_16000
@ ma_standard_sample_rate_16000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:424
ma_data_source_get_next_proc
ma_data_source *(* ma_data_source_get_next_proc)(ma_data_source *pDataSource)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4513
ma_data_converter_config::resampling
struct ma_data_converter_config::@80 resampling
ma_waveform_read_pcm_frames__square
static void ma_waveform_read_pcm_frames__square(ma_waveform *pWaveform, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45625
drflac_read_pcm_frames_s16__decode_independent_stereo
static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo(drflac *pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32 *pInputSamples0, const drflac_int32 *pInputSamples1, drflac_int16 *pOutputSamples)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:58104
ma_lcg_rand_f64
static MA_INLINE double ma_lcg_rand_f64(ma_lcg *pLCG)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2459
ma_pcm_deinterleave_u8__reference
static MA_INLINE void ma_pcm_deinterleave_u8__reference(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28383
ma_standard_sample_rate_384000
@ ma_standard_sample_rate_384000
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:429
drflac__decode_block_header
static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader, drflac_uint8 *isLastBlock, drflac_uint8 *blockType, drflac_uint32 *blockSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54812
drwav_cue
Definition: porcupine/demo/c/dr_libs/dr_wav.h:611
drwav_bool8
drwav_uint8 drwav_bool8
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39478
ma_aaudio_input_preset_voice_performance
@ ma_aaudio_input_preset_voice_performance
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1862
ma_get_enabled_backends
MA_API ma_result ma_get_enabled_backends(ma_backend *pBackends, size_t backendCap, size_t *pBackendCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5181
drmp3__seeking_mp3_frame_info::pcmFrameIndex
drmp3_uint64 pcmFrameIndex
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62284
ma_data_source_vtable::onGetLength
ma_result(* onGetLength)(ma_data_source *pDataSource, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4510
drwav_read_pcm_frames_f32__pcm
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav *pWav, drwav_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50185
ma_pcm_deinterleave_s16
MA_API void ma_pcm_deinterleave_s16(void **dst, const void *src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28750
ma_device_id::audio4
char audio4[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3065
ma_backend_jack
@ ma_backend_jack
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2804
ma_waveform_config_init
MA_API ma_waveform_config ma_waveform_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_waveform_type type, double amplitude, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45369
ma_pcm_s32_to_s24__optimized
static MA_INLINE void ma_pcm_s32_to_s24__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29306
ma_noise_config::seed
ma_int32 seed
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5405
ma_device_init_ex
MA_API ma_result ma_device_init_ex(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config *pContextConfig, const ma_device_config *pConfig, ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27362
cmd
string cmd
drwav__realloc_from_callbacks
DRWAV_PRIVATE void * drwav__realloc_from_callbacks(void *p, size_t szNew, size_t szOld, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46645
ma_decoder_config::pCustomBackendUserData
void * pCustomBackendUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4763
ma_loshelf2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2136
ma_rb__get_write_ptr
static MA_INLINE void * ma_rb__get_write_ptr(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36350
ma_notch2_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2078
drflac::totalPCMFrameCount
drflac_uint64 totalPCMFrameCount
Definition: porcupine/demo/c/dr_libs/dr_flac.h:719
ma_hishelf2_config::shelfSlope
double shelfSlope
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2162
DRFLAC_VERSION_REVISION
#define DRFLAC_VERSION_REVISION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39982
ma_lpf_get_latency
MA_API ma_uint32 ma_lpf_get_latency(const ma_lpf *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31118
ma_sind
static MA_INLINE double ma_sind(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:787
drwav__read_acid_to_metadata_obj
DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_parser *pParser, drwav_metadata *pMetadata)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47052
drwav_init_file_ex_w
DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav *pWav, const wchar_t *filename, drwav_chunk_proc onChunk, void *pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48975
DRMP3_HDR_IS_MS_STEREO
#define DRMP3_HDR_IS_MS_STEREO(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59345
ma_biquad_get_latency
MA_API ma_uint32 ma_biquad_get_latency(const ma_biquad *pBQ)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30606
ma_device_config::contentType
ma_aaudio_content_type contentType
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2012
ma_pcm_rb_get_subbuffer_stride
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_stride(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36976
header
const std::string header
ma_pcm_rb_available_write
MA_API ma_uint32 ma_pcm_rb_available_write(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36958
ma_backend_alsa
@ ma_backend_alsa
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2803
ma_lpf1_config_init
MA_API ma_lpf1_config ma_lpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30621
DRMP3_S1
#define DRMP3_S1(k)
drwav_acid_flag_stretch
@ drwav_acid_flag_stretch
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39736
spx_uint64_t
unsigned long long spx_uint64_t
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/speex_resampler/ma_speex_resampler.h:19
ma_data_source_get_data_format
MA_API ma_result ma_data_source_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37609
ma_backend_callbacks::onDeviceInit
ma_result(* onDeviceInit)(ma_device *pDevice, const ma_device_config *pConfig, ma_device_descriptor *pDescriptorPlayback, ma_device_descriptor *pDescriptorCapture)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2128
drwav_seek_origin_start
@ drwav_seek_origin_start
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39577
ma_channel_converter::shuffleTable
ma_uint8 shuffleTable[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2384
ma_pcm_s24_to_u8__reference
static MA_INLINE void ma_pcm_s24_to_u8__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28761
ma_standard_channel_map_sndio
@ ma_standard_channel_map_sndio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1811
ma_hpf::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:776
ma_lpf2_init
MA_API ma_result ma_lpf2_init(const ma_lpf2_config *pConfig, ma_lpf2 *pLPF)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30826
drflac__swap_endian_uint32
static DRFLAC_INLINE drflac_uint32 drflac__swap_endian_uint32(drflac_uint32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51523
drflac__gIsNEONSupported
static drflac_bool32 drflac__gIsNEONSupported
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51470
ma_context_get_devices__enum_callback
static ma_bool32 ma_context_get_devices__enum_callback(ma_context *pContext, ma_device_type deviceType, const ma_device_info *pInfo, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26817
assert.h
ma_pcm_convert
MA_API void ma_pcm_convert(void *pOut, ma_format formatOut, const void *pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30234
ma_decoder__data_source_on_read
static ma_result ma_decoder__data_source_on_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43559
drflac_container_native
@ drflac_container_native
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40102
DRMP3_MIN
#define DRMP3_MIN(a, b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59364
MA_STATE_STARTING
#define MA_STATE_STARTING
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1628
MA_CHANNEL_FRONT_LEFT
#define MA_CHANNEL_FRONT_LEFT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1603
drflac_allocation_callbacks_from_miniaudio
static drflac_allocation_callbacks drflac_allocation_callbacks_from_miniaudio(const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41562
drmp3_int32
signed int drmp3_int32
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:108
c89atomic_is_lock_free_16
static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_16(volatile void *ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3882
drwav_read_pcm_frames_s32__pcm
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50487
DR_WAVE_FORMAT_MULAW
#define DR_WAVE_FORMAT_MULAW
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39569
ma_pcm_rb::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2597
ma_wav_get_length_in_pcm_frames
MA_API ma_result ma_wav_get_length_in_pcm_frames(ma_wav *pWav, ma_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41333
drflac_bs::crc16CacheIgnoredBytes
drflac_uint32 crc16CacheIgnoredBytes
Definition: porcupine/demo/c/dr_libs/dr_flac.h:622
drwav__memory_stream
Definition: porcupine/demo/c/dr_libs/dr_wav.h:418
ma_pcm_u8_to_s32__optimized
static MA_INLINE void ma_pcm_u8_to_s32__optimized(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28218
drwav_int32
signed int drwav_int32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39454
ma_mp3_ds_read
static ma_result ma_mp3_ds_read(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42156
drwav_inst::gainDecibels
drwav_int8 gainDecibels
Definition: porcupine/demo/c/dr_libs/dr_wav.h:577
drwav_metadata::data
union drwav_metadata::@9 data
drmp3_L12_scale_info::total_bands
drmp3_uint8 total_bands
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59488
ma_data_converter::resampler
ma_resampler resampler
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2433
drmp3_fopen
static drmp3_result drmp3_fopen(FILE **ppFile, const char *pFilePath, const char *pOpenMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61806
drmp3::seekPointCount
drmp3_uint32 seekPointCount
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:358
ma_data_source_config_init
MA_API ma_data_source_config ma_data_source_config_init(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37214
ma_lpf1_process_pcm_frames
MA_API ma_result ma_lpf1_process_pcm_frames(ma_lpf1 *pLPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30750
ma_spinlock_unlock
MA_API ma_result ma_spinlock_unlock(volatile ma_spinlock *pSpinlock)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4301
drflac_seekpoint::flacFrameOffset
drflac_uint64 flacFrameOffset
Definition: porcupine/demo/c/dr_libs/dr_flac.h:391
ma_rb_acquire_read
MA_API ma_result ma_rb_acquire_read(ma_rb *pRB, size_t *pSizeInBytes, void **ppBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36450
drwav_acid::tempo
float tempo
Definition: porcupine/demo/c/dr_libs/dr_wav.h:651
ma_hpf_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1990
MA_NOT_UNIQUE
#define MA_NOT_UNIQUE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1695
ma_fopen
MA_API ma_result ma_fopen(FILE **ppFile, const char *pFilePath, const char *pOpenMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1586
drflac::onMeta
drflac_meta_proc onMeta
Definition: porcupine/demo/c/dr_libs/dr_flac.h:691
MA_ZERO_OBJECT
#define MA_ZERO_OBJECT(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:774
ma_decoder_init_mp3
MA_API ma_result ma_decoder_init_mp3(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43725
drwav__metadata_parser_stage_read
@ drwav__metadata_parser_stage_read
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46896
ma_lpf1_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1881
ma_decoder_init_file_flac_w
MA_API ma_result ma_decoder_init_file_flac_w(const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44724
ma_encoder_seek_proc
ma_bool32(* ma_encoder_seek_proc)(ma_encoder *pEncoder, int byteOffset, ma_seek_origin origin)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5308
drwav__write_u32ne_to_le
DRWAV_PRIVATE size_t drwav__write_u32ne_to_le(drwav *pWav, drwav_uint32 value)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47842
ma_encoder_write_proc
size_t(* ma_encoder_write_proc)(ma_encoder *pEncoder, const void *pBufferIn, size_t bytesToWrite)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5307
ma_pcm_s24_to_f32
MA_API void ma_pcm_s24_to_f32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29039
ma_decoder_init_custom__internal
static ma_result ma_decoder_init_custom__internal(const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40818
DRMP3_HDR_TEST_MS_STEREO
#define DRMP3_HDR_TEST_MS_STEREO(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59352
ma_apply_volume_factor_pcm_frames_s16
MA_API void ma_apply_volume_factor_pcm_frames_s16(ma_int16 *pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27969
drmp3_allocation_callbacks::onMalloc
void *(* onMalloc)(size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:329
drflac__seek_to_next_flac_frame
static DRFLAC_INLINE drflac_result drflac__seek_to_next_flac_frame(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54413
drmp3_allocation_callbacks::onRealloc
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:330
drmp3_L3_imdct12
static void drmp3_L3_imdct12(float *x, float *dst, float *overlap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60338
drflac_seek_origin_start
@ drflac_seek_origin_start
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40108
ma_biquad::r2
ma_biquad_coefficient r2[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1867
ma_flac_seek_to_pcm_frame
MA_API ma_result ma_flac_seek_to_pcm_frame(ma_flac *pFlac, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41863
ma_data_converter::channelConverter
ma_channel_converter channelConverter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2432
drmp3_seek_point::mp3FramesToDiscard
drmp3_uint16 mp3FramesToDiscard
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:294
drmp3_seek_proc
drmp3_bool32(* drmp3_seek_proc)(void *pUserData, int offset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40504
drwav_bext::pOriginationTime
char pOriginationTime[8]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:690
ma_mp3::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42133
drmp3d_sample_t
drmp3_int16 drmp3d_sample_t
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60596
ma_data_converter
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2429
drwav_init_memory_with_metadata
DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav *pWav, const void *data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49170
ma_powf
static MA_INLINE float ma_powf(float x, float y)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:828
ma_biquad_config::b0
double b0
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1847
drflac__init_private__ogg
static drflac_bool32 drflac__init_private__ogg(drflac_init_info *pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void *pUserData, void *pUserDataMD, drflac_bool32 relaxed)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55746
drmp3::onRead
drmp3_read_proc onRead
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:346
drflac__read_subframe_header
static drflac_bool32 drflac__read_subframe_header(drflac_bs *bs, drflac_subframe *pSubframe)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54128
ma_noise_type
ma_noise_type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5393
drmp3_hdr_valid
static int drmp3_hdr_valid(const drmp3_uint8 *h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59531
ma_channel_mix_mode_rectangular
@ ma_channel_mix_mode_rectangular
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1796
ma_biquad_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1845
ma_log::callbacks
ma_log_callback callbacks[MA_MAX_LOG_CALLBACKS]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:590
drflac_streaminfo::minFrameSizeInPCMFrames
drflac_uint32 minFrameSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:400
ma_channel_map_blank
MA_API ma_bool32 ma_channel_map_blank(ma_uint32 channels, const ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36251
ma_decoding_backend_get_channel_map__mp3
static ma_result ma_decoding_backend_get_channel_map__mp3(void *pUserData, ma_data_source *pBackend, ma_channel *pChannelMap, size_t channelMapCap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42734
drmp3_uint16
unsigned short drmp3_uint16
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:107
ma_decoder_config::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5190
DRWAV_BAD_PROTOCOL
#define DRWAV_BAD_PROTOCOL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39550
ma_context_config::custom
ma_backend_callbacks custom
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2168
ma_decoder_tell_bytes
static ma_result ma_decoder_tell_bytes(ma_decoder *pDecoder, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40623
ma_hpf1_process_pcm_frames
MA_API ma_result ma_hpf1_process_pcm_frames(ma_hpf1 *pHPF, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31261
ma_hishelf2_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2159
drflac_streaminfo::maxBlockSizeInPCMFrames
drflac_uint16 maxBlockSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:399
drwav::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_wav.h:817
drflac_bs::nextL2Line
drflac_uint32 nextL2Line
Definition: porcupine/demo/c/dr_libs/dr_flac.h:604
drwav_metadata_location_inside_adtl_list
@ drwav_metadata_location_inside_adtl_list
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39797
MA_TOO_MANY_OPEN_FILES
#define MA_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1668
ma_flac
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41499
ma_data_converter_process_pcm_frames__channels_first
static ma_result ma_data_converter_process_pcm_frames__channels_first(ma_data_converter *pConverter, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35158
drwav__bswap_samples_s32
static DRWAV_INLINE void drwav__bswap_samples_s32(drwav_int32 *pSamples, drwav_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46505
ma_rb__extract_offset_in_bytes
static MA_INLINE ma_uint32 ma_rb__extract_offset_in_bytes(ma_uint32 encodedOffset)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36334
drmp3_s16_to_f32
static void drmp3_s16_to_f32(float *dst, const drmp3_int16 *src, drmp3_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61998
DRMP3_DEADLOCK
#define DRMP3_DEADLOCK
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40434
DRMP3_HDR_GET_STEREO_MODE_EXT
#define DRMP3_HDR_GET_STEREO_MODE_EXT(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59354
ma_speex_resampler_get_required_input_frame_count
int ma_speex_resampler_get_required_input_frame_count(SpeexResamplerState *st, spx_uint64_t out_len, spx_uint64_t *in_len)
ma_data_converter_get_required_input_frame_count
MA_API ma_uint64 ma_data_converter_get_required_input_frame_count(const ma_data_converter *pConverter, ma_uint64 outputFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35378
ma_context_config::threadStackSize
size_t threadStackSize
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2143
drflac_oggbs::bosPageHeader
drflac_ogg_page_header bosPageHeader
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55448
ma_copy_string_w
MA_API wchar_t * ma_copy_string_w(const wchar_t *src, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1169
drflac_ogg_page_header
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54775
ma_decoder_init_from_vtable
static ma_result ma_decoder_init_from_vtable(const ma_decoding_backend_vtable *pVTable, void *pVTableUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40787
ma_hishelf2_config_init
MA_API ma_hishelf2_config ma_hishelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32308
ma_device_descriptor::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2048
drwav_bytes_to_s64
DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51076
ma_device::stopEvent
ma_event stopEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3596
ma_standard_sample_rate_352800
@ ma_standard_sample_rate_352800
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:428
ma_swap_endian_uint32
static MA_INLINE ma_uint32 ma_swap_endian_uint32(ma_uint32 n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:461
ma_decoder_init_vfs
MA_API ma_result ma_decoder_init_vfs(ma_vfs *pVFS, const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44303
drwav_smpl::sampleLoopCount
drwav_uint32 sampleLoopCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:558
ma_decoder_init_vorbis
MA_API ma_result ma_decoder_init_vorbis(ma_decoder_read_proc onRead, ma_decoder_seek_proc onSeek, void *pUserData, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43744
ma_context_config::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3165
c89atomic_fetch_or_explicit_32
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_fetch_or_explicit_32(volatile c89atomic_uint32 *dst, c89atomic_uint32 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3741
c89atomic_compare_and_swap_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_compare_and_swap_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 expected, c89atomic_uint8 desired)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3443
ma_has_neon
static MA_INLINE ma_bool32 ma_has_neon(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:359
c89atomic_fetch_and_explicit_8
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_fetch_and_explicit_8(volatile c89atomic_uint8 *dst, c89atomic_uint8 src, c89atomic_memory_order order)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3631
ma_is_standard_sample_rate
static MA_INLINE ma_bool32 ma_is_standard_sample_rate(ma_uint32 sampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:661
drmp3_L12_apply_scf_384
static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59716
drwav__memory_stream_write
Definition: porcupine/demo/c/dr_libs/dr_wav.h:426
ma_backend
ma_backend
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2793
ma_event::value
ma_uint32 value
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2885
ma_rb::clearOnWriteAcquire
ma_bool32 clearOnWriteAcquire
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2574
drmp3_L3_restore_reservoir
static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60406
drwav_int64
signed long long drwav_int64
Definition: porcupine/demo/c/dr_libs/dr_wav.h:151
ma_pcm_u8_to_s32
MA_API void ma_pcm_u8_to_s32(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28242
ma_linear_resampler_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2207
ma_data_converter::hasResampler
ma_bool32 hasResampler
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2437
ma_noise_type_white
@ ma_noise_type_white
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5395
ma_channel_converter::channelsIn
ma_uint32 channelsIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2370
ma_wav_seek_to_pcm_frame
MA_API ma_result ma_wav_seek_to_pcm_frame(ma_wav *pWav, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41225
drmp3::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:359
ma_device_uninit__null
static ma_result ma_device_uninit__null(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6392
ma_hpf1_process_pcm_frame_f32
static MA_INLINE void ma_hpf1_process_pcm_frame_f32(ma_hpf1 *pHPF, float *pY, const float *pX)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:31221
ma_ios_session_category_playback
@ ma_ios_session_category_playback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3031
DRMP3_INLINE
#define DRMP3_INLINE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40474
drflac__find_and_seek_to_next_sync_code
static drflac_bool32 drflac__find_and_seek_to_next_sync_code(drflac_bs *bs)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52145
ma_device::wakeupEvent
ma_event wakeupEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3594
ma_device_descriptor_is_valid
static ma_bool32 ma_device_descriptor_is_valid(const ma_device_descriptor *pDeviceDescriptor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6012
drmp3_get_mp3_and_pcm_frame_count
DRMP3_API drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3 *pMP3, drmp3_uint64 *pMP3FrameCount, drmp3_uint64 *pPCMFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62213
DRFLAC_SUCCESS
#define DRFLAC_SUCCESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51357
drflac__on_seek_stdio
static drflac_bool32 drflac__on_seek_stdio(void *pUserData, int offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56596
drmp3_read_pcm_frames_s16
DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3 *pMP3, drmp3_uint64 framesToRead, drmp3_int16 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62070
drflac::pSeekpoints
drflac_seekpoint * pSeekpoints
Definition: porcupine/demo/c/dr_libs/dr_flac.h:748
drmp3dec_decode_frame
DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60859
drflac::pExtraData
drflac_uint8 pExtraData[1]
Definition: porcupine/demo/c/dr_libs/dr_flac.h:762
c89atomic_compare_and_swap_ptr
static C89ATOMIC_INLINE void * c89atomic_compare_and_swap_ptr(volatile void **dst, void *expected, void *desired)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3931
ma_decoder_init_vfs_mp3
MA_API ma_result ma_decoder_init_vfs_mp3(ma_vfs *pVFS, const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44446
drwav_data_format
Definition: porcupine/demo/c/dr_libs/dr_wav.h:435
ma_degrees_to_radians
static MA_INLINE double ma_degrees_to_radians(double degrees)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:839
DRMP3_RELOAD_SCALEFACTOR
#define DRMP3_RELOAD_SCALEFACTOR
drflac_int32
signed int drflac_int32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:245
ma_audio_buffer_ref_unmap
MA_API ma_result ma_audio_buffer_ref_unmap(ma_audio_buffer_ref *pAudioBufferRef, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38177
ma_device_info::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1932
DRMP3_NOT_SOCKET
#define DRMP3_NOT_SOCKET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40444
MA_TAU_D
#define MA_TAU_D
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:590
ma_resampler_get_output_latency
MA_API ma_uint64 ma_resampler_get_output_latency(const ma_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33590
ma_context_config::sessionCategory
ma_ios_session_category sessionCategory
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3178
drmp3__full_read_and_close_f32
static float * drmp3__full_read_and_close_f32(drmp3 *pMP3, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62389
drwav_wfopen
DRWAV_PRIVATE drwav_result drwav_wfopen(FILE **ppFile, const wchar_t *pFilePath, const wchar_t *pOpenMode, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48869
drflac_seek_proc
drflac_bool32(* drflac_seek_proc)(void *pUserData, int offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40186
drflac_open_file_with_metadata
DRFLAC_API drflac * drflac_open_file_with_metadata(const char *pFileName, drflac_meta_proc onMeta, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56629
ma_audio_buffer_uninit
MA_API void ma_audio_buffer_uninit(ma_audio_buffer *pAudioBuffer)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38411
VORBIS_need_more_data
@ VORBIS_need_more_data
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:367
DRMP3_HDR_IS_FREE_FORMAT
#define DRMP3_HDR_IS_FREE_FORMAT(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59346
drflac_open_file_and_read_pcm_frames_s32
DRFLAC_API drflac_int32 * drflac_open_file_and_read_pcm_frames_s32(const char *filename, unsigned int *channels, unsigned int *sampleRate, drflac_uint64 *totalPCMFrameCount, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59118
drflac_open_file_with_metadata_w
DRFLAC_API drflac * drflac_open_file_with_metadata_w(const wchar_t *pFileName, drflac_meta_proc onMeta, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56643
drflac__read_rice_parts_x1
static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts_x1(drflac_bs *bs, drflac_uint8 riceParam, drflac_uint32 *pZeroCounterOut, drflac_uint32 *pRiceParamPartOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:52752
ma_wav::onSeek
ma_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40862
drwav::translatedFormatTag
drwav_uint16 translatedFormatTag
Definition: porcupine/demo/c/dr_libs/dr_wav.h:840
DRWAV_VERSION_MINOR
#define DRWAV_VERSION_MINOR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39446
drflac_metadata::pRawData
const void * pRawData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:422
ma_data_source_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4515
MA_IO_ERROR
#define MA_IO_ERROR
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1679
ma_standard_sample_rate_44100
@ ma_standard_sample_rate_44100
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:413
DRMP3_ALREADY_CONNECTED
#define DRMP3_ALREADY_CONNECTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40453
ma_audio_buffer_read_pcm_frames
MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer *pAudioBuffer, void *pFramesOut, ma_uint64 frameCount, ma_bool32 loop)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38421
drwav_metadata_type_list_info_genre
@ drwav_metadata_type_list_info_genre
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39661
ma_waveform_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5363
DRMP3_MALLOC
#define DRMP3_MALLOC(sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61029
ma_hishelf2_config::frequency
double frequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2163
ma_device_info::isDefault
ma_bool32 isDefault
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3096
ma_backend_webaudio
@ ma_backend_webaudio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2807
ma_count_set_bits
static MA_INLINE unsigned int ma_count_set_bits(unsigned int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1802
ma_mutex_lock
MA_API void ma_mutex_lock(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4798
ma_context::deviceInfoLock
ma_mutex deviceInfoLock
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3218
ma_decoder_init_memory_vorbis
MA_API ma_result ma_decoder_init_memory_vorbis(const void *pData, size_t dataSize, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44046
ma_sleep
static void ma_sleep(ma_uint32 milliseconds)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:522
ma_rb_seek_write
MA_API ma_result ma_rb_seek_write(ma_rb *pRB, size_t offsetInBytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36670
drwav_container_riff
@ drwav_container_riff
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39582
drmp3dec::qmf_state
float qmf_state[15 *2 *32]
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:264
drwav_metadata_location
drwav_metadata_location
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39792
ma_rb_uninit
MA_API void ma_rb_uninit(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36429
drwav_u8_to_s16
DRWAV_API void drwav_u8_to_s16(drwav_int16 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50060
ma_context_config::jack
struct ma_context_config::@107 jack
drflac__init_private__native
static drflac_bool32 drflac__init_private__native(drflac_init_info *pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void *pUserData, void *pUserDataMD, drflac_bool32 relaxed)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55194
ma_opensl_recording_preset_voice_unprocessed
@ ma_opensl_recording_preset_voice_unprocessed
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1818
ma_resampler_config::speex
struct ma_resampler_config::@76 speex
MA_FORMAT_NOT_SUPPORTED
#define MA_FORMAT_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1715
ma_pcm_s24_to_s24
MA_API void ma_pcm_s24_to_s24(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28920
ma_share_mode
ma_share_mode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3018
drmp3__on_read_memory
static size_t drmp3__on_read_memory(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61347
ma_channel_converter_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2360
ma_device_get_master_volume
MA_API ma_result ma_device_get_master_volume(ma_device *pDevice, float *pVolume)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27632
DR_WAVE_FORMAT_ADPCM
#define DR_WAVE_FORMAT_ADPCM
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39566
c89atomic_compare_exchange_weak_explicit_ptr
static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_weak_explicit_ptr(volatile void **dst, volatile void **expected, void *desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3927
drflac_open_memory_with_metadata
DRFLAC_API drflac * drflac_open_memory_with_metadata(const void *pData, size_t dataSize, drflac_meta_proc onMeta, void *pUserData, const drflac_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56722
drwav_bytes_to_u64
DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51070
drwav_init_write_sequential
DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav *pWav, const drwav_data_format *pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void *pUserData, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48385
ma_pcm_rb_commit_write
MA_API ma_result ma_pcm_rb_commit_write(ma_pcm_rb *pRB, ma_uint32 sizeInFrames, void *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36913
drwav_metadata_type_list_all_info_strings
@ drwav_metadata_type_list_all_info_strings
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39664
ma_channel_converter_config::weights
float weights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2366
DRFLAC_IS_DIRECTORY
#define DRFLAC_IS_DIRECTORY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51372
ma_bool8
ma_uint8 ma_bool8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1528
drwav__data_chunk_size_riff
DRWAV_PRIVATE drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48239
ma_default_vfs_open__stdio
static ma_result ma_default_vfs_open__stdio(ma_vfs *pVFS, const char *pFilePath, ma_uint32 openMode, ma_vfs_file *pFile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38984
ma_context_config::tryAutoSpawn
ma_bool32 tryAutoSpawn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3174
ma_decoder__on_tell_memory
static ma_result ma_decoder__on_tell_memory(ma_decoder *pDecoder, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:43948
ma_device_config::noAutoChannels
ma_bool32 noAutoChannels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1992
ma_decoding_backend_uninit__mp3
static void ma_decoding_backend_uninit__mp3(void *pUserData, ma_data_source *pBackend, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42724
drwav__metadata_alloc
DRWAV_PRIVATE drwav_result drwav__metadata_alloc(drwav__metadata_parser *pParser, drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46938
MA_RESTRICT
#define MA_RESTRICT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:416
DRWAV_MAX_SAMPLE_RATE
#define DRWAV_MAX_SAMPLE_RATE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46379
ma_aaudio_input_preset
ma_aaudio_input_preset
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1854
ma_channel_converter::isStereoToMono
ma_bool32 isStereoToMono
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2383
ma_device_descriptor::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2049
drflac_seekpoint::pcmFrameCount
drflac_uint16 pcmFrameCount
Definition: porcupine/demo/c/dr_libs/dr_flac.h:392
ma_decoder_read_pcm_frames
MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder *pDecoder, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44808
drmp3::pSeekPoints
drmp3_seek_point * pSeekPoints
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:357
ma_hishelf2_process_pcm_frames
MA_API ma_result ma_hishelf2_process_pcm_frames(ma_hishelf2 *pFilter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32410
ma_seek_origin_start
@ ma_seek_origin_start
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5141
ma_ios_session_category_default
@ ma_ios_session_category_default
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3027
ma_encoder::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5332
ma_rb_init
MA_API ma_result ma_rb_init(size_t bufferSizeInBytes, void *pOptionalPreallocatedBuffer, const ma_allocation_callbacks *pAllocationCallbacks, ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36424
DRMP3_SIZE_MAX
#define DRMP3_SIZE_MAX
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61007
ma_noise_config_init
MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels, ma_noise_type type, ma_int32 seed, double amplitude)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45801
drwav_preinit_write
DRWAV_PRIVATE drwav_bool32 drwav_preinit_write(drwav *pWav, const drwav_data_format *pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void *pUserData, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:48268
drwav__chunk_padding_size_w64
DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46699
ma_pcm_rb_pointer_distance
MA_API ma_int32 ma_pcm_rb_pointer_distance(ma_pcm_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36940
g_drwavAlawTable
static unsigned short g_drwavAlawTable[256]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49818
ma_vfs_or_default_seek
MA_API ma_result ma_vfs_or_default_seek(ma_vfs *pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39402
drwav_int16
signed short drwav_int16
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39452
drwav_s24_to_s32
DRWAV_API void drwav_s24_to_s32(drwav_int32 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50674
ma_channel
ma_uint8 ma_channel
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1600
ma_context_sizeof
MA_API size_t ma_context_sizeof()
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26779
ma_context_config_init
MA_API ma_context_config ma_context_config_init()
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26542
ma_data_converter_config_init_default
MA_API ma_data_converter_config ma_data_converter_config_init_default()
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34511
ma_device_read__null
static ma_result ma_device_read__null(ma_device *pDevice, void *pPCMFrames, ma_uint32 frameCount, ma_uint32 *pFramesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6574
ma_event_wait__posix
static ma_result ma_event_wait__posix(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4590
ma_wav::onRead
ma_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40861
drwav_read_pcm_frames_s32__ieee
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav *pWav, drwav_uint64 framesToRead, drwav_int32 *pBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50544
drmp3dec::mdct_overlap
float mdct_overlap[2][9 *32]
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:264
drwav_acid::flags
drwav_uint32 flags
Definition: porcupine/demo/c/dr_libs/dr_wav.h:634
ma_device_config::channelMap
ma_channel channelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3130
ma_rb_acquire_write
MA_API ma_result ma_rb_acquire_write(ma_rb *pRB, size_t *pSizeInBytes, void **ppBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36535
ma_linear_resampler_process_pcm_frames_s16_upsample
static ma_result ma_linear_resampler_process_pcm_frames_s16_upsample(ma_linear_resampler *pResampler, const void *pFramesIn, ma_uint64 *pFrameCountIn, void *pFramesOut, ma_uint64 *pFrameCountOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32694
ma_wav_ds_seek
static ma_result ma_wav_ds_seek(ma_data_source *pDataSource, ma_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40888
drwav_u8_to_s32
DRWAV_API void drwav_u8_to_s32(drwav_int32 *pOut, const drwav_uint8 *pIn, size_t sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50654
DRMP3_OUT_OF_RANGE
#define DRMP3_OUT_OF_RANGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40412
MA_DEFAULT_SAMPLE_RATE
#define MA_DEFAULT_SAMPLE_RATE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:606
ma_uint16
uint16_t ma_uint16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1501
drmp3::streamCursor
drmp3_uint64 streamCursor
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:356
drwav__bswap_samples_s16
static DRWAV_INLINE void drwav__bswap_samples_s16(drwav_int16 *pSamples, drwav_uint64 sampleCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46479
MA_FREE
#define MA_FREE(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:738
drflac_crc16_bytes
static DRFLAC_INLINE drflac_uint16 drflac_crc16_bytes(drflac_uint16 crc, drflac_cache_t data, drflac_uint32 byteCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51729
DRMP3_INVALID_OPERATION
#define DRMP3_INVALID_OPERATION
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40410
drwav_smpl::smpteFormat
drwav_uint32 smpteFormat
Definition: porcupine/demo/c/dr_libs/dr_wav.h:554
ma_rb_get_subbuffer_size
MA_API size_t ma_rb_get_subbuffer_size(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36765
ma_device_config::playback
struct ma_device_config::@97 playback
ma_pcm_s32_to_s24__reference
static MA_INLINE void ma_pcm_s32_to_s24__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29290
DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE
#define DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40074
drflac_result
drflac_int32 drflac_result
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51356
ma_ios_session_category_none
@ ma_ios_session_category_none
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3028
ma_waveform::time
double time
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5377
drflac_cuesheet_track_iterator::pRunningData
const char * pRunningData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1280
ma_device_type_duplex
@ ma_device_type_duplex
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3014
ma_audio_buffer_ref::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4566
ma_rb_pointer_distance
MA_API ma_int32 ma_rb_pointer_distance(ma_rb *pRB)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36714
ma_hishelf2_process_pcm_frame_f32
static MA_INLINE void ma_hishelf2_process_pcm_frame_f32(ma_hishelf2 *pFilter, float *pFrameOut, const float *pFrameIn)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32405
DRWAV_NO_ADDRESS
#define DRWAV_NO_ADDRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39549
MA_CHANNEL_SIDE_LEFT
#define MA_CHANNEL_SIDE_LEFT
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1612
drwav__pcm_to_s32
DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32 *pOut, const drwav_uint8 *pIn, size_t totalSampleCount, unsigned int bytesPerSample)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50436
ma_channel_converter::channelMapIn
ma_channel channelMapIn[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2372
ma_device__post_init_setup
static ma_result ma_device__post_init_setup(ma_device *pDevice, ma_device_type deviceType)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26166
drmp3_bs_init
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59510
ma_default_vfs_read__stdio
static ma_result ma_default_vfs_read__stdio(ma_vfs *pVFS, ma_vfs_file file, void *pDst, size_t sizeInBytes, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39059
ma_resampler_config::algorithm
ma_resample_algorithm algorithm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2246
c89atomic_compare_and_swap_16
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_compare_and_swap_16(volatile c89atomic_uint16 *dst, c89atomic_uint16 expected, c89atomic_uint16 desired)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3453
DRMP3_BAD_PIPE
#define DRMP3_BAD_PIPE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40433
drwav_list_label_or_note::pString
char * pString
Definition: porcupine/demo/c/dr_libs/dr_wav.h:670
drwav_open_file_and_read_pcm_frames_f32
DRWAV_API float * drwav_open_file_and_read_pcm_frames_f32(const char *filename, unsigned int *channelsOut, unsigned int *sampleRateOut, drwav_uint64 *totalFrameCountOut, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:50899
ma_device_start__null
static ma_result ma_device_start__null(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6474
drflac_container
drflac_container
Definition: porcupine/demo/c/dr_libs/dr_flac.h:373
DRFLAC_NOT_IMPLEMENTED
#define DRFLAC_NOT_IMPLEMENTED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51386
ma_pcm_interleave_s16__reference
static MA_INLINE void ma_pcm_interleave_s16__reference(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28702
ma_calculate_buffer_size_in_frames_from_descriptor
MA_API ma_uint32 ma_calculate_buffer_size_in_frames_from_descriptor(const ma_device_descriptor *pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27717
drmp3d_DCT_II
static void drmp3d_DCT_II(float *grbuf, int n)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60445
drwav::memoryStreamWrite
drwav__memory_stream_write memoryStreamWrite
Definition: porcupine/demo/c/dr_libs/dr_wav.h:879
ma_device_start
MA_API ma_result ma_device_start(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27485
ma_device::internalPeriodSizeInFrames
ma_uint32 internalPeriodSizeInFrames
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3632
drmp3_find_closest_seek_point
static drmp3_bool32 drmp3_find_closest_seek_point(drmp3 *pMP3, drmp3_uint64 frameIndex, drmp3_uint32 *pSeekPointIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62146
ma_log::lock
ma_mutex lock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:594
ma_wav::pReadSeekTellUserData
void * pReadSeekTellUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40864
drwav__metadata_parser::onSeek
drwav_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46901
ma_linear_resampler_interpolate_frame_f32
static void ma_linear_resampler_interpolate_frame_f32(ma_linear_resampler *pResampler, float *MA_RESTRICT pFrameOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32602
ma_device::playback
struct ma_device::@115 playback
drflac_init_info::oggFirstBytePos
drflac_uint64 oggFirstBytePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54808
ma_backend_aaudio
@ ma_backend_aaudio
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2805
drwav_seek_to_first_pcm_frame
DRWAV_PRIVATE drwav_bool32 drwav_seek_to_first_pcm_frame(drwav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49364
drflac_metadata
Definition: porcupine/demo/c/dr_libs/dr_flac.h:409
ma_default_vfs_tell
static ma_result ma_default_vfs_tell(ma_vfs *pVFS, ma_vfs_file file, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39298
drwav_chunk_header::id
union drwav_chunk_header::@8 id
ma_biquad_float_to_fp
static ma_int32 ma_biquad_float_to_fp(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30418
ma_bpf2_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2017
drwav_cue_point::sampleByteOffset
drwav_uint32 sampleByteOffset
Definition: porcupine/demo/c/dr_libs/dr_wav.h:608
ma_pcm_rb_acquire_read
MA_API ma_result ma_pcm_rb_acquire_read(ma_pcm_rb *pRB, ma_uint32 *pSizeInFrames, void **ppBufferOut)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:36864
drflac__seek_flac_frame
static drflac_result drflac__seek_flac_frame(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54335
ma_mp3::onRead
ma_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42134
ma_get_standard_channel_map_microsoft
static void ma_get_standard_channel_map_microsoft(ma_uint32 channels, ma_channel *pChannelMap)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:35574
ma_device::type
ma_device_type type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3587
drmp3dec_scratch
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59502
ma_linear_resampler::x1
union ma_linear_resampler::@74 x1
drwav_version
DRWAV_API void drwav_version(drwav_uint32 *pMajor, drwav_uint32 *pMinor, drwav_uint32 *pRevision)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46362
DRFLAC_CONNECTION_RESET
#define DRFLAC_CONNECTION_RESET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51402
ma_decoder_init_vfs_mp3_w
MA_API ma_result ma_decoder_init_vfs_mp3_w(ma_vfs *pVFS, const wchar_t *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44649
ma_event_signal
MA_API ma_result ma_event_signal(ma_event *pEvent)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4913
drwav_unknown_metadata::chunkLocation
drwav_metadata_location chunkLocation
Definition: porcupine/demo/c/dr_libs/dr_wav.h:778
ma_vfs_callbacks::onSeek
ma_result(* onSeek)(ma_vfs *pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4655
drwav__memory_stream_write::ppData
void ** ppData
Definition: porcupine/demo/c/dr_libs/dr_wav.h:428
MA_ZERO_MEMORY
#define MA_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:746
drwav__memory_stream_write::currentWritePos
size_t currentWritePos
Definition: porcupine/demo/c/dr_libs/dr_wav.h:432
ma_device_stop__null
static ma_result ma_device_stop__null(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6484
drwav__write_byte
DRWAV_PRIVATE size_t drwav__write_byte(drwav *pWav, drwav_uint8 byte)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47827
drflac_bs::consumedBits
drflac_uint32 consumedBits
Definition: porcupine/demo/c/dr_libs/dr_flac.h:607
ma_decoder::outputSampleRate
ma_uint32 outputSampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5205
drmp3_bs::pos
int pos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59483
ma_peak2::bq
ma_biquad bq
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2110
drwav_bext::pOriginatorName
char * pOriginatorName
Definition: porcupine/demo/c/dr_libs/dr_wav.h:687
ma_semaphore_release__posix
static ma_result ma_semaphore_release__posix(ma_semaphore *pSemaphore)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4671
ma_vfs_seek
MA_API ma_result ma_vfs_seek(ma_vfs *pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:38609
drwav_init
DRWAV_API drwav_bool32 drwav_init(drwav *pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void *pUserData, const drwav_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:47795
DRMP3_NO_DATA_AVAILABLE
#define DRMP3_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40439
drmp3_seek_to_pcm_frame__seek_table
static drmp3_bool32 drmp3_seek_to_pcm_frame__seek_table(drmp3 *pMP3, drmp3_uint64 frameIndex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62162
ma_decoder_init_vfs_vorbis
MA_API ma_result ma_decoder_init_vfs_vorbis(ma_vfs *pVFS, const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44464
drmp3_bs::limit
int limit
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59483
ma_encoder_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5316
MA_CHANNEL_AUX_24
#define MA_CHANNEL_AUX_24
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1645
ma_channel_converter::channelsOut
ma_uint32 channelsOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2371
ma_context_get_log
MA_API ma_log * ma_context_get_log(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26785
ma_pcm_interleave_s24__optimized
static MA_INLINE void ma_pcm_interleave_s24__optimized(void *dst, const void **src, ma_uint64 frameCount, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29080
ma_decoder__on_tell_vfs
static ma_result ma_decoder__on_tell_vfs(ma_decoder *pDecoder, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44271
ma_peak2_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2103
ma_device_config::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3112
drwav_acid_flag_disk_based
@ drwav_acid_flag_disk_based
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:39737
ma_peak2_get_latency
MA_API ma_uint32 ma_peak2_get_latency(const ma_peak2 *pFilter)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:32167
DRMP3_NO_ADDRESS
#define DRMP3_NO_ADDRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40445
MA_BIQUAD_FIXED_POINT_SHIFT
#define MA_BIQUAD_FIXED_POINT_SHIFT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30415
drflac__on_read_ogg
static size_t drflac__on_read_ogg(void *pUserData, void *bufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55591
drwav::msadpcm
struct drwav::@10 msadpcm
ma_channel_converter_process_pcm_frames
MA_API ma_result ma_channel_converter_process_pcm_frames(ma_channel_converter *pConverter, void *pFramesOut, const void *pFramesIn, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34477
drflac_allocation_callbacks::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:566
ma_device_get_log
MA_API ma_log * ma_device_get_log(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27480
ma_context_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3160
ma_noise_read_pcm_frames
MA_API ma_uint64 ma_noise_read_pcm_frames(ma_noise *pNoise, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46227
drwav_bytes_to_s16
DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8 *data)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51049
MA_PROTOCOL_NOT_SUPPORTED
#define MA_PROTOCOL_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1700
MA_MAX_FILTER_ORDER
#define MA_MAX_FILTER_ORDER
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1758
ma_copy_and_apply_volume_factor_pcm_frames
MA_API void ma_copy_and_apply_volume_factor_pcm_frames(void *pPCMFramesOut, const void *pPCMFramesIn, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27951
ma_ptr
void * ma_ptr
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1534
ma_pcm_u8_to_f32__reference
static MA_INLINE void ma_pcm_u8_to_f32__reference(void *dst, const void *src, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28267
drwav_get_length_in_pcm_frames
DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav *pWav, drwav_uint64 *pLength)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49468
ma_loshelf2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2130
drflac::allocationCallbacks
drflac_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/dr_flac.h:697
ma_aaudio_usage_game
@ ma_aaudio_usage_game
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1834
MA_INVALID_DATA
#define MA_INVALID_DATA
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1692
MA_OUT_OF_MEMORY
#define MA_OUT_OF_MEMORY
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1663


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:14:03