pvrecorder/src/miniaudio/miniaudio.h
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 
12 /*
13 1. Introduction
14 ===============
15 miniaudio is a single file library for audio playback and capture. To use it, do the following in one .c file:
16 
17  ```c
18  #define MINIAUDIO_IMPLEMENTATION
19  #include "miniaudio.h"
20  ```
21 
22 You can do `#include "miniaudio.h"` in other parts of the program just like any other header.
23 
24 miniaudio uses the concept of a "device" as the abstraction for physical devices. The idea is that you choose a physical device to emit or capture audio from,
25 and then move data to/from the device when miniaudio tells you to. Data is delivered to and from devices asynchronously via a callback which you specify when
26 initializing the device.
27 
28 When initializing the device you first need to configure it. The device configuration allows you to specify things like the format of the data delivered via
29 the callback, the size of the internal buffer and the ID of the device you want to emit or capture audio from.
30 
31 Once you have the device configuration set up you can initialize the device. When initializing a device you need to allocate memory for the device object
32 beforehand. This gives the application complete control over how the memory is allocated. In the example below we initialize a playback device on the stack,
33 but you could allocate it on the heap if that suits your situation better.
34 
35  ```c
36  void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
37  {
38  // In playback mode copy data to pOutput. In capture mode read data from pInput. In full-duplex mode, both
39  // pOutput and pInput will be valid and you can move data from pInput into pOutput. Never process more than
40  // frameCount frames.
41  }
42 
43  int main()
44  {
45  ma_device_config config = ma_device_config_init(ma_device_type_playback);
46  config.playback.format = ma_format_f32; // Set to ma_format_unknown to use the device's native format.
47  config.playback.channels = 2; // Set to 0 to use the device's native channel count.
48  config.sampleRate = 48000; // Set to 0 to use the device's native sample rate.
49  config.dataCallback = data_callback; // This function will be called when miniaudio needs more data.
50  config.pUserData = pMyCustomData; // Can be accessed from the device object (device.pUserData).
51 
52  ma_device device;
53  if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) {
54  return -1; // Failed to initialize the device.
55  }
56 
57  ma_device_start(&device); // The device is sleeping by default so you'll need to start it manually.
58 
59  // Do something here. Probably your program's main loop.
60 
61  ma_device_uninit(&device); // This will stop the device so no need to do that manually.
62  return 0;
63  }
64  ```
65 
66 In the example above, `data_callback()` is where audio data is written and read from the device. The idea is in playback mode you cause sound to be emitted
67 from the speakers by writing audio data to the output buffer (`pOutput` in the example). In capture mode you read data from the input buffer (`pInput`) to
68 extract sound captured by the microphone. The `frameCount` parameter tells you how many frames can be written to the output buffer and read from the input
69 buffer. A "frame" is one sample for each channel. For example, in a stereo stream (2 channels), one frame is 2 samples: one for the left, one for the right.
70 The channel count is defined by the device config. The size in bytes of an individual sample is defined by the sample format which is also specified in the
71 device config. Multi-channel audio data is always interleaved, which means the samples for each frame are stored next to each other in memory. For example, in
72 a stereo stream the first pair of samples will be the left and right samples for the first frame, the second pair of samples will be the left and right samples
73 for the second frame, etc.
74 
75 The configuration of the device is defined by the `ma_device_config` structure. The config object is always initialized with `ma_device_config_init()`. It's
76 important to always initialize the config with this function as it initializes it with logical defaults and ensures your program doesn't break when new members
77 are added to the `ma_device_config` structure. The example above uses a fairly simple and standard device configuration. The call to `ma_device_config_init()`
78 takes a single parameter, which is whether or not the device is a playback, capture, duplex or loopback device (loopback devices are not supported on all
79 backends). The `config.playback.format` member sets the sample format which can be one of the following (all formats are native-endian):
80 
81  +---------------+----------------------------------------+---------------------------+
82  | Symbol | Description | Range |
83  +---------------+----------------------------------------+---------------------------+
84  | ma_format_f32 | 32-bit floating point | [-1, 1] |
85  | ma_format_s16 | 16-bit signed integer | [-32768, 32767] |
86  | ma_format_s24 | 24-bit signed integer (tightly packed) | [-8388608, 8388607] |
87  | ma_format_s32 | 32-bit signed integer | [-2147483648, 2147483647] |
88  | ma_format_u8 | 8-bit unsigned integer | [0, 255] |
89  +---------------+----------------------------------------+---------------------------+
90 
91 The `config.playback.channels` member sets the number of channels to use with the device. The channel count cannot exceed MA_MAX_CHANNELS. The
92 `config.sampleRate` member sets the sample rate (which must be the same for both playback and capture in full-duplex configurations). This is usually set to
93 44100 or 48000, but can be set to anything. It's recommended to keep this between 8000 and 384000, however.
94 
95 Note that leaving the format, channel count and/or sample rate at their default values will result in the internal device's native configuration being used
96 which is useful if you want to avoid the overhead of miniaudio's automatic data conversion.
97 
98 In addition to the sample format, channel count and sample rate, the data callback and user data pointer are also set via the config. The user data pointer is
99 not passed into the callback as a parameter, but is instead set to the `pUserData` member of `ma_device` which you can access directly since all miniaudio
100 structures are transparent.
101 
102 Initializing the device is done with `ma_device_init()`. This will return a result code telling you what went wrong, if anything. On success it will return
103 `MA_SUCCESS`. After initialization is complete the device will be in a stopped state. To start it, use `ma_device_start()`. Uninitializing the device will stop
104 it, which is what the example above does, but you can also stop the device with `ma_device_stop()`. To resume the device simply call `ma_device_start()` again.
105 Note that it's important to never stop or start the device from inside the callback. This will result in a deadlock. Instead you set a variable or signal an
106 event indicating that the device needs to stop and handle it in a different thread. The following APIs must never be called inside the callback:
107 
108  ```c
109  ma_device_init()
110  ma_device_init_ex()
111  ma_device_uninit()
112  ma_device_start()
113  ma_device_stop()
114  ```
115 
116 You must never try uninitializing and reinitializing a device inside the callback. You must also never try to stop and start it from inside the callback. There
117 are a few other things you shouldn't do in the callback depending on your requirements, however this isn't so much a thread-safety thing, but rather a
118 real-time processing thing which is beyond the scope of this introduction.
119 
120 The example above demonstrates the initialization of a playback device, but it works exactly the same for capture. All you need to do is change the device type
121 from `ma_device_type_playback` to `ma_device_type_capture` when setting up the config, like so:
122 
123  ```c
124  ma_device_config config = ma_device_config_init(ma_device_type_capture);
125  config.capture.format = MY_FORMAT;
126  config.capture.channels = MY_CHANNEL_COUNT;
127  ```
128 
129 In the data callback you just read from the input buffer (`pInput` in the example above) and leave the output buffer alone (it will be set to NULL when the
130 device type is set to `ma_device_type_capture`).
131 
132 These are the available device types and how you should handle the buffers in the callback:
133 
134  +-------------------------+--------------------------------------------------------+
135  | Device Type | Callback Behavior |
136  +-------------------------+--------------------------------------------------------+
137  | ma_device_type_playback | Write to output buffer, leave input buffer untouched. |
138  | ma_device_type_capture | Read from input buffer, leave output buffer untouched. |
139  | ma_device_type_duplex | Read from input buffer, write to output buffer. |
140  | ma_device_type_loopback | Read from input buffer, leave output buffer untouched. |
141  +-------------------------+--------------------------------------------------------+
142 
143 You will notice in the example above that the sample format and channel count is specified separately for playback and capture. This is to support different
144 data formats between the playback and capture devices in a full-duplex system. An example may be that you want to capture audio data as a monaural stream (one
145 channel), but output sound to a stereo speaker system. Note that if you use different formats between playback and capture in a full-duplex configuration you
146 will need to convert the data yourself. There are functions available to help you do this which will be explained later.
147 
148 The example above did not specify a physical device to connect to which means it will use the operating system's default device. If you have multiple physical
149 devices connected and you want to use a specific one you will need to specify the device ID in the configuration, like so:
150 
151  ```c
152  config.playback.pDeviceID = pMyPlaybackDeviceID; // Only if requesting a playback or duplex device.
153  config.capture.pDeviceID = pMyCaptureDeviceID; // Only if requesting a capture, duplex or loopback device.
154  ```
155 
156 To retrieve the device ID you will need to perform device enumeration, however this requires the use of a new concept called the "context". Conceptually
157 speaking the context sits above the device. There is one context to many devices. The purpose of the context is to represent the backend at a more global level
158 and to perform operations outside the scope of an individual device. Mainly it is used for performing run-time linking against backend libraries, initializing
159 backends and enumerating devices. The example below shows how to enumerate devices.
160 
161  ```c
162  ma_context context;
163  if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
164  // Error.
165  }
166 
167  ma_device_info* pPlaybackInfos;
168  ma_uint32 playbackCount;
169  ma_device_info* pCaptureInfos;
170  ma_uint32 captureCount;
171  if (ma_context_get_devices(&context, &pPlaybackInfos, &playbackCount, &pCaptureInfos, &captureCount) != MA_SUCCESS) {
172  // Error.
173  }
174 
175  // Loop over each device info and do something with it. Here we just print the name with their index. You may want
176  // to give the user the opportunity to choose which device they'd prefer.
177  for (ma_uint32 iDevice = 0; iDevice < playbackCount; iDevice += 1) {
178  printf("%d - %s\n", iDevice, pPlaybackInfos[iDevice].name);
179  }
180 
181  ma_device_config config = ma_device_config_init(ma_device_type_playback);
182  config.playback.pDeviceID = &pPlaybackInfos[chosenPlaybackDeviceIndex].id;
183  config.playback.format = MY_FORMAT;
184  config.playback.channels = MY_CHANNEL_COUNT;
185  config.sampleRate = MY_SAMPLE_RATE;
186  config.dataCallback = data_callback;
187  config.pUserData = pMyCustomData;
188 
189  ma_device device;
190  if (ma_device_init(&context, &config, &device) != MA_SUCCESS) {
191  // Error
192  }
193 
194  ...
195 
196  ma_device_uninit(&device);
197  ma_context_uninit(&context);
198  ```
199 
200 The first thing we do in this example is initialize a `ma_context` object with `ma_context_init()`. The first parameter is a pointer to a list of `ma_backend`
201 values which are used to override the default backend priorities. When this is NULL, as in this example, miniaudio's default priorities are used. The second
202 parameter is the number of backends listed in the array pointed to by the first parameter. The third parameter is a pointer to a `ma_context_config` object
203 which can be NULL, in which case defaults are used. The context configuration is used for setting the logging callback, custom memory allocation callbacks,
204 user-defined data and some backend-specific configurations.
205 
206 Once the context has been initialized you can enumerate devices. In the example above we use the simpler `ma_context_get_devices()`, however you can also use a
207 callback for handling devices by using `ma_context_enumerate_devices()`. When using `ma_context_get_devices()` you provide a pointer to a pointer that will,
208 upon output, be set to a pointer to a buffer containing a list of `ma_device_info` structures. You also provide a pointer to an unsigned integer that will
209 receive the number of items in the returned buffer. Do not free the returned buffers as their memory is managed internally by miniaudio.
210 
211 The `ma_device_info` structure contains an `id` member which is the ID you pass to the device config. It also contains the name of the device which is useful
212 for presenting a list of devices to the user via the UI.
213 
214 When creating your own context you will want to pass it to `ma_device_init()` when initializing the device. Passing in NULL, like we do in the first example,
215 will result in miniaudio creating the context for you, which you don't want to do since you've already created a context. Note that internally the context is
216 only tracked by it's pointer which means you must not change the location of the `ma_context` object. If this is an issue, consider using `malloc()` to
217 allocate memory for the context.
218 
219 
220 
221 2. Building
222 ===========
223 miniaudio should work cleanly out of the box without the need to download or install any dependencies. See below for platform-specific details.
224 
225 
226 2.1. Windows
227 ------------
228 The Windows build should compile cleanly on all popular compilers without the need to configure any include paths nor link to any libraries.
229 
230 2.2. macOS and iOS
231 ------------------
232 The macOS build should compile cleanly without the need to download any dependencies nor link to any libraries or frameworks. The iOS build needs to be
233 compiled as Objective-C and will need to link the relevant frameworks but should compile cleanly out of the box with Xcode. Compiling through the command line
234 requires linking to `-lpthread` and `-lm`.
235 
236 Due to the way miniaudio links to frameworks at runtime, your application may not pass Apple's notarization process. To fix this there are two options. The
237 first is to use the `MA_NO_RUNTIME_LINKING` option, like so:
238 
239  ```c
240  #ifdef __APPLE__
241  #define MA_NO_RUNTIME_LINKING
242  #endif
243  #define MINIAUDIO_IMPLEMENTATION
244  #include "miniaudio.h"
245  ```
246 
247 This will require linking with `-framework CoreFoundation -framework CoreAudio -framework AudioUnit`. Alternatively, if you would rather keep using runtime
248 linking you can add the following to your entitlements.xcent file:
249 
250  ```
251  <key>com.apple.security.cs.allow-dyld-environment-variables</key>
252  <true/>
253  <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
254  <true/>
255  ```
256 
257 
258 2.3. Linux
259 ----------
260 The Linux build only requires linking to `-ldl`, `-lpthread` and `-lm`. You do not need any development packages.
261 
262 2.4. BSD
263 --------
264 The BSD build only requires linking to `-lpthread` and `-lm`. NetBSD uses audio(4), OpenBSD uses sndio and FreeBSD uses OSS.
265 
266 2.5. Android
267 ------------
268 AAudio is the highest priority backend on Android. This should work out of the box without needing any kind of compiler configuration. Support for AAudio
269 starts with Android 8 which means older versions will fall back to OpenSL|ES which requires API level 16+.
270 
271 There have been reports that the OpenSL|ES backend fails to initialize on some Android based devices due to `dlopen()` failing to open "libOpenSLES.so". If
272 this happens on your platform you'll need to disable run-time linking with `MA_NO_RUNTIME_LINKING` and link with -lOpenSLES.
273 
274 2.6. Emscripten
275 ---------------
276 The Emscripten build emits Web Audio JavaScript directly and should compile cleanly out of the box. You cannot use -std=c* compiler flags, nor -ansi.
277 
278 
279 2.7. Build Options
280 ------------------
281 `#define` these options before including miniaudio.h.
282 
283  +----------------------------------+--------------------------------------------------------------------+
284  | Option | Description |
285  +----------------------------------+--------------------------------------------------------------------+
286  | MA_NO_WASAPI | Disables the WASAPI backend. |
287  +----------------------------------+--------------------------------------------------------------------+
288  | MA_NO_DSOUND | Disables the DirectSound backend. |
289  +----------------------------------+--------------------------------------------------------------------+
290  | MA_NO_WINMM | Disables the WinMM backend. |
291  +----------------------------------+--------------------------------------------------------------------+
292  | MA_NO_ALSA | Disables the ALSA backend. |
293  +----------------------------------+--------------------------------------------------------------------+
294  | MA_NO_PULSEAUDIO | Disables the PulseAudio backend. |
295  +----------------------------------+--------------------------------------------------------------------+
296  | MA_NO_JACK | Disables the JACK backend. |
297  +----------------------------------+--------------------------------------------------------------------+
298  | MA_NO_COREAUDIO | Disables the Core Audio backend. |
299  +----------------------------------+--------------------------------------------------------------------+
300  | MA_NO_SNDIO | Disables the sndio backend. |
301  +----------------------------------+--------------------------------------------------------------------+
302  | MA_NO_AUDIO4 | Disables the audio(4) backend. |
303  +----------------------------------+--------------------------------------------------------------------+
304  | MA_NO_OSS | Disables the OSS backend. |
305  +----------------------------------+--------------------------------------------------------------------+
306  | MA_NO_AAUDIO | Disables the AAudio backend. |
307  +----------------------------------+--------------------------------------------------------------------+
308  | MA_NO_OPENSL | Disables the OpenSL|ES backend. |
309  +----------------------------------+--------------------------------------------------------------------+
310  | MA_NO_WEBAUDIO | Disables the Web Audio backend. |
311  +----------------------------------+--------------------------------------------------------------------+
312  | MA_NO_NULL | Disables the null backend. |
313  +----------------------------------+--------------------------------------------------------------------+
314  | MA_ENABLE_ONLY_SPECIFIC_BACKENDS | Disables all backends by default and requires `MA_ENABLE_*` to |
315  | | enable specific backends. |
316  +----------------------------------+--------------------------------------------------------------------+
317  | MA_ENABLE_WASAPI | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
318  | | enable the WASAPI backend. |
319  +----------------------------------+--------------------------------------------------------------------+
320  | MA_ENABLE_DSOUND | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
321  | | enable the DirectSound backend. |
322  +----------------------------------+--------------------------------------------------------------------+
323  | MA_ENABLE_WINMM | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
324  | | enable the WinMM backend. |
325  +----------------------------------+--------------------------------------------------------------------+
326  | MA_ENABLE_ALSA | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
327  | | enable the ALSA backend. |
328  +----------------------------------+--------------------------------------------------------------------+
329  | MA_ENABLE_PULSEAUDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
330  | | enable the PulseAudio backend. |
331  +----------------------------------+--------------------------------------------------------------------+
332  | MA_ENABLE_JACK | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
333  | | enable the JACK backend. |
334  +----------------------------------+--------------------------------------------------------------------+
335  | MA_ENABLE_COREAUDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
336  | | enable the Core Audio backend. |
337  +----------------------------------+--------------------------------------------------------------------+
338  | MA_ENABLE_SNDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
339  | | enable the sndio backend. |
340  +----------------------------------+--------------------------------------------------------------------+
341  | MA_ENABLE_AUDIO4 | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
342  | | enable the audio(4) backend. |
343  +----------------------------------+--------------------------------------------------------------------+
344  | MA_ENABLE_OSS | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
345  | | enable the OSS backend. |
346  +----------------------------------+--------------------------------------------------------------------+
347  | MA_ENABLE_AAUDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
348  | | enable the AAudio backend. |
349  +----------------------------------+--------------------------------------------------------------------+
350  | MA_ENABLE_OPENSL | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
351  | | enable the OpenSL|ES backend. |
352  +----------------------------------+--------------------------------------------------------------------+
353  | MA_ENABLE_WEBAUDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
354  | | enable the Web Audio backend. |
355  +----------------------------------+--------------------------------------------------------------------+
356  | MA_ENABLE_NULL | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to |
357  | | enable the null backend. |
358  +----------------------------------+--------------------------------------------------------------------+
359  | MA_NO_DECODING | Disables decoding APIs. |
360  +----------------------------------+--------------------------------------------------------------------+
361  | MA_NO_ENCODING | Disables encoding APIs. |
362  +----------------------------------+--------------------------------------------------------------------+
363  | MA_NO_WAV | Disables the built-in WAV decoder and encoder. |
364  +----------------------------------+--------------------------------------------------------------------+
365  | MA_NO_FLAC | Disables the built-in FLAC decoder. |
366  +----------------------------------+--------------------------------------------------------------------+
367  | MA_NO_MP3 | Disables the built-in MP3 decoder. |
368  +----------------------------------+--------------------------------------------------------------------+
369  | MA_NO_DEVICE_IO | Disables playback and recording. This will disable ma_context and |
370  | | ma_device APIs. This is useful if you only want to use miniaudio's |
371  | | data conversion and/or decoding APIs. |
372  +----------------------------------+--------------------------------------------------------------------+
373  | MA_NO_THREADING | Disables the ma_thread, ma_mutex, ma_semaphore and ma_event APIs. |
374  | | This option is useful if you only need to use miniaudio for data |
375  | | conversion, decoding and/or encoding. Some families of APIs |
376  | | require threading which means the following options must also be |
377  | | set: |
378  | | |
379  | | ``` |
380  | | MA_NO_DEVICE_IO |
381  | | ``` |
382  +----------------------------------+--------------------------------------------------------------------+
383  | MA_NO_GENERATION | Disables generation APIs such a ma_waveform and ma_noise. |
384  +----------------------------------+--------------------------------------------------------------------+
385  | MA_NO_SSE2 | Disables SSE2 optimizations. |
386  +----------------------------------+--------------------------------------------------------------------+
387  | MA_NO_AVX2 | Disables AVX2 optimizations. |
388  +----------------------------------+--------------------------------------------------------------------+
389  | MA_NO_AVX512 | Disables AVX-512 optimizations. |
390  +----------------------------------+--------------------------------------------------------------------+
391  | MA_NO_NEON | Disables NEON optimizations. |
392  +----------------------------------+--------------------------------------------------------------------+
393  | MA_NO_RUNTIME_LINKING | Disables runtime linking. This is useful for passing Apple's |
394  | | notarization process. When enabling this, you may need to avoid |
395  | | using `-std=c89` or `-std=c99` on Linux builds or else you may end |
396  | | up with compilation errors due to conflicts with `timespec` and |
397  | | `timeval` data types. |
398  | | |
399  | | You may need to enable this if your target platform does not allow |
400  | | runtime linking via `dlopen()`. |
401  +----------------------------------+--------------------------------------------------------------------+
402  | MA_DEBUG_OUTPUT | Enable processing of MA_LOG_LEVEL_DEBUG messages and `printf()` |
403  | | output. |
404  +----------------------------------+--------------------------------------------------------------------+
405  | MA_COINIT_VALUE | Windows only. The value to pass to internal calls to |
406  | | `CoInitializeEx()`. Defaults to `COINIT_MULTITHREADED`. |
407  +----------------------------------+--------------------------------------------------------------------+
408  | MA_API | Controls how public APIs should be decorated. Default is `extern`. |
409  +----------------------------------+--------------------------------------------------------------------+
410  | MA_DLL | If set, configures MA_API to either import or export APIs |
411  | | depending on whether or not the implementation is being defined. |
412  | | If defining the implementation, MA_API will be configured to |
413  | | export. Otherwise it will be configured to import. This has no |
414  | | effect if MA_API is defined externally. |
415  +----------------------------------+--------------------------------------------------------------------+
416 
417 
418 3. Definitions
419 ==============
420 This section defines common terms used throughout miniaudio. Unfortunately there is often ambiguity in the use of terms throughout the audio space, so this
421 section is intended to clarify how miniaudio uses each term.
422 
423 3.1. Sample
424 -----------
425 A sample is a single unit of audio data. If the sample format is f32, then one sample is one 32-bit floating point number.
426 
427 3.2. Frame / PCM Frame
428 ----------------------
429 A frame is a group of samples equal to the number of channels. For a stereo stream a frame is 2 samples, a mono frame is 1 sample, a 5.1 surround sound frame
430 is 6 samples, etc. The terms "frame" and "PCM frame" are the same thing in miniaudio. Note that this is different to a compressed frame. If ever miniaudio
431 needs to refer to a compressed frame, such as a FLAC frame, it will always clarify what it's referring to with something like "FLAC frame".
432 
433 3.3. Channel
434 ------------
435 A stream of monaural audio that is emitted from an individual speaker in a speaker system, or received from an individual microphone in a microphone system. A
436 stereo stream has two channels (a left channel, and a right channel), a 5.1 surround sound system has 6 channels, etc. Some audio systems refer to a channel as
437 a complex audio stream that's mixed with other channels to produce the final mix - this is completely different to miniaudio's use of the term "channel" and
438 should not be confused.
439 
440 3.4. Sample Rate
441 ----------------
442 The sample rate in miniaudio is always expressed in Hz, such as 44100, 48000, etc. It's the number of PCM frames that are processed per second.
443 
444 3.5. Formats
445 ------------
446 Throughout miniaudio you will see references to different sample formats:
447 
448  +---------------+----------------------------------------+---------------------------+
449  | Symbol | Description | Range |
450  +---------------+----------------------------------------+---------------------------+
451  | ma_format_f32 | 32-bit floating point | [-1, 1] |
452  | ma_format_s16 | 16-bit signed integer | [-32768, 32767] |
453  | ma_format_s24 | 24-bit signed integer (tightly packed) | [-8388608, 8388607] |
454  | ma_format_s32 | 32-bit signed integer | [-2147483648, 2147483647] |
455  | ma_format_u8 | 8-bit unsigned integer | [0, 255] |
456  +---------------+----------------------------------------+---------------------------+
457 
458 All formats are native-endian.
459 
460 
461 
462 4. Decoding
463 ===========
464 The `ma_decoder` API is used for reading audio files. Decoders are completely decoupled from devices and can be used independently. The following formats are
465 supported:
466 
467  +---------+------------------+----------+
468  | Format | Decoding Backend | Built-In |
469  +---------+------------------+----------+
470  | WAV | dr_wav | Yes |
471  | MP3 | dr_mp3 | Yes |
472  | FLAC | dr_flac | Yes |
473  | Vorbis | stb_vorbis | No |
474  +---------+------------------+----------+
475 
476 Vorbis is supported via stb_vorbis which can be enabled by including the header section before the implementation of miniaudio, like the following:
477 
478  ```c
479  #define STB_VORBIS_HEADER_ONLY
480  #include "extras/stb_vorbis.c" // Enables Vorbis decoding.
481 
482  #define MINIAUDIO_IMPLEMENTATION
483  #include "miniaudio.h"
484 
485  // The stb_vorbis implementation must come after the implementation of miniaudio.
486  #undef STB_VORBIS_HEADER_ONLY
487  #include "extras/stb_vorbis.c"
488  ```
489 
490 A copy of stb_vorbis is included in the "extras" folder in the miniaudio repository (https://github.com/mackron/miniaudio).
491 
492 Built-in decoders are amalgamated into the implementation section of miniaudio. You can disable the built-in decoders by specifying one or more of the
493 following options before the miniaudio implementation:
494 
495  ```c
496  #define MA_NO_WAV
497  #define MA_NO_MP3
498  #define MA_NO_FLAC
499  ```
500 
501 Disabling built-in decoding libraries is useful if you use these libraries independantly of the `ma_decoder` API.
502 
503 A decoder can be initialized from a file with `ma_decoder_init_file()`, a block of memory with `ma_decoder_init_memory()`, or from data delivered via callbacks
504 with `ma_decoder_init()`. Here is an example for loading a decoder from a file:
505 
506  ```c
507  ma_decoder decoder;
508  ma_result result = ma_decoder_init_file("MySong.mp3", NULL, &decoder);
509  if (result != MA_SUCCESS) {
510  return false; // An error occurred.
511  }
512 
513  ...
514 
515  ma_decoder_uninit(&decoder);
516  ```
517 
518 When initializing a decoder, you can optionally pass in a pointer to a `ma_decoder_config` object (the `NULL` argument in the example above) which allows you
519 to configure the output format, channel count, sample rate and channel map:
520 
521  ```c
522  ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 2, 48000);
523  ```
524 
525 When passing in `NULL` for decoder config in `ma_decoder_init*()`, the output format will be the same as that defined by the decoding backend.
526 
527 Data is read from the decoder as PCM frames. This will return the number of PCM frames actually read. If the return value is less than the requested number of
528 PCM frames it means you've reached the end:
529 
530  ```c
531  ma_uint64 framesRead = ma_decoder_read_pcm_frames(pDecoder, pFrames, framesToRead);
532  if (framesRead < framesToRead) {
533  // Reached the end.
534  }
535  ```
536 
537 You can also seek to a specific frame like so:
538 
539  ```c
540  ma_result result = ma_decoder_seek_to_pcm_frame(pDecoder, targetFrame);
541  if (result != MA_SUCCESS) {
542  return false; // An error occurred.
543  }
544  ```
545 
546 If you want to loop back to the start, you can simply seek back to the first PCM frame:
547 
548  ```c
549  ma_decoder_seek_to_pcm_frame(pDecoder, 0);
550  ```
551 
552 When loading a decoder, miniaudio uses a trial and error technique to find the appropriate decoding backend. This can be unnecessarily inefficient if the type
553 is already known. In this case you can use `encodingFormat` variable in the device config to specify a specific encoding format you want to decode:
554 
555  ```c
556  decoderConfig.encodingFormat = ma_encoding_format_wav;
557  ```
558 
559 See the `ma_encoding_format` enum for possible encoding formats.
560 
561 The `ma_decoder_init_file()` API will try using the file extension to determine which decoding backend to prefer.
562 
563 
564 
565 5. Encoding
566 ===========
567 The `ma_encoding` API is used for writing audio files. The only supported output format is WAV which is achieved via dr_wav which is amalgamated into the
568 implementation section of miniaudio. This can be disabled by specifying the following option before the implementation of miniaudio:
569 
570  ```c
571  #define MA_NO_WAV
572  ```
573 
574 An encoder can be initialized to write to a file with `ma_encoder_init_file()` or from data delivered via callbacks with `ma_encoder_init()`. Below is an
575 example for initializing an encoder to output to a file.
576 
577  ```c
578  ma_encoder_config config = ma_encoder_config_init(ma_resource_format_wav, FORMAT, CHANNELS, SAMPLE_RATE);
579  ma_encoder encoder;
580  ma_result result = ma_encoder_init_file("my_file.wav", &config, &encoder);
581  if (result != MA_SUCCESS) {
582  // Error
583  }
584 
585  ...
586 
587  ma_encoder_uninit(&encoder);
588  ```
589 
590 When initializing an encoder you must specify a config which is initialized with `ma_encoder_config_init()`. Here you must specify the file type, the output
591 sample format, output channel count and output sample rate. The following file types are supported:
592 
593  +------------------------+-------------+
594  | Enum | Description |
595  +------------------------+-------------+
596  | ma_resource_format_wav | WAV |
597  +------------------------+-------------+
598 
599 If the format, channel count or sample rate is not supported by the output file type an error will be returned. The encoder will not perform data conversion so
600 you will need to convert it before outputting any audio data. To output audio data, use `ma_encoder_write_pcm_frames()`, like in the example below:
601 
602  ```c
603  framesWritten = ma_encoder_write_pcm_frames(&encoder, pPCMFramesToWrite, framesToWrite);
604  ```
605 
606 Encoders must be uninitialized with `ma_encoder_uninit()`.
607 
608 
609 6. Data Conversion
610 ==================
611 A data conversion API is included with miniaudio which supports the majority of data conversion requirements. This supports conversion between sample formats,
612 channel counts (with channel mapping) and sample rates.
613 
614 
615 6.1. Sample Format Conversion
616 -----------------------------
617 Conversion between sample formats is achieved with the `ma_pcm_*_to_*()`, `ma_pcm_convert()` and `ma_convert_pcm_frames_format()` APIs. Use `ma_pcm_*_to_*()`
618 to convert between two specific formats. Use `ma_pcm_convert()` to convert based on a `ma_format` variable. Use `ma_convert_pcm_frames_format()` to convert
619 PCM frames where you want to specify the frame count and channel count as a variable instead of the total sample count.
620 
621 
622 6.1.1. Dithering
623 ----------------
624 Dithering can be set using the ditherMode parameter.
625 
626 The different dithering modes include the following, in order of efficiency:
627 
628  +-----------+--------------------------+
629  | Type | Enum Token |
630  +-----------+--------------------------+
631  | None | ma_dither_mode_none |
632  | Rectangle | ma_dither_mode_rectangle |
633  | Triangle | ma_dither_mode_triangle |
634  +-----------+--------------------------+
635 
636 Note that even if the dither mode is set to something other than `ma_dither_mode_none`, it will be ignored for conversions where dithering is not needed.
637 Dithering is available for the following conversions:
638 
639  ```
640  s16 -> u8
641  s24 -> u8
642  s32 -> u8
643  f32 -> u8
644  s24 -> s16
645  s32 -> s16
646  f32 -> s16
647  ```
648 
649 Note that it is not an error to pass something other than ma_dither_mode_none for conversions where dither is not used. It will just be ignored.
650 
651 
652 
653 6.2. Channel Conversion
654 -----------------------
655 Channel conversion is used for channel rearrangement and conversion from one channel count to another. The `ma_channel_converter` API is used for channel
656 conversion. Below is an example of initializing a simple channel converter which converts from mono to stereo.
657 
658  ```c
659  ma_channel_converter_config config = ma_channel_converter_config_init(
660  ma_format, // Sample format
661  1, // Input channels
662  NULL, // Input channel map
663  2, // Output channels
664  NULL, // Output channel map
665  ma_channel_mix_mode_default); // The mixing algorithm to use when combining channels.
666 
667  result = ma_channel_converter_init(&config, &converter);
668  if (result != MA_SUCCESS) {
669  // Error.
670  }
671  ```
672 
673 To perform the conversion simply call `ma_channel_converter_process_pcm_frames()` like so:
674 
675  ```c
676  ma_result result = ma_channel_converter_process_pcm_frames(&converter, pFramesOut, pFramesIn, frameCount);
677  if (result != MA_SUCCESS) {
678  // Error.
679  }
680  ```
681 
682 It is up to the caller to ensure the output buffer is large enough to accomodate the new PCM frames.
683 
684 Input and output PCM frames are always interleaved. Deinterleaved layouts are not supported.
685 
686 
687 6.2.1. Channel Mapping
688 ----------------------
689 In addition to converting from one channel count to another, like the example above, the channel converter can also be used to rearrange channels. When
690 initializing the channel converter, you can optionally pass in channel maps for both the input and output frames. If the channel counts are the same, and each
691 channel map contains the same channel positions with the exception that they're in a different order, a simple shuffling of the channels will be performed. If,
692 however, there is not a 1:1 mapping of channel positions, or the channel counts differ, the input channels will be mixed based on a mixing mode which is
693 specified when initializing the `ma_channel_converter_config` object.
694 
695 When converting from mono to multi-channel, the mono channel is simply copied to each output channel. When going the other way around, the audio of each output
696 channel is simply averaged and copied to the mono channel.
697 
698 In more complicated cases blending is used. The `ma_channel_mix_mode_simple` mode will drop excess channels and silence extra channels. For example, converting
699 from 4 to 2 channels, the 3rd and 4th channels will be dropped, whereas converting from 2 to 4 channels will put silence into the 3rd and 4th channels.
700 
701 The `ma_channel_mix_mode_rectangle` mode uses spacial locality based on a rectangle to compute a simple distribution between input and output. Imagine sitting
702 in the middle of a room, with speakers on the walls representing channel positions. The MA_CHANNEL_FRONT_LEFT position can be thought of as being in the corner
703 of the front and left walls.
704 
705 Finally, the `ma_channel_mix_mode_custom_weights` mode can be used to use custom user-defined weights. Custom weights can be passed in as the last parameter of
706 `ma_channel_converter_config_init()`.
707 
708 Predefined channel maps can be retrieved with `ma_get_standard_channel_map()`. This takes a `ma_standard_channel_map` enum as it's first parameter, which can
709 be one of the following:
710 
711  +-----------------------------------+-----------------------------------------------------------+
712  | Name | Description |
713  +-----------------------------------+-----------------------------------------------------------+
714  | ma_standard_channel_map_default | Default channel map used by miniaudio. See below. |
715  | ma_standard_channel_map_microsoft | Channel map used by Microsoft's bitfield channel maps. |
716  | ma_standard_channel_map_alsa | Default ALSA channel map. |
717  | ma_standard_channel_map_rfc3551 | RFC 3551. Based on AIFF. |
718  | ma_standard_channel_map_flac | FLAC channel map. |
719  | ma_standard_channel_map_vorbis | Vorbis channel map. |
720  | ma_standard_channel_map_sound4 | FreeBSD's sound(4). |
721  | ma_standard_channel_map_sndio | sndio channel map. http://www.sndio.org/tips.html. |
722  | ma_standard_channel_map_webaudio | https://webaudio.github.io/web-audio-api/#ChannelOrdering |
723  +-----------------------------------+-----------------------------------------------------------+
724 
725 Below are the channel maps used by default in miniaudio (`ma_standard_channel_map_default`):
726 
727  +---------------+---------------------------------+
728  | Channel Count | Mapping |
729  +---------------+---------------------------------+
730  | 1 (Mono) | 0: MA_CHANNEL_MONO |
731  +---------------+---------------------------------+
732  | 2 (Stereo) | 0: MA_CHANNEL_FRONT_LEFT <br> |
733  | | 1: MA_CHANNEL_FRONT_RIGHT |
734  +---------------+---------------------------------+
735  | 3 | 0: MA_CHANNEL_FRONT_LEFT <br> |
736  | | 1: MA_CHANNEL_FRONT_RIGHT <br> |
737  | | 2: MA_CHANNEL_FRONT_CENTER |
738  +---------------+---------------------------------+
739  | 4 (Surround) | 0: MA_CHANNEL_FRONT_LEFT <br> |
740  | | 1: MA_CHANNEL_FRONT_RIGHT <br> |
741  | | 2: MA_CHANNEL_FRONT_CENTER <br> |
742  | | 3: MA_CHANNEL_BACK_CENTER |
743  +---------------+---------------------------------+
744  | 5 | 0: MA_CHANNEL_FRONT_LEFT <br> |
745  | | 1: MA_CHANNEL_FRONT_RIGHT <br> |
746  | | 2: MA_CHANNEL_FRONT_CENTER <br> |
747  | | 3: MA_CHANNEL_BACK_LEFT <br> |
748  | | 4: MA_CHANNEL_BACK_RIGHT |
749  +---------------+---------------------------------+
750  | 6 (5.1) | 0: MA_CHANNEL_FRONT_LEFT <br> |
751  | | 1: MA_CHANNEL_FRONT_RIGHT <br> |
752  | | 2: MA_CHANNEL_FRONT_CENTER <br> |
753  | | 3: MA_CHANNEL_LFE <br> |
754  | | 4: MA_CHANNEL_SIDE_LEFT <br> |
755  | | 5: MA_CHANNEL_SIDE_RIGHT |
756  +---------------+---------------------------------+
757  | 7 | 0: MA_CHANNEL_FRONT_LEFT <br> |
758  | | 1: MA_CHANNEL_FRONT_RIGHT <br> |
759  | | 2: MA_CHANNEL_FRONT_CENTER <br> |
760  | | 3: MA_CHANNEL_LFE <br> |
761  | | 4: MA_CHANNEL_BACK_CENTER <br> |
762  | | 4: MA_CHANNEL_SIDE_LEFT <br> |
763  | | 5: MA_CHANNEL_SIDE_RIGHT |
764  +---------------+---------------------------------+
765  | 8 (7.1) | 0: MA_CHANNEL_FRONT_LEFT <br> |
766  | | 1: MA_CHANNEL_FRONT_RIGHT <br> |
767  | | 2: MA_CHANNEL_FRONT_CENTER <br> |
768  | | 3: MA_CHANNEL_LFE <br> |
769  | | 4: MA_CHANNEL_BACK_LEFT <br> |
770  | | 5: MA_CHANNEL_BACK_RIGHT <br> |
771  | | 6: MA_CHANNEL_SIDE_LEFT <br> |
772  | | 7: MA_CHANNEL_SIDE_RIGHT |
773  +---------------+---------------------------------+
774  | Other | All channels set to 0. This |
775  | | is equivalent to the same |
776  | | mapping as the device. |
777  +---------------+---------------------------------+
778 
779 
780 
781 6.3. Resampling
782 ---------------
783 Resampling is achieved with the `ma_resampler` object. To create a resampler object, do something like the following:
784 
785  ```c
786  ma_resampler_config config = ma_resampler_config_init(
787  ma_format_s16,
788  channels,
789  sampleRateIn,
790  sampleRateOut,
791  ma_resample_algorithm_linear);
792 
793  ma_resampler resampler;
794  ma_result result = ma_resampler_init(&config, &resampler);
795  if (result != MA_SUCCESS) {
796  // An error occurred...
797  }
798  ```
799 
800 Do the following to uninitialize the resampler:
801 
802  ```c
803  ma_resampler_uninit(&resampler);
804  ```
805 
806 The following example shows how data can be processed
807 
808  ```c
809  ma_uint64 frameCountIn = 1000;
810  ma_uint64 frameCountOut = 2000;
811  ma_result result = ma_resampler_process_pcm_frames(&resampler, pFramesIn, &frameCountIn, pFramesOut, &frameCountOut);
812  if (result != MA_SUCCESS) {
813  // An error occurred...
814  }
815 
816  // At this point, frameCountIn contains the number of input frames that were consumed and frameCountOut contains the
817  // number of output frames written.
818  ```
819 
820 To initialize the resampler you first need to set up a config (`ma_resampler_config`) with `ma_resampler_config_init()`. You need to specify the sample format
821 you want to use, the number of channels, the input and output sample rate, and the algorithm.
822 
823 The sample format can be either `ma_format_s16` or `ma_format_f32`. If you need a different format you will need to perform pre- and post-conversions yourself
824 where necessary. Note that the format is the same for both input and output. The format cannot be changed after initialization.
825 
826 The resampler supports multiple channels and is always interleaved (both input and output). The channel count cannot be changed after initialization.
827 
828 The sample rates can be anything other than zero, and are always specified in hertz. They should be set to something like 44100, etc. The sample rate is the
829 only configuration property that can be changed after initialization.
830 
831 The miniaudio resampler supports multiple algorithms:
832 
833  +-----------+------------------------------+
834  | Algorithm | Enum Token |
835  +-----------+------------------------------+
836  | Linear | ma_resample_algorithm_linear |
837  | Speex | ma_resample_algorithm_speex |
838  +-----------+------------------------------+
839 
840 Because Speex is not public domain it is strictly opt-in and the code is stored in separate files. if you opt-in to the Speex backend you will need to consider
841 it's license, the text of which can be found in it's source files in "extras/speex_resampler". Details on how to opt-in to the Speex resampler is explained in
842 the Speex Resampler section below.
843 
844 The algorithm cannot be changed after initialization.
845 
846 Processing always happens on a per PCM frame basis and always assumes interleaved input and output. De-interleaved processing is not supported. To process
847 frames, use `ma_resampler_process_pcm_frames()`. On input, this function takes the number of output frames you can fit in the output buffer and the number of
848 input frames contained in the input buffer. On output these variables contain the number of output frames that were written to the output buffer and the
849 number of input frames that were consumed in the process. You can pass in NULL for the input buffer in which case it will be treated as an infinitely large
850 buffer of zeros. The output buffer can also be NULL, in which case the processing will be treated as seek.
851 
852 The sample rate can be changed dynamically on the fly. You can change this with explicit sample rates with `ma_resampler_set_rate()` and also with a decimal
853 ratio with `ma_resampler_set_rate_ratio()`. The ratio is in/out.
854 
855 Sometimes it's useful to know exactly how many input frames will be required to output a specific number of frames. You can calculate this with
856 `ma_resampler_get_required_input_frame_count()`. Likewise, it's sometimes useful to know exactly how many frames would be output given a certain number of
857 input frames. You can do this with `ma_resampler_get_expected_output_frame_count()`.
858 
859 Due to the nature of how resampling works, the resampler introduces some latency. This can be retrieved in terms of both the input rate and the output rate
860 with `ma_resampler_get_input_latency()` and `ma_resampler_get_output_latency()`.
861 
862 
863 6.3.1. Resampling Algorithms
864 ----------------------------
865 The choice of resampling algorithm depends on your situation and requirements. The linear resampler is the most efficient and has the least amount of latency,
866 but at the expense of poorer quality. The Speex resampler is higher quality, but slower with more latency. It also performs several heap allocations internally
867 for memory management.
868 
869 
870 6.3.1.1. Linear Resampling
871 --------------------------
872 The linear resampler is the fastest, but comes at the expense of poorer quality. There is, however, some control over the quality of the linear resampler which
873 may make it a suitable option depending on your requirements.
874 
875 The linear resampler performs low-pass filtering before or after downsampling or upsampling, depending on the sample rates you're converting between. When
876 decreasing the sample rate, the low-pass filter will be applied before downsampling. When increasing the rate it will be performed after upsampling. By default
877 a fourth order low-pass filter will be applied. This can be configured via the `lpfOrder` configuration variable. Setting this to 0 will disable filtering.
878 
879 The low-pass filter has a cutoff frequency which defaults to half the sample rate of the lowest of the input and output sample rates (Nyquist Frequency). This
880 can be controlled with the `lpfNyquistFactor` config variable. This defaults to 1, and should be in the range of 0..1, although a value of 0 does not make
881 sense and should be avoided. A value of 1 will use the Nyquist Frequency as the cutoff. A value of 0.5 will use half the Nyquist Frequency as the cutoff, etc.
882 Values less than 1 will result in more washed out sound due to more of the higher frequencies being removed. This config variable has no impact on performance
883 and is a purely perceptual configuration.
884 
885 The API for the linear resampler is the same as the main resampler API, only it's called `ma_linear_resampler`.
886 
887 
888 6.3.1.2. Speex Resampling
889 -------------------------
890 The Speex resampler is made up of third party code which is released under the BSD license. Because it is licensed differently to miniaudio, which is public
891 domain, it is strictly opt-in and all of it's code is stored in separate files. If you opt-in to the Speex resampler you must consider the license text in it's
892 source files. To opt-in, you must first `#include` the following file before the implementation of miniaudio.h:
893 
894  ```c
895  #include "extras/speex_resampler/ma_speex_resampler.h"
896  ```
897 
898 Both the header and implementation is contained within the same file. The implementation can be included in your program like so:
899 
900  ```c
901  #define MINIAUDIO_SPEEX_RESAMPLER_IMPLEMENTATION
902  #include "extras/speex_resampler/ma_speex_resampler.h"
903  ```
904 
905 Note that even if you opt-in to the Speex backend, miniaudio won't use it unless you explicitly ask for it in the respective config of the object you are
906 initializing. If you try to use the Speex resampler without opting in, initialization of the `ma_resampler` object will fail with `MA_NO_BACKEND`.
907 
908 The only configuration option to consider with the Speex resampler is the `speex.quality` config variable. This is a value between 0 and 10, with 0 being
909 the fastest with the poorest quality and 10 being the slowest with the highest quality. The default value is 3.
910 
911 
912 
913 6.4. General Data Conversion
914 ----------------------------
915 The `ma_data_converter` API can be used to wrap sample format conversion, channel conversion and resampling into one operation. This is what miniaudio uses
916 internally to convert between the format requested when the device was initialized and the format of the backend's native device. The API for general data
917 conversion is very similar to the resampling API. Create a `ma_data_converter` object like this:
918 
919  ```c
920  ma_data_converter_config config = ma_data_converter_config_init(
921  inputFormat,
922  outputFormat,
923  inputChannels,
924  outputChannels,
925  inputSampleRate,
926  outputSampleRate
927  );
928 
929  ma_data_converter converter;
930  ma_result result = ma_data_converter_init(&config, &converter);
931  if (result != MA_SUCCESS) {
932  // An error occurred...
933  }
934  ```
935 
936 In the example above we use `ma_data_converter_config_init()` to initialize the config, however there's many more properties that can be configured, such as
937 channel maps and resampling quality. Something like the following may be more suitable depending on your requirements:
938 
939  ```c
940  ma_data_converter_config config = ma_data_converter_config_init_default();
941  config.formatIn = inputFormat;
942  config.formatOut = outputFormat;
943  config.channelsIn = inputChannels;
944  config.channelsOut = outputChannels;
945  config.sampleRateIn = inputSampleRate;
946  config.sampleRateOut = outputSampleRate;
947  ma_get_standard_channel_map(ma_standard_channel_map_flac, config.channelCountIn, config.channelMapIn);
948  config.resampling.linear.lpfOrder = MA_MAX_FILTER_ORDER;
949  ```
950 
951 Do the following to uninitialize the data converter:
952 
953  ```c
954  ma_data_converter_uninit(&converter);
955  ```
956 
957 The following example shows how data can be processed
958 
959  ```c
960  ma_uint64 frameCountIn = 1000;
961  ma_uint64 frameCountOut = 2000;
962  ma_result result = ma_data_converter_process_pcm_frames(&converter, pFramesIn, &frameCountIn, pFramesOut, &frameCountOut);
963  if (result != MA_SUCCESS) {
964  // An error occurred...
965  }
966 
967  // At this point, frameCountIn contains the number of input frames that were consumed and frameCountOut contains the number
968  // of output frames written.
969  ```
970 
971 The data converter supports multiple channels and is always interleaved (both input and output). The channel count cannot be changed after initialization.
972 
973 Sample rates can be anything other than zero, and are always specified in hertz. They should be set to something like 44100, etc. The sample rate is the only
974 configuration property that can be changed after initialization, but only if the `resampling.allowDynamicSampleRate` member of `ma_data_converter_config` is
975 set to `MA_TRUE`. To change the sample rate, use `ma_data_converter_set_rate()` or `ma_data_converter_set_rate_ratio()`. The ratio must be in/out. The
976 resampling algorithm cannot be changed after initialization.
977 
978 Processing always happens on a per PCM frame basis and always assumes interleaved input and output. De-interleaved processing is not supported. To process
979 frames, use `ma_data_converter_process_pcm_frames()`. On input, this function takes the number of output frames you can fit in the output buffer and the number
980 of input frames contained in the input buffer. On output these variables contain the number of output frames that were written to the output buffer and the
981 number of input frames that were consumed in the process. You can pass in NULL for the input buffer in which case it will be treated as an infinitely large
982 buffer of zeros. The output buffer can also be NULL, in which case the processing will be treated as seek.
983 
984 Sometimes it's useful to know exactly how many input frames will be required to output a specific number of frames. You can calculate this with
985 `ma_data_converter_get_required_input_frame_count()`. Likewise, it's sometimes useful to know exactly how many frames would be output given a certain number of
986 input frames. You can do this with `ma_data_converter_get_expected_output_frame_count()`.
987 
988 Due to the nature of how resampling works, the data converter introduces some latency if resampling is required. This can be retrieved in terms of both the
989 input rate and the output rate with `ma_data_converter_get_input_latency()` and `ma_data_converter_get_output_latency()`.
990 
991 
992 
993 7. Filtering
994 ============
995 
996 7.1. Biquad Filtering
997 ---------------------
998 Biquad filtering is achieved with the `ma_biquad` API. Example:
999 
1000  ```c
1001  ma_biquad_config config = ma_biquad_config_init(ma_format_f32, channels, b0, b1, b2, a0, a1, a2);
1002  ma_result result = ma_biquad_init(&config, &biquad);
1003  if (result != MA_SUCCESS) {
1004  // Error.
1005  }
1006 
1007  ...
1008 
1009  ma_biquad_process_pcm_frames(&biquad, pFramesOut, pFramesIn, frameCount);
1010  ```
1011 
1012 Biquad filtering is implemented using transposed direct form 2. The numerator coefficients are b0, b1 and b2, and the denominator coefficients are a0, a1 and
1013 a2. The a0 coefficient is required and coefficients must not be pre-normalized.
1014 
1015 Supported formats are `ma_format_s16` and `ma_format_f32`. If you need to use a different format you need to convert it yourself beforehand. When using
1016 `ma_format_s16` the biquad filter will use fixed point arithmetic. When using `ma_format_f32`, floating point arithmetic will be used.
1017 
1018 Input and output frames are always interleaved.
1019 
1020 Filtering can be applied in-place by passing in the same pointer for both the input and output buffers, like so:
1021 
1022  ```c
1023  ma_biquad_process_pcm_frames(&biquad, pMyData, pMyData, frameCount);
1024  ```
1025 
1026 If you need to change the values of the coefficients, but maintain the values in the registers you can do so with `ma_biquad_reinit()`. This is useful if you
1027 need to change the properties of the filter while keeping the values of registers valid to avoid glitching. Do not use `ma_biquad_init()` for this as it will
1028 do a full initialization which involves clearing the registers to 0. Note that changing the format or channel count after initialization is invalid and will
1029 result in an error.
1030 
1031 
1032 7.2. Low-Pass Filtering
1033 -----------------------
1034 Low-pass filtering is achieved with the following APIs:
1035 
1036  +---------+------------------------------------------+
1037  | API | Description |
1038  +---------+------------------------------------------+
1039  | ma_lpf1 | First order low-pass filter |
1040  | ma_lpf2 | Second order low-pass filter |
1041  | ma_lpf | High order low-pass filter (Butterworth) |
1042  +---------+------------------------------------------+
1043 
1044 Low-pass filter example:
1045 
1046  ```c
1047  ma_lpf_config config = ma_lpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
1048  ma_result result = ma_lpf_init(&config, &lpf);
1049  if (result != MA_SUCCESS) {
1050  // Error.
1051  }
1052 
1053  ...
1054 
1055  ma_lpf_process_pcm_frames(&lpf, pFramesOut, pFramesIn, frameCount);
1056  ```
1057 
1058 Supported formats are `ma_format_s16` and` ma_format_f32`. If you need to use a different format you need to convert it yourself beforehand. Input and output
1059 frames are always interleaved.
1060 
1061 Filtering can be applied in-place by passing in the same pointer for both the input and output buffers, like so:
1062 
1063  ```c
1064  ma_lpf_process_pcm_frames(&lpf, pMyData, pMyData, frameCount);
1065  ```
1066 
1067 The maximum filter order is limited to `MA_MAX_FILTER_ORDER` which is set to 8. If you need more, you can chain first and second order filters together.
1068 
1069  ```c
1070  for (iFilter = 0; iFilter < filterCount; iFilter += 1) {
1071  ma_lpf2_process_pcm_frames(&lpf2[iFilter], pMyData, pMyData, frameCount);
1072  }
1073  ```
1074 
1075 If you need to change the configuration of the filter, but need to maintain the state of internal registers you can do so with `ma_lpf_reinit()`. This may be
1076 useful if you need to change the sample rate and/or cutoff frequency dynamically while maintaing smooth transitions. Note that changing the format or channel
1077 count after initialization is invalid and will result in an error.
1078 
1079 The `ma_lpf` object supports a configurable order, but if you only need a first order filter you may want to consider using `ma_lpf1`. Likewise, if you only
1080 need a second order filter you can use `ma_lpf2`. The advantage of this is that they're lighter weight and a bit more efficient.
1081 
1082 If an even filter order is specified, a series of second order filters will be processed in a chain. If an odd filter order is specified, a first order filter
1083 will be applied, followed by a series of second order filters in a chain.
1084 
1085 
1086 7.3. High-Pass Filtering
1087 ------------------------
1088 High-pass filtering is achieved with the following APIs:
1089 
1090  +---------+-------------------------------------------+
1091  | API | Description |
1092  +---------+-------------------------------------------+
1093  | ma_hpf1 | First order high-pass filter |
1094  | ma_hpf2 | Second order high-pass filter |
1095  | ma_hpf | High order high-pass filter (Butterworth) |
1096  +---------+-------------------------------------------+
1097 
1098 High-pass filters work exactly the same as low-pass filters, only the APIs are called `ma_hpf1`, `ma_hpf2` and `ma_hpf`. See example code for low-pass filters
1099 for example usage.
1100 
1101 
1102 7.4. Band-Pass Filtering
1103 ------------------------
1104 Band-pass filtering is achieved with the following APIs:
1105 
1106  +---------+-------------------------------+
1107  | API | Description |
1108  +---------+-------------------------------+
1109  | ma_bpf2 | Second order band-pass filter |
1110  | ma_bpf | High order band-pass filter |
1111  +---------+-------------------------------+
1112 
1113 Band-pass filters work exactly the same as low-pass filters, only the APIs are called `ma_bpf2` and `ma_hpf`. See example code for low-pass filters for example
1114 usage. Note that the order for band-pass filters must be an even number which means there is no first order band-pass filter, unlike low-pass and high-pass
1115 filters.
1116 
1117 
1118 7.5. Notch Filtering
1119 --------------------
1120 Notch filtering is achieved with the following APIs:
1121 
1122  +-----------+------------------------------------------+
1123  | API | Description |
1124  +-----------+------------------------------------------+
1125  | ma_notch2 | Second order notching filter |
1126  +-----------+------------------------------------------+
1127 
1128 
1129 7.6. Peaking EQ Filtering
1130 -------------------------
1131 Peaking filtering is achieved with the following APIs:
1132 
1133  +----------+------------------------------------------+
1134  | API | Description |
1135  +----------+------------------------------------------+
1136  | ma_peak2 | Second order peaking filter |
1137  +----------+------------------------------------------+
1138 
1139 
1140 7.7. Low Shelf Filtering
1141 ------------------------
1142 Low shelf filtering is achieved with the following APIs:
1143 
1144  +-------------+------------------------------------------+
1145  | API | Description |
1146  +-------------+------------------------------------------+
1147  | ma_loshelf2 | Second order low shelf filter |
1148  +-------------+------------------------------------------+
1149 
1150 Where a high-pass filter is used to eliminate lower frequencies, a low shelf filter can be used to just turn them down rather than eliminate them entirely.
1151 
1152 
1153 7.8. High Shelf Filtering
1154 -------------------------
1155 High shelf filtering is achieved with the following APIs:
1156 
1157  +-------------+------------------------------------------+
1158  | API | Description |
1159  +-------------+------------------------------------------+
1160  | ma_hishelf2 | Second order high shelf filter |
1161  +-------------+------------------------------------------+
1162 
1163 The high shelf filter has the same API as the low shelf filter, only you would use `ma_hishelf` instead of `ma_loshelf`. Where a low shelf filter is used to
1164 adjust the volume of low frequencies, the high shelf filter does the same thing for high frequencies.
1165 
1166 
1167 
1168 
1169 8. Waveform and Noise Generation
1170 ================================
1171 
1172 8.1. Waveforms
1173 --------------
1174 miniaudio supports generation of sine, square, triangle and sawtooth waveforms. This is achieved with the `ma_waveform` API. Example:
1175 
1176  ```c
1177  ma_waveform_config config = ma_waveform_config_init(
1178  FORMAT,
1179  CHANNELS,
1180  SAMPLE_RATE,
1181  ma_waveform_type_sine,
1182  amplitude,
1183  frequency);
1184 
1185  ma_waveform waveform;
1186  ma_result result = ma_waveform_init(&config, &waveform);
1187  if (result != MA_SUCCESS) {
1188  // Error.
1189  }
1190 
1191  ...
1192 
1193  ma_waveform_read_pcm_frames(&waveform, pOutput, frameCount);
1194  ```
1195 
1196 The amplitude, frequency, type, and sample rate can be changed dynamically with `ma_waveform_set_amplitude()`, `ma_waveform_set_frequency()`,
1197 `ma_waveform_set_type()`, and `ma_waveform_set_sample_rate()` respectively.
1198 
1199 You can invert the waveform by setting the amplitude to a negative value. You can use this to control whether or not a sawtooth has a positive or negative
1200 ramp, for example.
1201 
1202 Below are the supported waveform types:
1203 
1204  +---------------------------+
1205  | Enum Name |
1206  +---------------------------+
1207  | ma_waveform_type_sine |
1208  | ma_waveform_type_square |
1209  | ma_waveform_type_triangle |
1210  | ma_waveform_type_sawtooth |
1211  +---------------------------+
1212 
1213 
1214 
1215 8.2. Noise
1216 ----------
1217 miniaudio supports generation of white, pink and Brownian noise via the `ma_noise` API. Example:
1218 
1219  ```c
1220  ma_noise_config config = ma_noise_config_init(
1221  FORMAT,
1222  CHANNELS,
1223  ma_noise_type_white,
1224  SEED,
1225  amplitude);
1226 
1227  ma_noise noise;
1228  ma_result result = ma_noise_init(&config, &noise);
1229  if (result != MA_SUCCESS) {
1230  // Error.
1231  }
1232 
1233  ...
1234 
1235  ma_noise_read_pcm_frames(&noise, pOutput, frameCount);
1236  ```
1237 
1238 The noise API uses simple LCG random number generation. It supports a custom seed which is useful for things like automated testing requiring reproducibility.
1239 Setting the seed to zero will default to `MA_DEFAULT_LCG_SEED`.
1240 
1241 The amplitude, seed, and type can be changed dynamically with `ma_noise_set_amplitude()`, `ma_noise_set_seed()`, and `ma_noise_set_type()` respectively.
1242 
1243 By default, the noise API will use different values for different channels. So, for example, the left side in a stereo stream will be different to the right
1244 side. To instead have each channel use the same random value, set the `duplicateChannels` member of the noise config to true, like so:
1245 
1246  ```c
1247  config.duplicateChannels = MA_TRUE;
1248  ```
1249 
1250 Below are the supported noise types.
1251 
1252  +------------------------+
1253  | Enum Name |
1254  +------------------------+
1255  | ma_noise_type_white |
1256  | ma_noise_type_pink |
1257  | ma_noise_type_brownian |
1258  +------------------------+
1259 
1260 
1261 
1262 9. Audio Buffers
1263 ================
1264 miniaudio supports reading from a buffer of raw audio data via the `ma_audio_buffer` API. This can read from memory that's managed by the application, but
1265 can also handle the memory management for you internally. Memory management is flexible and should support most use cases.
1266 
1267 Audio buffers are initialised using the standard configuration system used everywhere in miniaudio:
1268 
1269  ```c
1270  ma_audio_buffer_config config = ma_audio_buffer_config_init(
1271  format,
1272  channels,
1273  sizeInFrames,
1274  pExistingData,
1275  &allocationCallbacks);
1276 
1277  ma_audio_buffer buffer;
1278  result = ma_audio_buffer_init(&config, &buffer);
1279  if (result != MA_SUCCESS) {
1280  // Error.
1281  }
1282 
1283  ...
1284 
1285  ma_audio_buffer_uninit(&buffer);
1286  ```
1287 
1288 In the example above, the memory pointed to by `pExistingData` will *not* be copied and is how an application can do self-managed memory allocation. If you
1289 would rather make a copy of the data, use `ma_audio_buffer_init_copy()`. To uninitialize the buffer, use `ma_audio_buffer_uninit()`.
1290 
1291 Sometimes it can be convenient to allocate the memory for the `ma_audio_buffer` structure and the raw audio data in a contiguous block of memory. That is,
1292 the raw audio data will be located immediately after the `ma_audio_buffer` structure. To do this, use `ma_audio_buffer_alloc_and_init()`:
1293 
1294  ```c
1295  ma_audio_buffer_config config = ma_audio_buffer_config_init(
1296  format,
1297  channels,
1298  sizeInFrames,
1299  pExistingData,
1300  &allocationCallbacks);
1301 
1302  ma_audio_buffer* pBuffer
1303  result = ma_audio_buffer_alloc_and_init(&config, &pBuffer);
1304  if (result != MA_SUCCESS) {
1305  // Error
1306  }
1307 
1308  ...
1309 
1310  ma_audio_buffer_uninit_and_free(&buffer);
1311  ```
1312 
1313 If you initialize the buffer with `ma_audio_buffer_alloc_and_init()` you should uninitialize it with `ma_audio_buffer_uninit_and_free()`. In the example above,
1314 the memory pointed to by `pExistingData` will be copied into the buffer, which is contrary to the behavior of `ma_audio_buffer_init()`.
1315 
1316 An audio buffer has a playback cursor just like a decoder. As you read frames from the buffer, the cursor moves forward. The last parameter (`loop`) can be
1317 used to determine if the buffer should loop. The return value is the number of frames actually read. If this is less than the number of frames requested it
1318 means the end has been reached. This should never happen if the `loop` parameter is set to true. If you want to manually loop back to the start, you can do so
1319 with with `ma_audio_buffer_seek_to_pcm_frame(pAudioBuffer, 0)`. Below is an example for reading data from an audio buffer.
1320 
1321  ```c
1322  ma_uint64 framesRead = ma_audio_buffer_read_pcm_frames(pAudioBuffer, pFramesOut, desiredFrameCount, isLooping);
1323  if (framesRead < desiredFrameCount) {
1324  // If not looping, this means the end has been reached. This should never happen in looping mode with valid input.
1325  }
1326  ```
1327 
1328 Sometimes you may want to avoid the cost of data movement between the internal buffer and the output buffer. Instead you can use memory mapping to retrieve a
1329 pointer to a segment of data:
1330 
1331  ```c
1332  void* pMappedFrames;
1333  ma_uint64 frameCount = frameCountToTryMapping;
1334  ma_result result = ma_audio_buffer_map(pAudioBuffer, &pMappedFrames, &frameCount);
1335  if (result == MA_SUCCESS) {
1336  // Map was successful. The value in frameCount will be how many frames were _actually_ mapped, which may be
1337  // less due to the end of the buffer being reached.
1338  ma_copy_pcm_frames(pFramesOut, pMappedFrames, frameCount, pAudioBuffer->format, pAudioBuffer->channels);
1339 
1340  // You must unmap the buffer.
1341  ma_audio_buffer_unmap(pAudioBuffer, frameCount);
1342  }
1343  ```
1344 
1345 When you use memory mapping, the read cursor is increment by the frame count passed in to `ma_audio_buffer_unmap()`. If you decide not to process every frame
1346 you can pass in a value smaller than the value returned by `ma_audio_buffer_map()`. The disadvantage to using memory mapping is that it does not handle looping
1347 for you. You can determine if the buffer is at the end for the purpose of looping with `ma_audio_buffer_at_end()` or by inspecting the return value of
1348 `ma_audio_buffer_unmap()` and checking if it equals `MA_AT_END`. You should not treat `MA_AT_END` as an error when returned by `ma_audio_buffer_unmap()`.
1349 
1350 
1351 
1352 10. Ring Buffers
1353 ================
1354 miniaudio supports lock free (single producer, single consumer) ring buffers which are exposed via the `ma_rb` and `ma_pcm_rb` APIs. The `ma_rb` API operates
1355 on bytes, whereas the `ma_pcm_rb` operates on PCM frames. They are otherwise identical as `ma_pcm_rb` is just a wrapper around `ma_rb`.
1356 
1357 Unlike most other APIs in miniaudio, ring buffers support both interleaved and deinterleaved streams. The caller can also allocate their own backing memory for
1358 the ring buffer to use internally for added flexibility. Otherwise the ring buffer will manage it's internal memory for you.
1359 
1360 The examples below use the PCM frame variant of the ring buffer since that's most likely the one you will want to use. To initialize a ring buffer, do
1361 something like the following:
1362 
1363  ```c
1364  ma_pcm_rb rb;
1365  ma_result result = ma_pcm_rb_init(FORMAT, CHANNELS, BUFFER_SIZE_IN_FRAMES, NULL, NULL, &rb);
1366  if (result != MA_SUCCESS) {
1367  // Error
1368  }
1369  ```
1370 
1371 The `ma_pcm_rb_init()` function takes the sample format and channel count as parameters because it's the PCM varient of the ring buffer API. For the regular
1372 ring buffer that operates on bytes you would call `ma_rb_init()` which leaves these out and just takes the size of the buffer in bytes instead of frames. The
1373 fourth parameter is an optional pre-allocated buffer and the fifth parameter is a pointer to a `ma_allocation_callbacks` structure for custom memory allocation
1374 routines. Passing in `NULL` for this results in `MA_MALLOC()` and `MA_FREE()` being used.
1375 
1376 Use `ma_pcm_rb_init_ex()` if you need a deinterleaved buffer. The data for each sub-buffer is offset from each other based on the stride. To manage your
1377 sub-buffers you can use `ma_pcm_rb_get_subbuffer_stride()`, `ma_pcm_rb_get_subbuffer_offset()` and `ma_pcm_rb_get_subbuffer_ptr()`.
1378 
1379 Use `ma_pcm_rb_acquire_read()` and `ma_pcm_rb_acquire_write()` to retrieve a pointer to a section of the ring buffer. You specify the number of frames you
1380 need, and on output it will set to what was actually acquired. If the read or write pointer is positioned such that the number of frames requested will require
1381 a loop, it will be clamped to the end of the buffer. Therefore, the number of frames you're given may be less than the number you requested.
1382 
1383 After calling `ma_pcm_rb_acquire_read()` or `ma_pcm_rb_acquire_write()`, you do your work on the buffer and then "commit" it with `ma_pcm_rb_commit_read()` or
1384 `ma_pcm_rb_commit_write()`. This is where the read/write pointers are updated. When you commit you need to pass in the buffer that was returned by the earlier
1385 call to `ma_pcm_rb_acquire_read()` or `ma_pcm_rb_acquire_write()` and is only used for validation. The number of frames passed to `ma_pcm_rb_commit_read()` and
1386 `ma_pcm_rb_commit_write()` is what's used to increment the pointers, and can be less that what was originally requested.
1387 
1388 If you want to correct for drift between the write pointer and the read pointer you can use a combination of `ma_pcm_rb_pointer_distance()`,
1389 `ma_pcm_rb_seek_read()` and `ma_pcm_rb_seek_write()`. Note that you can only move the pointers forward, and you should only move the read pointer forward via
1390 the consumer thread, and the write pointer forward by the producer thread. If there is too much space between the pointers, move the read pointer forward. If
1391 there is too little space between the pointers, move the write pointer forward.
1392 
1393 You can use a ring buffer at the byte level instead of the PCM frame level by using the `ma_rb` API. This is exactly the same, only you will use the `ma_rb`
1394 functions instead of `ma_pcm_rb` and instead of frame counts you will pass around byte counts.
1395 
1396 The maximum size of the buffer in bytes is `0x7FFFFFFF-(MA_SIMD_ALIGNMENT-1)` due to the most significant bit being used to encode a loop flag and the internally
1397 managed buffers always being aligned to MA_SIMD_ALIGNMENT.
1398 
1399 Note that the ring buffer is only thread safe when used by a single consumer thread and single producer thread.
1400 
1401 
1402 
1403 11. Backends
1404 ============
1405 The following backends are supported by miniaudio.
1406 
1407  +-------------+-----------------------+--------------------------------------------------------+
1408  | Name | Enum Name | Supported Operating Systems |
1409  +-------------+-----------------------+--------------------------------------------------------+
1410  | WASAPI | ma_backend_wasapi | Windows Vista+ |
1411  | DirectSound | ma_backend_dsound | Windows XP+ |
1412  | WinMM | ma_backend_winmm | Windows XP+ (may work on older versions, but untested) |
1413  | Core Audio | ma_backend_coreaudio | macOS, iOS |
1414  | ALSA | ma_backend_alsa | Linux |
1415  | PulseAudio | ma_backend_pulseaudio | Cross Platform (disabled on Windows, BSD and Android) |
1416  | JACK | ma_backend_jack | Cross Platform (disabled on BSD and Android) |
1417  | sndio | ma_backend_sndio | OpenBSD |
1418  | audio(4) | ma_backend_audio4 | NetBSD, OpenBSD |
1419  | OSS | ma_backend_oss | FreeBSD |
1420  | AAudio | ma_backend_aaudio | Android 8+ |
1421  | OpenSL ES | ma_backend_opensl | Android (API level 16+) |
1422  | Web Audio | ma_backend_webaudio | Web (via Emscripten) |
1423  | Custom | ma_backend_custom | Cross Platform |
1424  | Null | ma_backend_null | Cross Platform (not used on Web) |
1425  +-------------+-----------------------+--------------------------------------------------------+
1426 
1427 Some backends have some nuance details you may want to be aware of.
1428 
1429 11.1. WASAPI
1430 ------------
1431 - Low-latency shared mode will be disabled when using an application-defined sample rate which is different to the device's native sample rate. To work around
1432  this, set `wasapi.noAutoConvertSRC` to true in the device config. This is due to IAudioClient3_InitializeSharedAudioStream() failing when the
1433  `AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM` flag is specified. Setting wasapi.noAutoConvertSRC will result in miniaudio's internal resampler being used instead
1434  which will in turn enable the use of low-latency shared mode.
1435 
1436 11.2. PulseAudio
1437 ----------------
1438 - If you experience bad glitching/noise on Arch Linux, consider this fix from the Arch wiki:
1439  https://wiki.archlinux.org/index.php/PulseAudio/Troubleshooting#Glitches,_skips_or_crackling. Alternatively, consider using a different backend such as ALSA.
1440 
1441 11.3. Android
1442 -------------
1443 - To capture audio on Android, remember to add the RECORD_AUDIO permission to your manifest: `<uses-permission android:name="android.permission.RECORD_AUDIO" />`
1444 - With OpenSL|ES, only a single ma_context can be active at any given time. This is due to a limitation with OpenSL|ES.
1445 - With AAudio, only default devices are enumerated. This is due to AAudio not having an enumeration API (devices are enumerated through Java). You can however
1446  perform your own device enumeration through Java and then set the ID in the ma_device_id structure (ma_device_id.aaudio) and pass it to ma_device_init().
1447 - The backend API will perform resampling where possible. The reason for this as opposed to using miniaudio's built-in resampler is to take advantage of any
1448  potential device-specific optimizations the driver may implement.
1449 
1450 11.4. UWP
1451 ---------
1452 - UWP only supports default playback and capture devices.
1453 - UWP requires the Microphone capability to be enabled in the application's manifest (Package.appxmanifest):
1454 
1455  ```
1456  <Package ...>
1457  ...
1458  <Capabilities>
1459  <DeviceCapability Name="microphone" />
1460  </Capabilities>
1461  </Package>
1462  ```
1463 
1464 11.5. Web Audio / Emscripten
1465 ----------------------------
1466 - You cannot use `-std=c*` compiler flags, nor `-ansi`. This only applies to the Emscripten build.
1467 - The first time a context is initialized it will create a global object called "miniaudio" whose primary purpose is to act as a factory for device objects.
1468 - Currently the Web Audio backend uses ScriptProcessorNode's, but this may need to change later as they've been deprecated.
1469 - Google has implemented a policy in their browsers that prevent automatic media output without first receiving some kind of user input. The following web page
1470  has additional details: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes. Starting the device may fail if you try to start playback
1471  without first handling some kind of user input.
1472 
1473 
1474 
1475 12. Miscellaneous Notes
1476 =======================
1477 - Automatic stream routing is enabled on a per-backend basis. Support is explicitly enabled for WASAPI and Core Audio, however other backends such as
1478  PulseAudio may naturally support it, though not all have been tested.
1479 - The contents of the output buffer passed into the data callback will always be pre-initialized to silence unless the `noPreZeroedOutputBuffer` config variable
1480  in `ma_device_config` is set to true, in which case it'll be undefined which will require you to write something to the entire buffer.
1481 - By default miniaudio will automatically clip samples. This only applies when the playback sample format is configured as `ma_format_f32`. If you are doing
1482  clipping yourself, you can disable this overhead by setting `noClip` to true in the device config.
1483 - The sndio backend is currently only enabled on OpenBSD builds.
1484 - The audio(4) backend is supported on OpenBSD, but you may need to disable sndiod before you can use it.
1485 - Note that GCC and Clang requires `-msse2`, `-mavx2`, etc. for SIMD optimizations.
1486 - When compiling with VC6 and earlier, decoding is restricted to files less than 2GB in size. This is due to 64-bit file APIs not being available.
1487 */
1488 
1489 #ifndef miniaudio_h
1490 #define miniaudio_h
1491 
1492 #ifdef __cplusplus
1493 extern "C" {
1494 #endif
1495 
1496 #define MA_STRINGIFY(x) #x
1497 #define MA_XSTRINGIFY(x) MA_STRINGIFY(x)
1498 
1499 #define MA_VERSION_MAJOR 0
1500 #define MA_VERSION_MINOR 10
1501 #define MA_VERSION_REVISION 41
1502 #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
1503 
1504 #if defined(_MSC_VER) && !defined(__clang__)
1505  #pragma warning(push)
1506  #pragma warning(disable:4201) /* nonstandard extension used: nameless struct/union */
1507  #pragma warning(disable:4214) /* nonstandard extension used: bit field types other than int */
1508  #pragma warning(disable:4324) /* structure was padded due to alignment specifier */
1509 #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
1510  #pragma GCC diagnostic push
1511  #pragma GCC diagnostic ignored "-Wpedantic" /* For ISO C99 doesn't support unnamed structs/unions [-Wpedantic] */
1512  #if defined(__clang__)
1513  #pragma GCC diagnostic ignored "-Wc11-extensions" /* anonymous unions are a C11 extension */
1514  #endif
1515 #endif
1516 
1517 /* Platform/backend detection. */
1518 #ifdef _WIN32
1519  #define MA_WIN32
1520  #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
1521  #define MA_WIN32_UWP
1522  #else
1523  #define MA_WIN32_DESKTOP
1524  #endif
1525 #else
1526  #define MA_POSIX
1527  #include <pthread.h> /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */
1528 
1529  #ifdef __unix__
1530  #define MA_UNIX
1531  #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
1532  #define MA_BSD
1533  #endif
1534  #endif
1535  #ifdef __linux__
1536  #define MA_LINUX
1537  #endif
1538  #ifdef __APPLE__
1539  #define MA_APPLE
1540  #endif
1541  #ifdef __ANDROID__
1542  #define MA_ANDROID
1543  #endif
1544  #ifdef __EMSCRIPTEN__
1545  #define MA_EMSCRIPTEN
1546  #endif
1547 #endif
1548 
1549 #include <stddef.h> /* For size_t. */
1550 
1551 /* Sized types. */
1552 typedef signed char ma_int8;
1553 typedef unsigned char ma_uint8;
1554 typedef signed short ma_int16;
1555 typedef unsigned short ma_uint16;
1556 typedef signed int ma_int32;
1557 typedef unsigned int ma_uint32;
1558 #if defined(_MSC_VER)
1559  typedef signed __int64 ma_int64;
1560  typedef unsigned __int64 ma_uint64;
1561 #else
1562  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
1563  #pragma GCC diagnostic push
1564  #pragma GCC diagnostic ignored "-Wlong-long"
1565  #if defined(__clang__)
1566  #pragma GCC diagnostic ignored "-Wc++11-long-long"
1567  #endif
1568  #endif
1569  typedef signed long long ma_int64;
1570  typedef unsigned long long ma_uint64;
1571  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
1572  #pragma GCC diagnostic pop
1573  #endif
1574 #endif
1575 #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__)
1576  typedef ma_uint64 ma_uintptr;
1577 #else
1579 #endif
1580 
1583 #define MA_TRUE 1
1584 #define MA_FALSE 0
1585 
1586 typedef void* ma_handle;
1587 typedef void* ma_ptr;
1588 typedef void (* ma_proc)(void);
1589 
1590 #if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
1591 typedef ma_uint16 wchar_t;
1592 #endif
1593 
1594 /* Define NULL for some compilers. */
1595 #ifndef NULL
1596 #define NULL 0
1597 #endif
1598 
1599 #if defined(SIZE_MAX)
1600  #define MA_SIZE_MAX SIZE_MAX
1601 #else
1602  #define MA_SIZE_MAX 0xFFFFFFFF /* When SIZE_MAX is not defined by the standard library just default to the maximum 32-bit unsigned integer. */
1603 #endif
1604 
1605 
1606 #ifdef _MSC_VER
1607  #define MA_INLINE __forceinline
1608 #elif defined(__GNUC__)
1609  /*
1610  I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
1611  the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
1612  case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
1613  command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
1614  I am using "__inline__" only when we're compiling in strict ANSI mode.
1615  */
1616  #if defined(__STRICT_ANSI__)
1617  #define MA_INLINE __inline__ __attribute__((always_inline))
1618  #else
1619  #define MA_INLINE inline __attribute__((always_inline))
1620  #endif
1621 #elif defined(__WATCOMC__)
1622  #define MA_INLINE __inline
1623 #else
1624  #define MA_INLINE
1625 #endif
1626 
1627 #if !defined(MA_API)
1628  #if defined(MA_DLL)
1629  #if defined(_WIN32)
1630  #define MA_DLL_IMPORT __declspec(dllimport)
1631  #define MA_DLL_EXPORT __declspec(dllexport)
1632  #define MA_DLL_PRIVATE static
1633  #else
1634  #if defined(__GNUC__) && __GNUC__ >= 4
1635  #define MA_DLL_IMPORT __attribute__((visibility("default")))
1636  #define MA_DLL_EXPORT __attribute__((visibility("default")))
1637  #define MA_DLL_PRIVATE __attribute__((visibility("hidden")))
1638  #else
1639  #define MA_DLL_IMPORT
1640  #define MA_DLL_EXPORT
1641  #define MA_DLL_PRIVATE static
1642  #endif
1643  #endif
1644 
1645  #if defined(MINIAUDIO_IMPLEMENTATION) || defined(MA_IMPLEMENTATION)
1646  #define MA_API MA_DLL_EXPORT
1647  #else
1648  #define MA_API MA_DLL_IMPORT
1649  #endif
1650  #define MA_PRIVATE MA_DLL_PRIVATE
1651  #else
1652  #define MA_API extern
1653  #define MA_PRIVATE static
1654  #endif
1655 #endif
1656 
1657 /* SIMD alignment in bytes. Currently set to 64 bytes in preparation for future AVX-512 optimizations. */
1658 #define MA_SIMD_ALIGNMENT 64
1659 
1660 
1661 /*
1662 Logging Levels
1663 ==============
1664 Log levels are only used to give logging callbacks some context as to the severity of a log message
1665 so they can do filtering. All log levels will be posted to registered logging callbacks, except for
1666 MA_LOG_LEVEL_DEBUG which will only get processed if MA_DEBUG_OUTPUT is enabled.
1667 
1668 MA_LOG_LEVEL_DEBUG
1669  Used for debugging. These log messages are only posted when `MA_DEBUG_OUTPUT` is enabled.
1670 
1671 MA_LOG_LEVEL_INFO
1672  Informational logging. Useful for debugging. This will also enable warning and error logs. This
1673  will never be called from within the data callback.
1674 
1675 MA_LOG_LEVEL_WARNING
1676  Warnings. You should enable this in you development builds and action them when encounted. This
1677  will also enable error logs. These logs usually indicate a potential problem or
1678  misconfiguration, but still allow you to keep running. This will never be called from within
1679  the data callback.
1680 
1681 MA_LOG_LEVEL_ERROR
1682  Error logging. This will be fired when an operation fails and is subsequently aborted. This can
1683  be fired from within the data callback, in which case the device will be stopped. You should
1684  always have this log level enabled.
1685 */
1686 #define MA_LOG_LEVEL_DEBUG 4
1687 #define MA_LOG_LEVEL_INFO 3
1688 #define MA_LOG_LEVEL_WARNING 2
1689 #define MA_LOG_LEVEL_ERROR 1
1690 
1691 /* Deprecated. */
1692 #define MA_LOG_LEVEL_VERBOSE MA_LOG_LEVEL_DEBUG
1693 
1694 /* Deprecated. */
1695 #ifndef MA_LOG_LEVEL
1696 #define MA_LOG_LEVEL MA_LOG_LEVEL_ERROR
1697 #endif
1698 
1699 /*
1700 An annotation for variables which must be used atomically. This doesn't actually do anything - it's
1701 just used as a way for humans to identify variables that should be used atomically.
1702 */
1703 #define MA_ATOMIC
1704 
1705 typedef struct ma_context ma_context;
1706 typedef struct ma_device ma_device;
1707 
1709 #define MA_CHANNEL_NONE 0
1710 #define MA_CHANNEL_MONO 1
1711 #define MA_CHANNEL_FRONT_LEFT 2
1712 #define MA_CHANNEL_FRONT_RIGHT 3
1713 #define MA_CHANNEL_FRONT_CENTER 4
1714 #define MA_CHANNEL_LFE 5
1715 #define MA_CHANNEL_BACK_LEFT 6
1716 #define MA_CHANNEL_BACK_RIGHT 7
1717 #define MA_CHANNEL_FRONT_LEFT_CENTER 8
1718 #define MA_CHANNEL_FRONT_RIGHT_CENTER 9
1719 #define MA_CHANNEL_BACK_CENTER 10
1720 #define MA_CHANNEL_SIDE_LEFT 11
1721 #define MA_CHANNEL_SIDE_RIGHT 12
1722 #define MA_CHANNEL_TOP_CENTER 13
1723 #define MA_CHANNEL_TOP_FRONT_LEFT 14
1724 #define MA_CHANNEL_TOP_FRONT_CENTER 15
1725 #define MA_CHANNEL_TOP_FRONT_RIGHT 16
1726 #define MA_CHANNEL_TOP_BACK_LEFT 17
1727 #define MA_CHANNEL_TOP_BACK_CENTER 18
1728 #define MA_CHANNEL_TOP_BACK_RIGHT 19
1729 #define MA_CHANNEL_AUX_0 20
1730 #define MA_CHANNEL_AUX_1 21
1731 #define MA_CHANNEL_AUX_2 22
1732 #define MA_CHANNEL_AUX_3 23
1733 #define MA_CHANNEL_AUX_4 24
1734 #define MA_CHANNEL_AUX_5 25
1735 #define MA_CHANNEL_AUX_6 26
1736 #define MA_CHANNEL_AUX_7 27
1737 #define MA_CHANNEL_AUX_8 28
1738 #define MA_CHANNEL_AUX_9 29
1739 #define MA_CHANNEL_AUX_10 30
1740 #define MA_CHANNEL_AUX_11 31
1741 #define MA_CHANNEL_AUX_12 32
1742 #define MA_CHANNEL_AUX_13 33
1743 #define MA_CHANNEL_AUX_14 34
1744 #define MA_CHANNEL_AUX_15 35
1745 #define MA_CHANNEL_AUX_16 36
1746 #define MA_CHANNEL_AUX_17 37
1747 #define MA_CHANNEL_AUX_18 38
1748 #define MA_CHANNEL_AUX_19 39
1749 #define MA_CHANNEL_AUX_20 40
1750 #define MA_CHANNEL_AUX_21 41
1751 #define MA_CHANNEL_AUX_22 42
1752 #define MA_CHANNEL_AUX_23 43
1753 #define MA_CHANNEL_AUX_24 44
1754 #define MA_CHANNEL_AUX_25 45
1755 #define MA_CHANNEL_AUX_26 46
1756 #define MA_CHANNEL_AUX_27 47
1757 #define MA_CHANNEL_AUX_28 48
1758 #define MA_CHANNEL_AUX_29 49
1759 #define MA_CHANNEL_AUX_30 50
1760 #define MA_CHANNEL_AUX_31 51
1761 #define MA_CHANNEL_LEFT MA_CHANNEL_FRONT_LEFT
1762 #define MA_CHANNEL_RIGHT MA_CHANNEL_FRONT_RIGHT
1763 #define MA_CHANNEL_POSITION_COUNT (MA_CHANNEL_AUX_31 + 1)
1764 
1765 
1766 typedef int ma_result;
1767 #define MA_SUCCESS 0
1768 #define MA_ERROR -1 /* A generic error. */
1769 #define MA_INVALID_ARGS -2
1770 #define MA_INVALID_OPERATION -3
1771 #define MA_OUT_OF_MEMORY -4
1772 #define MA_OUT_OF_RANGE -5
1773 #define MA_ACCESS_DENIED -6
1774 #define MA_DOES_NOT_EXIST -7
1775 #define MA_ALREADY_EXISTS -8
1776 #define MA_TOO_MANY_OPEN_FILES -9
1777 #define MA_INVALID_FILE -10
1778 #define MA_TOO_BIG -11
1779 #define MA_PATH_TOO_LONG -12
1780 #define MA_NAME_TOO_LONG -13
1781 #define MA_NOT_DIRECTORY -14
1782 #define MA_IS_DIRECTORY -15
1783 #define MA_DIRECTORY_NOT_EMPTY -16
1784 #define MA_AT_END -17
1785 #define MA_NO_SPACE -18
1786 #define MA_BUSY -19
1787 #define MA_IO_ERROR -20
1788 #define MA_INTERRUPT -21
1789 #define MA_UNAVAILABLE -22
1790 #define MA_ALREADY_IN_USE -23
1791 #define MA_BAD_ADDRESS -24
1792 #define MA_BAD_SEEK -25
1793 #define MA_BAD_PIPE -26
1794 #define MA_DEADLOCK -27
1795 #define MA_TOO_MANY_LINKS -28
1796 #define MA_NOT_IMPLEMENTED -29
1797 #define MA_NO_MESSAGE -30
1798 #define MA_BAD_MESSAGE -31
1799 #define MA_NO_DATA_AVAILABLE -32
1800 #define MA_INVALID_DATA -33
1801 #define MA_TIMEOUT -34
1802 #define MA_NO_NETWORK -35
1803 #define MA_NOT_UNIQUE -36
1804 #define MA_NOT_SOCKET -37
1805 #define MA_NO_ADDRESS -38
1806 #define MA_BAD_PROTOCOL -39
1807 #define MA_PROTOCOL_UNAVAILABLE -40
1808 #define MA_PROTOCOL_NOT_SUPPORTED -41
1809 #define MA_PROTOCOL_FAMILY_NOT_SUPPORTED -42
1810 #define MA_ADDRESS_FAMILY_NOT_SUPPORTED -43
1811 #define MA_SOCKET_NOT_SUPPORTED -44
1812 #define MA_CONNECTION_RESET -45
1813 #define MA_ALREADY_CONNECTED -46
1814 #define MA_NOT_CONNECTED -47
1815 #define MA_CONNECTION_REFUSED -48
1816 #define MA_NO_HOST -49
1817 #define MA_IN_PROGRESS -50
1818 #define MA_CANCELLED -51
1819 #define MA_MEMORY_ALREADY_MAPPED -52
1820 
1821 /* General miniaudio-specific errors. */
1822 #define MA_FORMAT_NOT_SUPPORTED -100
1823 #define MA_DEVICE_TYPE_NOT_SUPPORTED -101
1824 #define MA_SHARE_MODE_NOT_SUPPORTED -102
1825 #define MA_NO_BACKEND -103
1826 #define MA_NO_DEVICE -104
1827 #define MA_API_NOT_FOUND -105
1828 #define MA_INVALID_DEVICE_CONFIG -106
1829 #define MA_LOOP -107
1830 
1831 /* State errors. */
1832 #define MA_DEVICE_NOT_INITIALIZED -200
1833 #define MA_DEVICE_ALREADY_INITIALIZED -201
1834 #define MA_DEVICE_NOT_STARTED -202
1835 #define MA_DEVICE_NOT_STOPPED -203
1836 
1837 /* Operation errors. */
1838 #define MA_FAILED_TO_INIT_BACKEND -300
1839 #define MA_FAILED_TO_OPEN_BACKEND_DEVICE -301
1840 #define MA_FAILED_TO_START_BACKEND_DEVICE -302
1841 #define MA_FAILED_TO_STOP_BACKEND_DEVICE -303
1842 
1843 
1844 #define MA_MIN_CHANNELS 1
1845 #ifndef MA_MAX_CHANNELS
1846 #define MA_MAX_CHANNELS 32
1847 #endif
1848 
1849 
1850 #ifndef MA_MAX_FILTER_ORDER
1851 #define MA_MAX_FILTER_ORDER 8
1852 #endif
1853 
1854 typedef enum
1855 {
1858 
1859 typedef enum
1860 {
1864 
1865 typedef enum
1866 {
1870 } ma_dither_mode;
1871 
1872 typedef enum
1873 {
1874  /*
1875  I like to keep these explicitly defined because they're used as a key into a lookup table. When items are
1876  added to this, make sure there are no gaps and that they're added to the lookup table in ma_get_bytes_per_sample().
1877  */
1878  ma_format_unknown = 0, /* Mainly used for indicating an error, but also used as the default for the output format for decoders. */
1880  ma_format_s16 = 2, /* Seems to be the most widely supported format. */
1881  ma_format_s24 = 3, /* Tightly packed. 3 bytes per sample. */
1885 } ma_format;
1886 
1887 typedef enum
1888 {
1889  /* Standard rates need to be in priority order. */
1890  ma_standard_sample_rate_48000 = 48000, /* Most common */
1892 
1893  ma_standard_sample_rate_32000 = 32000, /* Lows */
1896 
1897  ma_standard_sample_rate_88200 = 88200, /* Highs */
1901 
1902  ma_standard_sample_rate_16000 = 16000, /* Extreme lows */
1905 
1906  ma_standard_sample_rate_352800 = 352800, /* Extreme highs */
1908 
1911  ma_standard_sample_rate_count = 14 /* Need to maintain the count manually. Make sure this is updated if items are added to enum. */
1913 
1914 /* These are deprecated. Use ma_standard_sample_rate_min and ma_standard_sample_rate_max. */
1915 #define MA_MIN_SAMPLE_RATE (ma_uint32)ma_standard_sample_rate_min
1916 #define MA_MAX_SAMPLE_RATE (ma_uint32)ma_standard_sample_rate_max
1917 
1918 
1919 typedef enum
1920 {
1921  ma_channel_mix_mode_rectangular = 0, /* Simple averaging based on the plane(s) the channel is sitting on. */
1922  ma_channel_mix_mode_simple, /* Drop excess channels; zeroed out extra channels. */
1923  ma_channel_mix_mode_custom_weights, /* Use custom weights specified in ma_channel_router_config. */
1927 
1928 typedef enum
1929 {
1932  ma_standard_channel_map_rfc3551, /* Based off AIFF. */
1935  ma_standard_channel_map_sound4, /* FreeBSD's sound(4). */
1936  ma_standard_channel_map_sndio, /* www.sndio.org/tips.html */
1937  ma_standard_channel_map_webaudio = ma_standard_channel_map_flac, /* https://webaudio.github.io/web-audio-api/#ChannelOrdering. Only 1, 2, 4 and 6 channels are defined, but can fill in the gaps with logical assumptions. */
1940 
1941 typedef enum
1942 {
1946 
1947 
1948 typedef struct
1949 {
1950  void* pUserData;
1951  void* (* onMalloc)(size_t sz, void* pUserData);
1952  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
1953  void (* onFree)(void* p, void* pUserData);
1955 
1956 typedef struct
1957 {
1958  ma_int32 state;
1959 } ma_lcg;
1960 
1961 
1962 #ifndef MA_NO_THREADING
1963 /* Thread priorities should be ordered such that the default priority of the worker thread is 0. */
1964 typedef enum
1965 {
1975 
1976 /* Spinlocks are 32-bit for compatibility reasons. */
1978 
1979 #if defined(MA_WIN32)
1980 typedef ma_handle ma_thread;
1981 #endif
1982 #if defined(MA_POSIX)
1983 typedef pthread_t ma_thread;
1984 #endif
1985 
1986 #if defined(MA_WIN32)
1987 typedef ma_handle ma_mutex;
1988 #endif
1989 #if defined(MA_POSIX)
1990 typedef pthread_mutex_t ma_mutex;
1991 #endif
1992 
1993 #if defined(MA_WIN32)
1994 typedef ma_handle ma_event;
1995 #endif
1996 #if defined(MA_POSIX)
1997 typedef struct
1998 {
1999  ma_uint32 value;
2000  pthread_mutex_t lock;
2001  pthread_cond_t cond;
2002 } ma_event;
2003 #endif /* MA_POSIX */
2004 
2005 #if defined(MA_WIN32)
2006 typedef ma_handle ma_semaphore;
2007 #endif
2008 #if defined(MA_POSIX)
2009 typedef struct
2010 {
2011  int value;
2012  pthread_mutex_t lock;
2013  pthread_cond_t cond;
2014 } ma_semaphore;
2015 #endif /* MA_POSIX */
2016 #else
2017 /* 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. */
2018 #ifndef MA_NO_DEVICE_IO
2019 #error "MA_NO_THREADING cannot be used without MA_NO_DEVICE_IO";
2020 #endif
2021 #endif /* MA_NO_THREADING */
2022 
2023 
2024 /*
2025 Retrieves the version of miniaudio as separated integers. Each component can be NULL if it's not required.
2026 */
2027 MA_API void ma_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* pRevision);
2028 
2029 /*
2030 Retrieves the version of miniaudio as a string which can be useful for logging purposes.
2031 */
2032 MA_API const char* ma_version_string(void);
2033 
2034 
2035 /**************************************************************************************************************************************************************
2036 
2037 Logging
2038 
2039 **************************************************************************************************************************************************************/
2040 #include <stdarg.h> /* For va_list. */
2041 
2042 #if defined(__has_attribute)
2043  #if __has_attribute(format)
2044  #define MA_ATTRIBUTE_FORMAT(fmt, va) __attribute__((format(printf, fmt, va)))
2045  #endif
2046 #endif
2047 #ifndef MA_ATTRIBUTE_FORMAT
2048 #define MA_ATTRIBUTE_FORMAT(fmt,va)
2049 #endif
2050 
2051 #ifndef MA_MAX_LOG_CALLBACKS
2052 #define MA_MAX_LOG_CALLBACKS 4
2053 #endif
2054 
2055 typedef void (* ma_log_callback_proc)(void* pUserData, ma_uint32 level, const char* pMessage);
2056 
2057 typedef struct
2058 {
2059  ma_log_callback_proc onLog;
2060  void* pUserData;
2061 } ma_log_callback;
2062 
2064 
2065 
2066 typedef struct
2067 {
2069  ma_uint32 callbackCount;
2070  ma_allocation_callbacks allocationCallbacks; /* Need to store these persistently because ma_log_postv() might need to allocate a buffer on the heap. */
2071 #ifndef MA_NO_THREADING
2072  ma_mutex lock; /* For thread safety just to make it easier and safer for the logging implementation. */
2073 #endif
2074 } ma_log;
2075 
2076 MA_API ma_result ma_log_init(const ma_allocation_callbacks* pAllocationCallbacks, ma_log* pLog);
2077 MA_API void ma_log_uninit(ma_log* pLog);
2080 MA_API ma_result ma_log_post(ma_log* pLog, ma_uint32 level, const char* pMessage);
2081 MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat, va_list args);
2082 MA_API ma_result ma_log_postf(ma_log* pLog, ma_uint32 level, const char* pFormat, ...) MA_ATTRIBUTE_FORMAT(3, 4);
2083 
2084 
2085 /**************************************************************************************************************************************************************
2086 
2087 Biquad Filtering
2088 
2089 **************************************************************************************************************************************************************/
2090 typedef union
2091 {
2092  float f32;
2093  ma_int32 s32;
2095 
2096 typedef struct
2097 {
2098  ma_format format;
2100  double b0;
2101  double b1;
2102  double b2;
2103  double a0;
2104  double a1;
2105  double a2;
2107 
2108 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);
2109 
2110 typedef struct
2111 {
2112  ma_format format;
2121 } ma_biquad;
2122 
2125 MA_API ma_result ma_biquad_process_pcm_frames(ma_biquad* pBQ, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2127 
2128 
2129 /**************************************************************************************************************************************************************
2130 
2131 Low-Pass Filtering
2132 
2133 **************************************************************************************************************************************************************/
2134 typedef struct
2135 {
2136  ma_format format;
2139  double cutoffFrequency;
2140  double q;
2142 
2145 
2146 typedef struct
2147 {
2148  ma_format format;
2152 } ma_lpf1;
2153 
2154 MA_API ma_result ma_lpf1_init(const ma_lpf1_config* pConfig, ma_lpf1* pLPF);
2155 MA_API ma_result ma_lpf1_reinit(const ma_lpf1_config* pConfig, ma_lpf1* pLPF);
2156 MA_API ma_result ma_lpf1_process_pcm_frames(ma_lpf1* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2158 
2159 typedef struct
2160 {
2161  ma_biquad bq; /* The second order low-pass filter is implemented as a biquad filter. */
2162 } ma_lpf2;
2163 
2164 MA_API ma_result ma_lpf2_init(const ma_lpf2_config* pConfig, ma_lpf2* pLPF);
2165 MA_API ma_result ma_lpf2_reinit(const ma_lpf2_config* pConfig, ma_lpf2* pLPF);
2166 MA_API ma_result ma_lpf2_process_pcm_frames(ma_lpf2* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2168 
2169 
2170 typedef struct
2171 {
2172  ma_format format;
2175  double cutoffFrequency;
2176  ma_uint32 order; /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
2177 } ma_lpf_config;
2178 
2180 
2181 typedef struct
2182 {
2183  ma_format format;
2186  ma_uint32 lpf1Count;
2187  ma_uint32 lpf2Count;
2188  ma_lpf1 lpf1[1];
2189  ma_lpf2 lpf2[MA_MAX_FILTER_ORDER/2];
2190 } ma_lpf;
2191 
2192 MA_API ma_result ma_lpf_init(const ma_lpf_config* pConfig, ma_lpf* pLPF);
2193 MA_API ma_result ma_lpf_reinit(const ma_lpf_config* pConfig, ma_lpf* pLPF);
2194 MA_API ma_result ma_lpf_process_pcm_frames(ma_lpf* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2196 
2197 
2198 /**************************************************************************************************************************************************************
2199 
2200 High-Pass Filtering
2201 
2202 **************************************************************************************************************************************************************/
2203 typedef struct
2204 {
2205  ma_format format;
2208  double cutoffFrequency;
2209  double q;
2211 
2214 
2215 typedef struct
2216 {
2217  ma_format format;
2221 } ma_hpf1;
2222 
2223 MA_API ma_result ma_hpf1_init(const ma_hpf1_config* pConfig, ma_hpf1* pHPF);
2224 MA_API ma_result ma_hpf1_reinit(const ma_hpf1_config* pConfig, ma_hpf1* pHPF);
2225 MA_API ma_result ma_hpf1_process_pcm_frames(ma_hpf1* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2227 
2228 typedef struct
2229 {
2230  ma_biquad bq; /* The second order high-pass filter is implemented as a biquad filter. */
2231 } ma_hpf2;
2232 
2233 MA_API ma_result ma_hpf2_init(const ma_hpf2_config* pConfig, ma_hpf2* pHPF);
2234 MA_API ma_result ma_hpf2_reinit(const ma_hpf2_config* pConfig, ma_hpf2* pHPF);
2235 MA_API ma_result ma_hpf2_process_pcm_frames(ma_hpf2* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2237 
2238 
2239 typedef struct
2240 {
2241  ma_format format;
2244  double cutoffFrequency;
2245  ma_uint32 order; /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
2246 } ma_hpf_config;
2247 
2249 
2250 typedef struct
2251 {
2252  ma_format format;
2255  ma_uint32 hpf1Count;
2256  ma_uint32 hpf2Count;
2257  ma_hpf1 hpf1[1];
2258  ma_hpf2 hpf2[MA_MAX_FILTER_ORDER/2];
2259 } ma_hpf;
2260 
2261 MA_API ma_result ma_hpf_init(const ma_hpf_config* pConfig, ma_hpf* pHPF);
2262 MA_API ma_result ma_hpf_reinit(const ma_hpf_config* pConfig, ma_hpf* pHPF);
2263 MA_API ma_result ma_hpf_process_pcm_frames(ma_hpf* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2265 
2266 
2267 /**************************************************************************************************************************************************************
2268 
2269 Band-Pass Filtering
2270 
2271 **************************************************************************************************************************************************************/
2272 typedef struct
2273 {
2274  ma_format format;
2277  double cutoffFrequency;
2278  double q;
2279 } ma_bpf2_config;
2280 
2282 
2283 typedef struct
2284 {
2285  ma_biquad bq; /* The second order band-pass filter is implemented as a biquad filter. */
2286 } ma_bpf2;
2287 
2288 MA_API ma_result ma_bpf2_init(const ma_bpf2_config* pConfig, ma_bpf2* pBPF);
2289 MA_API ma_result ma_bpf2_reinit(const ma_bpf2_config* pConfig, ma_bpf2* pBPF);
2290 MA_API ma_result ma_bpf2_process_pcm_frames(ma_bpf2* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2292 
2293 
2294 typedef struct
2295 {
2296  ma_format format;
2299  double cutoffFrequency;
2300  ma_uint32 order; /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
2301 } ma_bpf_config;
2302 
2304 
2305 typedef struct
2306 {
2307  ma_format format;
2309  ma_uint32 bpf2Count;
2310  ma_bpf2 bpf2[MA_MAX_FILTER_ORDER/2];
2311 } ma_bpf;
2312 
2313 MA_API ma_result ma_bpf_init(const ma_bpf_config* pConfig, ma_bpf* pBPF);
2314 MA_API ma_result ma_bpf_reinit(const ma_bpf_config* pConfig, ma_bpf* pBPF);
2315 MA_API ma_result ma_bpf_process_pcm_frames(ma_bpf* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2317 
2318 
2319 /**************************************************************************************************************************************************************
2320 
2321 Notching Filter
2322 
2323 **************************************************************************************************************************************************************/
2324 typedef struct
2325 {
2326  ma_format format;
2329  double q;
2330  double frequency;
2332 
2334 
2335 typedef struct
2336 {
2337  ma_biquad bq;
2338 } ma_notch2;
2339 
2340 MA_API ma_result ma_notch2_init(const ma_notch2_config* pConfig, ma_notch2* pFilter);
2341 MA_API ma_result ma_notch2_reinit(const ma_notch2_config* pConfig, ma_notch2* pFilter);
2342 MA_API ma_result ma_notch2_process_pcm_frames(ma_notch2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2344 
2345 
2346 /**************************************************************************************************************************************************************
2347 
2348 Peaking EQ Filter
2349 
2350 **************************************************************************************************************************************************************/
2351 typedef struct
2352 {
2353  ma_format format;
2356  double gainDB;
2357  double q;
2358  double frequency;
2360 
2361 MA_API ma_peak2_config ma_peak2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
2362 
2363 typedef struct
2364 {
2365  ma_biquad bq;
2366 } ma_peak2;
2367 
2368 MA_API ma_result ma_peak2_init(const ma_peak2_config* pConfig, ma_peak2* pFilter);
2369 MA_API ma_result ma_peak2_reinit(const ma_peak2_config* pConfig, ma_peak2* pFilter);
2370 MA_API ma_result ma_peak2_process_pcm_frames(ma_peak2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2372 
2373 
2374 /**************************************************************************************************************************************************************
2375 
2376 Low Shelf Filter
2377 
2378 **************************************************************************************************************************************************************/
2379 typedef struct
2380 {
2381  ma_format format;
2384  double gainDB;
2385  double shelfSlope;
2386  double frequency;
2388 
2389 MA_API ma_loshelf2_config ma_loshelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency);
2390 
2391 typedef struct
2392 {
2393  ma_biquad bq;
2394 } ma_loshelf2;
2395 
2398 MA_API ma_result ma_loshelf2_process_pcm_frames(ma_loshelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2400 
2401 
2402 /**************************************************************************************************************************************************************
2403 
2404 High Shelf Filter
2405 
2406 **************************************************************************************************************************************************************/
2407 typedef struct
2408 {
2409  ma_format format;
2412  double gainDB;
2413  double shelfSlope;
2414  double frequency;
2416 
2417 MA_API ma_hishelf2_config ma_hishelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency);
2418 
2419 typedef struct
2420 {
2421  ma_biquad bq;
2422 } ma_hishelf2;
2423 
2426 MA_API ma_result ma_hishelf2_process_pcm_frames(ma_hishelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2428 
2429 
2430 
2431 /************************************************************************************************************************************************************
2432 *************************************************************************************************************************************************************
2433 
2434 DATA CONVERSION
2435 ===============
2436 
2437 This section contains the APIs for data conversion. You will find everything here for channel mapping, sample format conversion, resampling, etc.
2438 
2439 *************************************************************************************************************************************************************
2440 ************************************************************************************************************************************************************/
2441 
2442 /**************************************************************************************************************************************************************
2443 
2444 Resampling
2445 
2446 **************************************************************************************************************************************************************/
2447 typedef struct
2448 {
2449  ma_format format;
2451  ma_uint32 sampleRateIn;
2452  ma_uint32 sampleRateOut;
2453  ma_uint32 lpfOrder; /* The low-pass filter order. Setting this to 0 will disable low-pass filtering. */
2454  double lpfNyquistFactor; /* 0..1. Defaults to 1. 1 = Half the sampling frequency (Nyquist Frequency), 0.5 = Quarter the sampling frequency (half Nyquest Frequency), etc. */
2456 
2458 
2459 typedef struct
2460 {
2462  ma_uint32 inAdvanceInt;
2463  ma_uint32 inAdvanceFrac;
2464  ma_uint32 inTimeInt;
2465  ma_uint32 inTimeFrac;
2466  union
2467  {
2468  float f32[MA_MAX_CHANNELS];
2470  } x0; /* The previous input frame. */
2471  union
2472  {
2473  float f32[MA_MAX_CHANNELS];
2475  } x1; /* The next input frame. */
2476  ma_lpf lpf;
2478 
2481 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);
2482 MA_API ma_result ma_linear_resampler_set_rate(ma_linear_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
2488 
2489 typedef enum
2490 {
2491  ma_resample_algorithm_linear = 0, /* Fastest, lowest quality. Optional low-pass filtering. Default. */
2494 
2495 typedef struct
2496 {
2497  ma_format format; /* Must be either ma_format_f32 or ma_format_s16. */
2499  ma_uint32 sampleRateIn;
2500  ma_uint32 sampleRateOut;
2502  struct
2503  {
2505  double lpfNyquistFactor;
2506  } linear;
2507  struct
2508  {
2509  int quality; /* 0 to 10. Defaults to 3. */
2510  } speex;
2512 
2514 
2515 typedef struct
2516 {
2518  union
2519  {
2521  struct
2522  {
2523  void* pSpeexResamplerState; /* SpeexResamplerState* */
2524  } speex;
2525  } state;
2526 } ma_resampler;
2527 
2528 /*
2529 Initializes a new resampler object from a config.
2530 */
2532 
2533 /*
2534 Uninitializes a resampler.
2535 */
2536 MA_API void ma_resampler_uninit(ma_resampler* pResampler);
2537 
2538 /*
2539 Converts the given input data.
2540 
2541 Both the input and output frames must be in the format specified in the config when the resampler was initilized.
2542 
2543 On input, [pFrameCountOut] contains the number of output frames to process. On output it contains the number of output frames that
2544 were actually processed, which may be less than the requested amount which will happen if there's not enough input data. You can use
2545 ma_resampler_get_expected_output_frame_count() to know how many output frames will be processed for a given number of input frames.
2546 
2547 On input, [pFrameCountIn] contains the number of input frames contained in [pFramesIn]. On output it contains the number of whole
2548 input frames that were actually processed. You can use ma_resampler_get_required_input_frame_count() to know how many input frames
2549 you should provide for a given number of output frames. [pFramesIn] can be NULL, in which case zeroes will be used instead.
2550 
2551 If [pFramesOut] is NULL, a seek is performed. In this case, if [pFrameCountOut] is not NULL it will seek by the specified number of
2552 output frames. Otherwise, if [pFramesCountOut] is NULL and [pFrameCountIn] is not NULL, it will seek by the specified number of input
2553 frames. When seeking, [pFramesIn] is allowed to NULL, in which case the internal timing state will be updated, but no input will be
2554 processed. In this case, any internal filter state will be updated as if zeroes were passed in.
2555 
2556 It is an error for [pFramesOut] to be non-NULL and [pFrameCountOut] to be NULL.
2557 
2558 It is an error for both [pFrameCountOut] and [pFrameCountIn] to be NULL.
2559 */
2560 MA_API ma_result ma_resampler_process_pcm_frames(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut);
2561 
2562 
2563 /*
2564 Sets the input and output sample sample rate.
2565 */
2566 MA_API ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
2567 
2568 /*
2569 Sets the input and output sample rate as a ratio.
2570 
2571 The ration is in/out.
2572 */
2573 MA_API ma_result ma_resampler_set_rate_ratio(ma_resampler* pResampler, float ratio);
2574 
2575 
2576 /*
2577 Calculates the number of whole input frames that would need to be read from the client in order to output the specified
2578 number of output frames.
2579 
2580 The returned value does not include cached input frames. It only returns the number of extra frames that would need to be
2581 read from the input buffer in order to output the specified number of output frames.
2582 */
2584 
2585 /*
2586 Calculates the number of whole output frames that would be output after fully reading and consuming the specified number of
2587 input frames.
2588 */
2590 
2591 
2592 /*
2593 Retrieves the latency introduced by the resampler in input frames.
2594 */
2596 
2597 /*
2598 Retrieves the latency introduced by the resampler in output frames.
2599 */
2601 
2602 
2603 
2604 /**************************************************************************************************************************************************************
2605 
2606 Channel Conversion
2607 
2608 **************************************************************************************************************************************************************/
2609 typedef struct
2610 {
2611  ma_format format;
2612  ma_uint32 channelsIn;
2613  ma_uint32 channelsOut;
2614  ma_channel channelMapIn[MA_MAX_CHANNELS];
2615  ma_channel channelMapOut[MA_MAX_CHANNELS];
2616  ma_channel_mix_mode mixingMode;
2617  float weights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]; /* [in][out]. Only used when mixingMode is set to ma_channel_mix_mode_custom_weights. */
2619 
2620 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);
2621 
2622 typedef struct
2623 {
2624  ma_format format;
2625  ma_uint32 channelsIn;
2626  ma_uint32 channelsOut;
2627  ma_channel channelMapIn[MA_MAX_CHANNELS];
2628  ma_channel channelMapOut[MA_MAX_CHANNELS];
2629  ma_channel_mix_mode mixingMode;
2630  union
2631  {
2632  float f32[MA_MAX_CHANNELS][MA_MAX_CHANNELS];
2634  } weights;
2635  ma_bool8 isPassthrough;
2636  ma_bool8 isSimpleShuffle;
2637  ma_bool8 isSimpleMonoExpansion;
2638  ma_bool8 isStereoToMono;
2639  ma_uint8 shuffleTable[MA_MAX_CHANNELS];
2641 
2644 MA_API ma_result ma_channel_converter_process_pcm_frames(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
2645 
2646 
2647 /**************************************************************************************************************************************************************
2648 
2649 Data Conversion
2650 
2651 **************************************************************************************************************************************************************/
2652 typedef struct
2653 {
2654  ma_format formatIn;
2655  ma_format formatOut;
2656  ma_uint32 channelsIn;
2657  ma_uint32 channelsOut;
2658  ma_uint32 sampleRateIn;
2659  ma_uint32 sampleRateOut;
2660  ma_channel channelMapIn[MA_MAX_CHANNELS];
2661  ma_channel channelMapOut[MA_MAX_CHANNELS];
2662  ma_dither_mode ditherMode;
2664  float channelWeights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]; /* [in][out]. Only used when channelMixMode is set to ma_channel_mix_mode_custom_weights. */
2665  struct
2666  {
2668  ma_bool32 allowDynamicSampleRate;
2669  struct
2670  {
2672  double lpfNyquistFactor;
2673  } linear;
2674  struct
2675  {
2676  int quality;
2677  } speex;
2678  } resampling;
2680 
2682 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);
2683 
2684 typedef struct
2685 {
2687  ma_channel_converter channelConverter;
2688  ma_resampler resampler;
2689  ma_bool8 hasPreFormatConversion;
2690  ma_bool8 hasPostFormatConversion;
2691  ma_bool8 hasChannelConverter;
2692  ma_bool8 hasResampler;
2693  ma_bool8 isPassthrough;
2695 
2698 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);
2699 MA_API ma_result ma_data_converter_set_rate(ma_data_converter* pConverter, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
2705 
2706 
2707 /************************************************************************************************************************************************************
2708 
2709 Format Conversion
2710 
2711 ************************************************************************************************************************************************************/
2712 MA_API void ma_pcm_u8_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2713 MA_API void ma_pcm_u8_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2714 MA_API void ma_pcm_u8_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2715 MA_API void ma_pcm_u8_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2716 MA_API void ma_pcm_s16_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2717 MA_API void ma_pcm_s16_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2718 MA_API void ma_pcm_s16_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2719 MA_API void ma_pcm_s16_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2720 MA_API void ma_pcm_s24_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2721 MA_API void ma_pcm_s24_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2722 MA_API void ma_pcm_s24_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2723 MA_API void ma_pcm_s24_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2724 MA_API void ma_pcm_s32_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2725 MA_API void ma_pcm_s32_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2726 MA_API void ma_pcm_s32_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2727 MA_API void ma_pcm_s32_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2728 MA_API void ma_pcm_f32_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2729 MA_API void ma_pcm_f32_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2730 MA_API void ma_pcm_f32_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2731 MA_API void ma_pcm_f32_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
2732 MA_API void ma_pcm_convert(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode);
2733 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);
2734 
2735 /*
2736 Deinterleaves an interleaved buffer.
2737 */
2738 MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void* pInterleavedPCMFrames, void** ppDeinterleavedPCMFrames);
2739 
2740 /*
2741 Interleaves a group of deinterleaved buffers.
2742 */
2743 MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void** ppDeinterleavedPCMFrames, void* pInterleavedPCMFrames);
2744 
2745 
2746 /************************************************************************************************************************************************************
2747 
2748 Channel Maps
2749 
2750 ************************************************************************************************************************************************************/
2751 /*
2752 This is used in the shuffle table to indicate that the channel index is undefined and should be ignored.
2753 */
2754 #define MA_CHANNEL_INDEX_NULL 255
2755 
2756 /* Retrieves the channel position of the specified channel based on miniaudio's default channel map. */
2758 
2759 /*
2760 Retrieves the channel position of the specified channel in the given channel map.
2761 
2762 The pChannelMap parameter can be null, in which case miniaudio's default channel map will be assumed.
2763 */
2764 MA_API ma_channel ma_channel_map_get_channel(const ma_channel* pChannelMap, ma_uint32 channelCount, ma_uint32 channelIndex);
2765 
2766 /*
2767 Initializes a blank channel map.
2768 
2769 When a blank channel map is specified anywhere it indicates that the native channel map should be used.
2770 */
2772 
2773 /*
2774 Helper for retrieving a standard channel map.
2775 
2776 The output channel map buffer must have a capacity of at least `channels`.
2777 */
2779 
2780 /*
2781 Copies a channel map.
2782 
2783 Both input and output channel map buffers must have a capacity of at at least `channels`.
2784 */
2786 
2787 /*
2788 Copies a channel map if one is specified, otherwise copies the default channel map.
2789 
2790 The output buffer must have a capacity of at least `channels`. If not NULL, the input channel map must also have a capacity of at least `channels`.
2791 */
2793 
2794 
2795 /*
2796 Determines whether or not a channel map is valid.
2797 
2798 A blank channel map is valid (all channels set to MA_CHANNEL_NONE). The way a blank channel map is handled is context specific, but
2799 is usually treated as a passthrough.
2800 
2801 Invalid channel maps:
2802  - A channel map with no channels
2803  - A channel map with more than one channel and a mono channel
2804 
2805 The channel map buffer must have a capacity of at least `channels`.
2806 */
2808 
2809 /*
2810 Helper for comparing two channel maps for equality.
2811 
2812 This assumes the channel count is the same between the two.
2813 
2814 Both channels map buffers must have a capacity of at least `channels`.
2815 */
2816 MA_API ma_bool32 ma_channel_map_equal(ma_uint32 channels, const ma_channel* pChannelMapA, const ma_channel* pChannelMapB);
2817 
2818 /*
2819 Helper for determining if a channel map is blank (all channels set to MA_CHANNEL_NONE).
2820 
2821 The channel map buffer must have a capacity of at least `channels`.
2822 */
2824 
2825 /*
2826 Helper for determining whether or not a channel is present in the given channel map.
2827 
2828 The channel map buffer must have a capacity of at least `channels`.
2829 */
2831 
2832 
2833 /************************************************************************************************************************************************************
2834 
2835 Conversion Helpers
2836 
2837 ************************************************************************************************************************************************************/
2838 
2839 /*
2840 High-level helper for doing a full format conversion in one go. Returns the number of output frames. Call this with pOut set to NULL to
2841 determine the required size of the output buffer. frameCountOut should be set to the capacity of pOut. If pOut is NULL, frameCountOut is
2842 ignored.
2843 
2844 A return value of 0 indicates an error.
2845 
2846 This function is useful for one-off bulk conversions, but if you're streaming data you should use the ma_data_converter APIs instead.
2847 */
2848 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);
2849 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);
2850 
2851 
2852 /************************************************************************************************************************************************************
2853 
2854 Ring Buffer
2855 
2856 ************************************************************************************************************************************************************/
2857 typedef struct
2858 {
2859  void* pBuffer;
2860  ma_uint32 subbufferSizeInBytes;
2861  ma_uint32 subbufferCount;
2862  ma_uint32 subbufferStrideInBytes;
2863  MA_ATOMIC ma_uint32 encodedReadOffset; /* Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
2864  MA_ATOMIC ma_uint32 encodedWriteOffset; /* Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
2865  ma_bool8 ownsBuffer; /* Used to know whether or not miniaudio is responsible for free()-ing the buffer. */
2866  ma_bool8 clearOnWriteAcquire; /* When set, clears the acquired write buffer before returning from ma_rb_acquire_write(). */
2867  ma_allocation_callbacks allocationCallbacks;
2868 } ma_rb;
2869 
2870 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);
2871 MA_API ma_result ma_rb_init(size_t bufferSizeInBytes, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_rb* pRB);
2872 MA_API void ma_rb_uninit(ma_rb* pRB);
2873 MA_API void ma_rb_reset(ma_rb* pRB);
2874 MA_API ma_result ma_rb_acquire_read(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut);
2875 MA_API ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut);
2876 MA_API ma_result ma_rb_acquire_write(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut);
2877 MA_API ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut);
2878 MA_API ma_result ma_rb_seek_read(ma_rb* pRB, size_t offsetInBytes);
2879 MA_API ma_result ma_rb_seek_write(ma_rb* pRB, size_t offsetInBytes);
2880 MA_API ma_int32 ma_rb_pointer_distance(ma_rb* pRB); /* Returns the distance between the write pointer and the read pointer. Should never be negative for a correct program. Will return the number of bytes that can be read before the read pointer hits the write pointer. */
2885 MA_API size_t ma_rb_get_subbuffer_offset(ma_rb* pRB, size_t subbufferIndex);
2886 MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pBuffer);
2887 
2888 
2889 typedef struct
2890 {
2891  ma_rb rb;
2892  ma_format format;
2894 } ma_pcm_rb;
2895 
2896 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);
2897 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);
2898 MA_API void ma_pcm_rb_uninit(ma_pcm_rb* pRB);
2899 MA_API void ma_pcm_rb_reset(ma_pcm_rb* pRB);
2900 MA_API ma_result ma_pcm_rb_acquire_read(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut);
2901 MA_API ma_result ma_pcm_rb_commit_read(ma_pcm_rb* pRB, ma_uint32 sizeInFrames, void* pBufferOut);
2902 MA_API ma_result ma_pcm_rb_acquire_write(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut);
2903 MA_API ma_result ma_pcm_rb_commit_write(ma_pcm_rb* pRB, ma_uint32 sizeInFrames, void* pBufferOut);
2906 MA_API ma_int32 ma_pcm_rb_pointer_distance(ma_pcm_rb* pRB); /* Return value is in frames. */
2912 MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer);
2913 
2914 
2915 /*
2916 The idea of the duplex ring buffer is to act as the intermediary buffer when running two asynchronous devices in a duplex set up. The
2917 capture device writes to it, and then a playback device reads from it.
2918 
2919 At the moment this is just a simple naive implementation, but in the future I want to implement some dynamic resampling to seamlessly
2920 handle desyncs. Note that the API is work in progress and may change at any time in any version.
2921 
2922 The size of the buffer is based on the capture side since that's what'll be written to the buffer. It is based on the capture period size
2923 in frames. The internal sample rate of the capture device is also needed in order to calculate the size.
2924 */
2925 typedef struct
2926 {
2927  ma_pcm_rb rb;
2928 } ma_duplex_rb;
2929 
2930 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);
2932 
2933 
2934 /************************************************************************************************************************************************************
2935 
2936 Miscellaneous Helpers
2937 
2938 ************************************************************************************************************************************************************/
2939 /*
2940 Retrieves a human readable description of the given result code.
2941 */
2942 MA_API const char* ma_result_description(ma_result result);
2943 
2944 /*
2945 malloc(). Calls MA_MALLOC().
2946 */
2947 MA_API void* ma_malloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks);
2948 
2949 /*
2950 realloc(). Calls MA_REALLOC().
2951 */
2952 MA_API void* ma_realloc(void* p, size_t sz, const ma_allocation_callbacks* pAllocationCallbacks);
2953 
2954 /*
2955 free(). Calls MA_FREE().
2956 */
2957 MA_API void ma_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks);
2958 
2959 /*
2960 Performs an aligned malloc, with the assumption that the alignment is a power of 2.
2961 */
2962 MA_API void* ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks* pAllocationCallbacks);
2963 
2964 /*
2965 Free's an aligned malloc'd buffer.
2966 */
2967 MA_API void ma_aligned_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks);
2968 
2969 /*
2970 Retrieves a friendly name for a format.
2971 */
2973 
2974 /*
2975 Blends two frames in floating point format.
2976 */
2977 MA_API void ma_blend_f32(float* pOut, float* pInA, float* pInB, float factor, ma_uint32 channels);
2978 
2979 /*
2980 Retrieves the size of a sample in bytes for the given format.
2981 
2982 This API is efficient and is implemented using a lookup table.
2983 
2984 Thread Safety: SAFE
2985  This API is pure.
2986 */
2989 
2990 /*
2991 Converts a log level to a string.
2992 */
2993 MA_API const char* ma_log_level_to_string(ma_uint32 logLevel);
2994 
2995 
2996 
2997 /************************************************************************************************************************************************************
2998 *************************************************************************************************************************************************************
2999 
3000 DEVICE I/O
3001 ==========
3002 
3003 This section contains the APIs for device playback and capture. Here is where you'll find ma_device_init(), etc.
3004 
3005 *************************************************************************************************************************************************************
3006 ************************************************************************************************************************************************************/
3007 #ifndef MA_NO_DEVICE_IO
3008 /* Some backends are only supported on certain platforms. */
3009 #if defined(MA_WIN32)
3010  #define MA_SUPPORT_WASAPI
3011  #if defined(MA_WIN32_DESKTOP) /* DirectSound and WinMM backends are only supported on desktops. */
3012  #define MA_SUPPORT_DSOUND
3013  #define MA_SUPPORT_WINMM
3014  #define MA_SUPPORT_JACK /* JACK is technically supported on Windows, but I don't know how many people use it in practice... */
3015  #endif
3016 #endif
3017 #if defined(MA_UNIX)
3018  #if defined(MA_LINUX)
3019  #if !defined(MA_ANDROID) /* ALSA is not supported on Android. */
3020  #define MA_SUPPORT_ALSA
3021  #endif
3022  #endif
3023  #if !defined(MA_BSD) && !defined(MA_ANDROID) && !defined(MA_EMSCRIPTEN)
3024  #define MA_SUPPORT_PULSEAUDIO
3025  #define MA_SUPPORT_JACK
3026  #endif
3027  #if defined(MA_ANDROID)
3028  #define MA_SUPPORT_AAUDIO
3029  #define MA_SUPPORT_OPENSL
3030  #endif
3031  #if defined(__OpenBSD__) /* <-- Change this to "#if defined(MA_BSD)" to enable sndio on all BSD flavors. */
3032  #define MA_SUPPORT_SNDIO /* sndio is only supported on OpenBSD for now. May be expanded later if there's demand. */
3033  #endif
3034  #if defined(__NetBSD__) || defined(__OpenBSD__)
3035  #define MA_SUPPORT_AUDIO4 /* Only support audio(4) on platforms with known support. */
3036  #endif
3037  #if defined(__FreeBSD__) || defined(__DragonFly__)
3038  #define MA_SUPPORT_OSS /* Only support OSS on specific platforms with known support. */
3039  #endif
3040 #endif
3041 #if defined(MA_APPLE)
3042  #define MA_SUPPORT_COREAUDIO
3043 #endif
3044 #if defined(MA_EMSCRIPTEN)
3045  #define MA_SUPPORT_WEBAUDIO
3046 #endif
3047 
3048 /* All platforms should support custom backends. */
3049 #define MA_SUPPORT_CUSTOM
3050 
3051 /* Explicitly disable the Null backend for Emscripten because it uses a background thread which is not properly supported right now. */
3052 #if !defined(MA_EMSCRIPTEN)
3053 #define MA_SUPPORT_NULL
3054 #endif
3055 
3056 
3057 #if defined(MA_SUPPORT_WASAPI) && !defined(MA_NO_WASAPI) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_WASAPI))
3058  #define MA_HAS_WASAPI
3059 #endif
3060 #if defined(MA_SUPPORT_DSOUND) && !defined(MA_NO_DSOUND) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_DSOUND))
3061  #define MA_HAS_DSOUND
3062 #endif
3063 #if defined(MA_SUPPORT_WINMM) && !defined(MA_NO_WINMM) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_WINMM))
3064  #define MA_HAS_WINMM
3065 #endif
3066 #if defined(MA_SUPPORT_ALSA) && !defined(MA_NO_ALSA) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_ALSA))
3067  #define MA_HAS_ALSA
3068 #endif
3069 #if defined(MA_SUPPORT_PULSEAUDIO) && !defined(MA_NO_PULSEAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_PULSEAUDIO))
3070  #define MA_HAS_PULSEAUDIO
3071 #endif
3072 #if defined(MA_SUPPORT_JACK) && !defined(MA_NO_JACK) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_JACK))
3073  #define MA_HAS_JACK
3074 #endif
3075 #if defined(MA_SUPPORT_COREAUDIO) && !defined(MA_NO_COREAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_COREAUDIO))
3076  #define MA_HAS_COREAUDIO
3077 #endif
3078 #if defined(MA_SUPPORT_SNDIO) && !defined(MA_NO_SNDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_SNDIO))
3079  #define MA_HAS_SNDIO
3080 #endif
3081 #if defined(MA_SUPPORT_AUDIO4) && !defined(MA_NO_AUDIO4) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_AUDIO4))
3082  #define MA_HAS_AUDIO4
3083 #endif
3084 #if defined(MA_SUPPORT_OSS) && !defined(MA_NO_OSS) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_OSS))
3085  #define MA_HAS_OSS
3086 #endif
3087 #if defined(MA_SUPPORT_AAUDIO) && !defined(MA_NO_AAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_AAUDIO))
3088  #define MA_HAS_AAUDIO
3089 #endif
3090 #if defined(MA_SUPPORT_OPENSL) && !defined(MA_NO_OPENSL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_OPENSL))
3091  #define MA_HAS_OPENSL
3092 #endif
3093 #if defined(MA_SUPPORT_WEBAUDIO) && !defined(MA_NO_WEBAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_WEBAUDIO))
3094  #define MA_HAS_WEBAUDIO
3095 #endif
3096 #if defined(MA_SUPPORT_CUSTOM) && !defined(MA_NO_CUSTOM) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_CUSTOM))
3097  #define MA_HAS_CUSTOM
3098 #endif
3099 #if defined(MA_SUPPORT_NULL) && !defined(MA_NO_NULL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_NULL))
3100  #define MA_HAS_NULL
3101 #endif
3102 
3103 #define MA_STATE_UNINITIALIZED 0
3104 #define MA_STATE_STOPPED 1 /* The device's default state after initialization. */
3105 #define MA_STATE_STARTED 2 /* The device is started and is requesting and/or delivering audio data. */
3106 #define MA_STATE_STARTING 3 /* Transitioning from a stopped state to started. */
3107 #define MA_STATE_STOPPING 4 /* Transitioning from a started state to stopped. */
3108 
3109 #ifdef MA_SUPPORT_WASAPI
3110 /* We need a IMMNotificationClient object for WASAPI. */
3111 typedef struct
3112 {
3113  void* lpVtbl;
3114  ma_uint32 counter;
3115  ma_device* pDevice;
3116 } ma_IMMNotificationClient;
3117 #endif
3118 
3119 /* Backend enums must be in priority order. */
3120 typedef enum
3121 {
3135  ma_backend_custom, /* <-- Custom backend, with callbacks defined by the context config. */
3136  ma_backend_null /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */
3137 } ma_backend;
3138 
3139 #define MA_BACKEND_COUNT (ma_backend_null+1)
3140 
3141 
3142 /*
3143 The callback for processing audio data from the device.
3144 
3145 The data callback is fired by miniaudio whenever the device needs to have more data delivered to a playback device, or when a capture device has some data
3146 available. This is called as soon as the backend asks for more data which means it may be called with inconsistent frame counts. You cannot assume the
3147 callback will be fired with a consistent frame count.
3148 
3149 
3150 Parameters
3151 ----------
3152 pDevice (in)
3153  A pointer to the relevant device.
3154 
3155 pOutput (out)
3156  A pointer to the output buffer that will receive audio data that will later be played back through the speakers. This will be non-null for a playback or
3157  full-duplex device and null for a capture and loopback device.
3158 
3159 pInput (in)
3160  A pointer to the buffer containing input data from a recording device. This will be non-null for a capture, full-duplex or loopback device and null for a
3161  playback device.
3162 
3163 frameCount (in)
3164  The number of PCM frames to process. Note that this will not necessarily be equal to what you requested when you initialized the device. The
3165  `periodSizeInFrames` and `periodSizeInMilliseconds` members of the device config are just hints, and are not necessarily exactly what you'll get. You must
3166  not assume this will always be the same value each time the callback is fired.
3167 
3168 
3169 Remarks
3170 -------
3171 You cannot stop and start the device from inside the callback or else you'll get a deadlock. You must also not uninitialize the device from inside the
3172 callback. The following APIs cannot be called from inside the callback:
3173 
3174  ma_device_init()
3175  ma_device_init_ex()
3176  ma_device_uninit()
3177  ma_device_start()
3178  ma_device_stop()
3179 
3180 The proper way to stop the device is to call `ma_device_stop()` from a different thread, normally the main application thread.
3181 */
3182 typedef void (* ma_device_callback_proc)(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
3183 
3184 /*
3185 The callback for when the device has been stopped.
3186 
3187 This will be called when the device is stopped explicitly with `ma_device_stop()` and also called implicitly when the device is stopped through external forces
3188 such as being unplugged or an internal error occuring.
3189 
3190 
3191 Parameters
3192 ----------
3193 pDevice (in)
3194  A pointer to the device that has just stopped.
3195 
3196 
3197 Remarks
3198 -------
3199 Do not restart or uninitialize the device from the callback.
3200 */
3201 typedef void (* ma_stop_proc)(ma_device* pDevice);
3202 
3203 /*
3204 The callback for handling log messages.
3205 
3206 
3207 Parameters
3208 ----------
3209 pContext (in)
3210  A pointer to the context the log message originated from.
3211 
3212 pDevice (in)
3213  A pointer to the device the log message originate from, if any. This can be null, in which case the message came from the context.
3214 
3215 logLevel (in)
3216  The log level. This can be one of the following:
3217 
3218  +----------------------+
3219  | Log Level |
3220  +----------------------+
3221  | MA_LOG_LEVEL_DEBUG |
3222  | MA_LOG_LEVEL_INFO |
3223  | MA_LOG_LEVEL_WARNING |
3224  | MA_LOG_LEVEL_ERROR |
3225  +----------------------+
3226 
3227 message (in)
3228  The log message.
3229 
3230 
3231 Remarks
3232 -------
3233 Do not modify the state of the device from inside the callback.
3234 */
3235 typedef void (* ma_log_proc)(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message);
3236 
3237 typedef enum
3238 {
3243 } ma_device_type;
3244 
3245 typedef enum
3246 {
3249 } ma_share_mode;
3250 
3251 /* iOS/tvOS/watchOS session categories. */
3252 typedef enum
3253 {
3254  ma_ios_session_category_default = 0, /* AVAudioSessionCategoryPlayAndRecord with AVAudioSessionCategoryOptionDefaultToSpeaker. */
3255  ma_ios_session_category_none, /* Leave the session category unchanged. */
3256  ma_ios_session_category_ambient, /* AVAudioSessionCategoryAmbient */
3257  ma_ios_session_category_solo_ambient, /* AVAudioSessionCategorySoloAmbient */
3258  ma_ios_session_category_playback, /* AVAudioSessionCategoryPlayback */
3259  ma_ios_session_category_record, /* AVAudioSessionCategoryRecord */
3260  ma_ios_session_category_play_and_record, /* AVAudioSessionCategoryPlayAndRecord */
3261  ma_ios_session_category_multi_route /* AVAudioSessionCategoryMultiRoute */
3263 
3264 /* iOS/tvOS/watchOS session category options */
3265 typedef enum
3266 {
3267  ma_ios_session_category_option_mix_with_others = 0x01, /* AVAudioSessionCategoryOptionMixWithOthers */
3268  ma_ios_session_category_option_duck_others = 0x02, /* AVAudioSessionCategoryOptionDuckOthers */
3269  ma_ios_session_category_option_allow_bluetooth = 0x04, /* AVAudioSessionCategoryOptionAllowBluetooth */
3270  ma_ios_session_category_option_default_to_speaker = 0x08, /* AVAudioSessionCategoryOptionDefaultToSpeaker */
3271  ma_ios_session_category_option_interrupt_spoken_audio_and_mix_with_others = 0x11, /* AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers */
3272  ma_ios_session_category_option_allow_bluetooth_a2dp = 0x20, /* AVAudioSessionCategoryOptionAllowBluetoothA2DP */
3273  ma_ios_session_category_option_allow_air_play = 0x40, /* AVAudioSessionCategoryOptionAllowAirPlay */
3275 
3276 /* OpenSL stream types. */
3277 typedef enum
3278 {
3279  ma_opensl_stream_type_default = 0, /* Leaves the stream type unset. */
3280  ma_opensl_stream_type_voice, /* SL_ANDROID_STREAM_VOICE */
3281  ma_opensl_stream_type_system, /* SL_ANDROID_STREAM_SYSTEM */
3282  ma_opensl_stream_type_ring, /* SL_ANDROID_STREAM_RING */
3283  ma_opensl_stream_type_media, /* SL_ANDROID_STREAM_MEDIA */
3284  ma_opensl_stream_type_alarm, /* SL_ANDROID_STREAM_ALARM */
3285  ma_opensl_stream_type_notification /* SL_ANDROID_STREAM_NOTIFICATION */
3287 
3288 /* OpenSL recording presets. */
3289 typedef enum
3290 {
3291  ma_opensl_recording_preset_default = 0, /* Leaves the input preset unset. */
3292  ma_opensl_recording_preset_generic, /* SL_ANDROID_RECORDING_PRESET_GENERIC */
3293  ma_opensl_recording_preset_camcorder, /* SL_ANDROID_RECORDING_PRESET_CAMCORDER */
3294  ma_opensl_recording_preset_voice_recognition, /* SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION */
3295  ma_opensl_recording_preset_voice_communication, /* SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION */
3296  ma_opensl_recording_preset_voice_unprocessed /* SL_ANDROID_RECORDING_PRESET_UNPROCESSED */
3298 
3299 /* AAudio usage types. */
3300 typedef enum
3301 {
3302  ma_aaudio_usage_default = 0, /* Leaves the usage type unset. */
3303  ma_aaudio_usage_announcement, /* AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT */
3304  ma_aaudio_usage_emergency, /* AAUDIO_SYSTEM_USAGE_EMERGENCY */
3305  ma_aaudio_usage_safety, /* AAUDIO_SYSTEM_USAGE_SAFETY */
3306  ma_aaudio_usage_vehicle_status, /* AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS */
3307  ma_aaudio_usage_alarm, /* AAUDIO_USAGE_ALARM */
3308  ma_aaudio_usage_assistance_accessibility, /* AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY */
3309  ma_aaudio_usage_assistance_navigation_guidance, /* AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE */
3310  ma_aaudio_usage_assistance_sonification, /* AAUDIO_USAGE_ASSISTANCE_SONIFICATION */
3311  ma_aaudio_usage_assitant, /* AAUDIO_USAGE_ASSISTANT */
3312  ma_aaudio_usage_game, /* AAUDIO_USAGE_GAME */
3313  ma_aaudio_usage_media, /* AAUDIO_USAGE_MEDIA */
3314  ma_aaudio_usage_notification, /* AAUDIO_USAGE_NOTIFICATION */
3315  ma_aaudio_usage_notification_event, /* AAUDIO_USAGE_NOTIFICATION_EVENT */
3316  ma_aaudio_usage_notification_ringtone, /* AAUDIO_USAGE_NOTIFICATION_RINGTONE */
3317  ma_aaudio_usage_voice_communication, /* AAUDIO_USAGE_VOICE_COMMUNICATION */
3318  ma_aaudio_usage_voice_communication_signalling /* AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING */
3319 } ma_aaudio_usage;
3320 
3321 /* AAudio content types. */
3322 typedef enum
3323 {
3324  ma_aaudio_content_type_default = 0, /* Leaves the content type unset. */
3325  ma_aaudio_content_type_movie, /* AAUDIO_CONTENT_TYPE_MOVIE */
3326  ma_aaudio_content_type_music, /* AAUDIO_CONTENT_TYPE_MUSIC */
3327  ma_aaudio_content_type_sonification, /* AAUDIO_CONTENT_TYPE_SONIFICATION */
3328  ma_aaudio_content_type_speech /* AAUDIO_CONTENT_TYPE_SPEECH */
3330 
3331 /* AAudio input presets. */
3332 typedef enum
3333 {
3334  ma_aaudio_input_preset_default = 0, /* Leaves the input preset unset. */
3335  ma_aaudio_input_preset_generic, /* AAUDIO_INPUT_PRESET_GENERIC */
3336  ma_aaudio_input_preset_camcorder, /* AAUDIO_INPUT_PRESET_CAMCORDER */
3337  ma_aaudio_input_preset_unprocessed, /* AAUDIO_INPUT_PRESET_UNPROCESSED */
3338  ma_aaudio_input_preset_voice_recognition, /* AAUDIO_INPUT_PRESET_VOICE_RECOGNITION */
3339  ma_aaudio_input_preset_voice_communication, /* AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION */
3340  ma_aaudio_input_preset_voice_performance /* AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE */
3342 
3343 
3344 typedef union
3345 {
3346  ma_int64 counter;
3347  double counterD;
3348 } ma_timer;
3349 
3350 typedef union
3351 {
3352  wchar_t wasapi[64]; /* WASAPI uses a wchar_t string for identification. */
3353  ma_uint8 dsound[16]; /* DirectSound uses a GUID for identification. */
3354  /*UINT_PTR*/ ma_uint32 winmm; /* When creating a device, WinMM expects a Win32 UINT_PTR for device identification. In practice it's actually just a UINT. */
3355  char alsa[256]; /* ALSA uses a name string for identification. */
3356  char pulse[256]; /* PulseAudio uses a name string for identification. */
3357  int jack; /* JACK always uses default devices. */
3358  char coreaudio[256]; /* Core Audio uses a string for identification. */
3359  char sndio[256]; /* "snd/0", etc. */
3360  char audio4[256]; /* "/dev/audio", etc. */
3361  char oss[64]; /* "dev/dsp0", etc. "dev/dsp" for the default device. */
3362  ma_int32 aaudio; /* AAudio uses a 32-bit integer for identification. */
3363  ma_uint32 opensl; /* OpenSL|ES uses a 32-bit unsigned integer for identification. */
3364  char webaudio[32]; /* Web Audio always uses default devices for now, but if this changes it'll be a GUID. */
3365  union
3366  {
3367  int i;
3368  char s[256];
3369  void* p;
3370  } custom; /* The custom backend could be anything. Give them a few options. */
3371  int nullbackend; /* The null backend uses an integer for device IDs. */
3372 } ma_device_id;
3373 
3374 
3378 
3379 #define MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE (1U << 1) /* If set, this is supported in exclusive mode. Otherwise not natively supported by exclusive mode. */
3380 
3381 typedef struct
3382 {
3383  /* Basic info. This is the only information guaranteed to be filled in during device enumeration. */
3384  ma_device_id id;
3385  char name[256];
3386  ma_bool32 isDefault;
3387 
3388  /*
3389  Detailed info. As much of this is filled as possible with ma_context_get_device_info(). Note that you are allowed to initialize
3390  a device with settings outside of this range, but it just means the data will be converted using miniaudio's data conversion
3391  pipeline before sending the data to/from the device. Most programs will need to not worry about these values, but it's provided
3392  here mainly for informational purposes or in the rare case that someone might find it useful.
3393 
3394  These will be set to 0 when returned by ma_context_enumerate_devices() or ma_context_get_devices().
3395  */
3396  ma_uint32 formatCount;
3397  ma_format formats[ma_format_count];
3398  ma_uint32 minChannels;
3399  ma_uint32 maxChannels;
3400  ma_uint32 minSampleRate;
3401  ma_uint32 maxSampleRate;
3402 
3403 
3404  /* Experimental. Don't use these right now. */
3405  ma_uint32 nativeDataFormatCount;
3406  struct
3407  {
3408  ma_format format; /* Sample format. If set to ma_format_unknown, all sample formats are supported. */
3409  ma_uint32 channels; /* If set to 0, all channels are supported. */
3410  ma_uint32 sampleRate; /* If set to 0, all sample rates are supported. */
3411  ma_uint32 flags; /* A combination of MA_DATA_FORMAT_FLAG_* flags. */
3412  } nativeDataFormats[/*ma_format_count * ma_standard_sample_rate_count * MA_MAX_CHANNELS*/ 64]; /* Not sure how big to make this. There can be *many* permutations for virtual devices which can support anything. */
3413 } ma_device_info;
3414 
3415 struct ma_device_config
3416 {
3423  ma_bool8 noPreZeroedOutputBuffer; /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to zero. */
3424  ma_bool8 noClip; /* When set to true, the contents of the output buffer passed into the data callback will be clipped after returning. Only applies when the playback sample format is f32. */
3427  void* pUserData;
3428  struct
3429  {
3431  struct
3432  {
3434  } linear;
3435  struct
3436  {
3437  int quality;
3438  } speex;
3439  } resampling;
3440  struct
3441  {
3442  const ma_device_id* pDeviceID;
3443  ma_format format;
3448  } playback;
3449  struct
3450  {
3451  const ma_device_id* pDeviceID;
3452  ma_format format;
3457  } capture;
3458 
3459  struct
3460  {
3461  ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */
3462  ma_bool8 noDefaultQualitySRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY. */
3463  ma_bool8 noAutoStreamRouting; /* Disables automatic stream routing. */
3464  ma_bool8 noHardwareOffloading; /* Disables WASAPI's hardware offloading feature. */
3465  } wasapi;
3466  struct
3467  {
3468  ma_bool32 noMMap; /* Disables MMap mode. */
3469  ma_bool32 noAutoFormat; /* Opens the ALSA device with SND_PCM_NO_AUTO_FORMAT. */
3470  ma_bool32 noAutoChannels; /* Opens the ALSA device with SND_PCM_NO_AUTO_CHANNELS. */
3471  ma_bool32 noAutoResample; /* Opens the ALSA device with SND_PCM_NO_AUTO_RESAMPLE. */
3472  } alsa;
3473  struct
3474  {
3475  const char* pStreamNamePlayback;
3476  const char* pStreamNameCapture;
3477  } pulse;
3478  struct
3479  {
3480  ma_bool32 allowNominalSampleRateChange; /* Desktop only. When enabled, allows changing of the sample rate at the operating system level. */
3481  } coreaudio;
3482  struct
3483  {
3486  } opensl;
3487  struct
3488  {
3492  } aaudio;
3493 };
3494 
3495 
3496 /*
3497 The callback for handling device enumeration. This is fired from `ma_context_enumerated_devices()`.
3498 
3499 
3500 Parameters
3501 ----------
3502 pContext (in)
3503  A pointer to the context performing the enumeration.
3504 
3505 deviceType (in)
3506  The type of the device being enumerated. This will always be either `ma_device_type_playback` or `ma_device_type_capture`.
3507 
3508 pInfo (in)
3509  A pointer to a `ma_device_info` containing the ID and name of the enumerated device. Note that this will not include detailed information about the device,
3510  only basic information (ID and name). The reason for this is that it would otherwise require opening the backend device to probe for the information which
3511  is too inefficient.
3512 
3513 pUserData (in)
3514  The user data pointer passed into `ma_context_enumerate_devices()`.
3515 */
3516 typedef ma_bool32 (* ma_enum_devices_callback_proc)(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData);
3517 
3518 
3519 /*
3520 Describes some basic details about a playback or capture device.
3521 */
3522 typedef struct
3523 {
3524  const ma_device_id* pDeviceID;
3525  ma_share_mode shareMode;
3526  ma_format format;
3527  ma_uint32 channels;
3528  ma_uint32 sampleRate;
3529  ma_channel channelMap[MA_MAX_CHANNELS];
3530  ma_uint32 periodSizeInFrames;
3531  ma_uint32 periodSizeInMilliseconds;
3532  ma_uint32 periodCount;
3534 
3535 /*
3536 These are the callbacks required to be implemented for a backend. These callbacks are grouped into two parts: context and device. There is one context
3537 to many devices. A device is created from a context.
3538 
3539 The general flow goes like this:
3540 
3541  1) A context is created with `onContextInit()`
3542  1a) Available devices can be enumerated with `onContextEnumerateDevices()` if required.
3543  1b) Detailed information about a device can be queried with `onContextGetDeviceInfo()` if required.
3544  2) A device is created from the context that was created in the first step using `onDeviceInit()`, and optionally a device ID that was
3545  selected from device enumeration via `onContextEnumerateDevices()`.
3546  3) A device is started or stopped with `onDeviceStart()` / `onDeviceStop()`
3547  4) Data is delivered to and from the device by the backend. This is always done based on the native format returned by the prior call
3548  to `onDeviceInit()`. Conversion between the device's native format and the format requested by the application will be handled by
3549  miniaudio internally.
3550 
3551 Initialization of the context is quite simple. You need to do any necessary initialization of internal objects and then output the
3552 callbacks defined in this structure.
3553 
3554 Once the context has been initialized you can initialize a device. Before doing so, however, the application may want to know which
3555 physical devices are available. This is where `onContextEnumerateDevices()` comes in. This is fairly simple. For each device, fire the
3556 given callback with, at a minimum, the basic information filled out in `ma_device_info`. When the callback returns `MA_FALSE`, enumeration
3557 needs to stop and the `onContextEnumerateDevices()` function return with a success code.
3558 
3559 Detailed device information can be retrieved from a device ID using `onContextGetDeviceInfo()`. This takes as input the device type and ID,
3560 and on output returns detailed information about the device in `ma_device_info`. The `onContextGetDeviceInfo()` callback must handle the
3561 case when the device ID is NULL, in which case information about the default device needs to be retrieved.
3562 
3563 Once the context has been created and the device ID retrieved (if using anything other than the default device), the device can be created.
3564 This is a little bit more complicated than initialization of the context due to it's more complicated configuration. When initializing a
3565 device, a duplex device may be requested. This means a separate data format needs to be specified for both playback and capture. On input,
3566 the data format is set to what the application wants. On output it's set to the native format which should match as closely as possible to
3567 the requested format. The conversion between the format requested by the application and the device's native format will be handled
3568 internally by miniaudio.
3569 
3570 On input, if the sample format is set to `ma_format_unknown`, the backend is free to use whatever sample format it desires, so long as it's
3571 supported by miniaudio. When the channel count is set to 0, the backend should use the device's native channel count. The same applies for
3572 sample rate. For the channel map, the default should be used when `ma_channel_map_blank()` returns true (all channels set to
3573 `MA_CHANNEL_NONE`). On input, the `periodSizeInFrames` or `periodSizeInMilliseconds` option should always be set. The backend should
3574 inspect both of these variables. If `periodSizeInFrames` is set, it should take priority, otherwise it needs to be derived from the period
3575 size in milliseconds (`periodSizeInMilliseconds`) and the sample rate, keeping in mind that the sample rate may be 0, in which case the
3576 sample rate will need to be determined before calculating the period size in frames. On output, all members of the `ma_device_data_format`
3577 object should be set to a valid value, except for `periodSizeInMilliseconds` which is optional (`periodSizeInFrames` *must* be set).
3578 
3579 Starting and stopping of the device is done with `onDeviceStart()` and `onDeviceStop()` and should be self-explanatory. If the backend uses
3580 asynchronous reading and writing, `onDeviceStart()` and `onDeviceStop()` should always be implemented.
3581 
3582 The handling of data delivery between the application and the device is the most complicated part of the process. To make this a bit
3583 easier, some helper callbacks are available. If the backend uses a blocking read/write style of API, the `onDeviceRead()` and
3584 `onDeviceWrite()` callbacks can optionally be implemented. These are blocking and work just like reading and writing from a file. If the
3585 backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within it's callback.
3586 This allows miniaudio to then process any necessary data conversion and then pass it to the miniaudio data callback.
3587 
3588 If the backend requires absolute flexibility with it's data delivery, it can optionally implement the `onDeviceDataLoop()` callback
3589 which will allow it to implement the logic that will run on the audio thread. This is much more advanced and is completely optional.
3590 
3591 The audio thread should run data delivery logic in a loop while `ma_device_get_state() == MA_STATE_STARTED` and no errors have been
3592 encounted. Do not start or stop the device here. That will be handled from outside the `onDeviceDataLoop()` callback.
3593 
3594 The invocation of the `onDeviceDataLoop()` callback will be handled by miniaudio. When you start the device, miniaudio will fire this
3595 callback. When the device is stopped, the `ma_device_get_state() == MA_STATE_STARTED` condition will fail and the loop will be terminated
3596 which will then fall through to the part that stops the device. For an example on how to implement the `onDeviceDataLoop()` callback,
3597 look at `ma_device_audio_thread__default_read_write()`. Implement the `onDeviceDataLoopWakeup()` callback if you need a mechanism to
3598 wake up the audio thread.
3599 */
3600 struct ma_backend_callbacks
3601 {
3602  ma_result (* onContextInit)(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks);
3603  ma_result (* onContextUninit)(ma_context* pContext);
3604  ma_result (* onContextEnumerateDevices)(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData);
3605  ma_result (* onContextGetDeviceInfo)(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo);
3606  ma_result (* onDeviceInit)(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture);
3607  ma_result (* onDeviceUninit)(ma_device* pDevice);
3608  ma_result (* onDeviceStart)(ma_device* pDevice);
3609  ma_result (* onDeviceStop)(ma_device* pDevice);
3610  ma_result (* onDeviceRead)(ma_device* pDevice, void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesRead);
3611  ma_result (* onDeviceWrite)(ma_device* pDevice, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten);
3612  ma_result (* onDeviceDataLoop)(ma_device* pDevice);
3614 };
3615 
3616 struct ma_context_config
3617 {
3618  ma_log_proc logCallback; /* Legacy logging callback. Will be removed in version 0.11. */
3619  ma_log* pLog;
3621  size_t threadStackSize;
3622  void* pUserData;
3624  struct
3625  {
3627  } alsa;
3628  struct
3629  {
3630  const char* pApplicationName;
3631  const char* pServerName;
3632  ma_bool32 tryAutoSpawn; /* Enables autospawning of the PulseAudio daemon if necessary. */
3633  } pulse;
3634  struct
3635  {
3638  ma_bool32 noAudioSessionActivate; /* iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:true] on initialization. */
3639  ma_bool32 noAudioSessionDeactivate; /* iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:false] on uninitialization. */
3640  } coreaudio;
3641  struct
3642  {
3643  const char* pClientName;
3645  } jack;
3647 };
3648 
3649 /* WASAPI specific structure for some commands which must run on a common thread due to bugs in WASAPI. */
3650 typedef struct
3651 {
3652  int code;
3653  ma_event* pEvent; /* This will be signalled when the event is complete. */
3654  union
3655  {
3656  struct
3657  {
3658  int _unused;
3659  } quit;
3660  struct
3661  {
3662  ma_device_type deviceType;
3663  void* pAudioClient;
3664  void** ppAudioClientService;
3665  ma_result* pResult; /* The result from creating the audio client service. */
3666  } createAudioClient;
3667  struct
3668  {
3669  ma_device* pDevice;
3670  ma_device_type deviceType;
3671  } releaseAudioClient;
3672  } data;
3674 
3675 struct ma_context
3676 {
3678  ma_backend backend; /* DirectSound, ALSA, etc. */
3679  ma_log* pLog;
3680  ma_log log; /* Only used if the log is owned by the context. The pLog member will be set to &log in this case. */
3681  ma_log_proc logCallback; /* Legacy callback. Will be removed in version 0.11. */
3683  size_t threadStackSize;
3684  void* pUserData;
3686  ma_mutex deviceEnumLock; /* Used to make ma_context_get_devices() thread safe. */
3687  ma_mutex deviceInfoLock; /* Used to make ma_context_get_device_info() thread safe. */
3688  ma_uint32 deviceInfoCapacity; /* Total capacity of pDeviceInfos. */
3691  ma_device_info* pDeviceInfos; /* Playback devices first, then capture. */
3692 
3693  union
3694  {
3695 #ifdef MA_SUPPORT_WASAPI
3696  struct
3697  {
3698  ma_thread commandThread;
3699  ma_mutex commandLock;
3700  ma_semaphore commandSem;
3701  ma_uint32 commandIndex;
3702  ma_uint32 commandCount;
3703  ma_context_command__wasapi commands[4];
3704  } wasapi;
3705 #endif
3706 #ifdef MA_SUPPORT_DSOUND
3707  struct
3708  {
3709  ma_handle hDSoundDLL;
3710  ma_proc DirectSoundCreate;
3711  ma_proc DirectSoundEnumerateA;
3712  ma_proc DirectSoundCaptureCreate;
3713  ma_proc DirectSoundCaptureEnumerateA;
3714  } dsound;
3715 #endif
3716 #ifdef MA_SUPPORT_WINMM
3717  struct
3718  {
3719  ma_handle hWinMM;
3720  ma_proc waveOutGetNumDevs;
3721  ma_proc waveOutGetDevCapsA;
3722  ma_proc waveOutOpen;
3723  ma_proc waveOutClose;
3724  ma_proc waveOutPrepareHeader;
3725  ma_proc waveOutUnprepareHeader;
3726  ma_proc waveOutWrite;
3727  ma_proc waveOutReset;
3728  ma_proc waveInGetNumDevs;
3729  ma_proc waveInGetDevCapsA;
3730  ma_proc waveInOpen;
3731  ma_proc waveInClose;
3732  ma_proc waveInPrepareHeader;
3733  ma_proc waveInUnprepareHeader;
3734  ma_proc waveInAddBuffer;
3735  ma_proc waveInStart;
3736  ma_proc waveInReset;
3737  } winmm;
3738 #endif
3739 #ifdef MA_SUPPORT_ALSA
3740  struct
3741  {
3742  ma_handle asoundSO;
3743  ma_proc snd_pcm_open;
3744  ma_proc snd_pcm_close;
3745  ma_proc snd_pcm_hw_params_sizeof;
3746  ma_proc snd_pcm_hw_params_any;
3747  ma_proc snd_pcm_hw_params_set_format;
3748  ma_proc snd_pcm_hw_params_set_format_first;
3749  ma_proc snd_pcm_hw_params_get_format_mask;
3750  ma_proc snd_pcm_hw_params_set_channels;
3751  ma_proc snd_pcm_hw_params_set_channels_near;
3752  ma_proc snd_pcm_hw_params_set_channels_minmax;
3753  ma_proc snd_pcm_hw_params_set_rate_resample;
3754  ma_proc snd_pcm_hw_params_set_rate;
3755  ma_proc snd_pcm_hw_params_set_rate_near;
3756  ma_proc snd_pcm_hw_params_set_buffer_size_near;
3757  ma_proc snd_pcm_hw_params_set_periods_near;
3758  ma_proc snd_pcm_hw_params_set_access;
3759  ma_proc snd_pcm_hw_params_get_format;
3760  ma_proc snd_pcm_hw_params_get_channels;
3761  ma_proc snd_pcm_hw_params_get_channels_min;
3762  ma_proc snd_pcm_hw_params_get_channels_max;
3763  ma_proc snd_pcm_hw_params_get_rate;
3764  ma_proc snd_pcm_hw_params_get_rate_min;
3765  ma_proc snd_pcm_hw_params_get_rate_max;
3766  ma_proc snd_pcm_hw_params_get_buffer_size;
3767  ma_proc snd_pcm_hw_params_get_periods;
3768  ma_proc snd_pcm_hw_params_get_access;
3769  ma_proc snd_pcm_hw_params_test_format;
3770  ma_proc snd_pcm_hw_params_test_channels;
3771  ma_proc snd_pcm_hw_params_test_rate;
3772  ma_proc snd_pcm_hw_params;
3773  ma_proc snd_pcm_sw_params_sizeof;
3774  ma_proc snd_pcm_sw_params_current;
3775  ma_proc snd_pcm_sw_params_get_boundary;
3776  ma_proc snd_pcm_sw_params_set_avail_min;
3777  ma_proc snd_pcm_sw_params_set_start_threshold;
3778  ma_proc snd_pcm_sw_params_set_stop_threshold;
3779  ma_proc snd_pcm_sw_params;
3780  ma_proc snd_pcm_format_mask_sizeof;
3781  ma_proc snd_pcm_format_mask_test;
3782  ma_proc snd_pcm_get_chmap;
3783  ma_proc snd_pcm_state;
3784  ma_proc snd_pcm_prepare;
3785  ma_proc snd_pcm_start;
3786  ma_proc snd_pcm_drop;
3787  ma_proc snd_pcm_drain;
3788  ma_proc snd_pcm_reset;
3789  ma_proc snd_device_name_hint;
3790  ma_proc snd_device_name_get_hint;
3791  ma_proc snd_card_get_index;
3792  ma_proc snd_device_name_free_hint;
3793  ma_proc snd_pcm_mmap_begin;
3794  ma_proc snd_pcm_mmap_commit;
3795  ma_proc snd_pcm_recover;
3796  ma_proc snd_pcm_readi;
3797  ma_proc snd_pcm_writei;
3798  ma_proc snd_pcm_avail;
3799  ma_proc snd_pcm_avail_update;
3800  ma_proc snd_pcm_wait;
3801  ma_proc snd_pcm_nonblock;
3802  ma_proc snd_pcm_info;
3803  ma_proc snd_pcm_info_sizeof;
3804  ma_proc snd_pcm_info_get_name;
3805  ma_proc snd_pcm_poll_descriptors;
3806  ma_proc snd_pcm_poll_descriptors_count;
3807  ma_proc snd_pcm_poll_descriptors_revents;
3808  ma_proc snd_config_update_free_global;
3809 
3810  ma_mutex internalDeviceEnumLock;
3811  ma_bool32 useVerboseDeviceEnumeration;
3812  } alsa;
3813 #endif
3814 #ifdef MA_SUPPORT_PULSEAUDIO
3815  struct
3816  {
3817  ma_handle pulseSO;
3818  ma_proc pa_mainloop_new;
3819  ma_proc pa_mainloop_free;
3820  ma_proc pa_mainloop_quit;
3821  ma_proc pa_mainloop_get_api;
3822  ma_proc pa_mainloop_iterate;
3823  ma_proc pa_mainloop_wakeup;
3824  ma_proc pa_threaded_mainloop_new;
3825  ma_proc pa_threaded_mainloop_free;
3826  ma_proc pa_threaded_mainloop_start;
3827  ma_proc pa_threaded_mainloop_stop;
3828  ma_proc pa_threaded_mainloop_lock;
3829  ma_proc pa_threaded_mainloop_unlock;
3830  ma_proc pa_threaded_mainloop_wait;
3831  ma_proc pa_threaded_mainloop_signal;
3832  ma_proc pa_threaded_mainloop_accept;
3833  ma_proc pa_threaded_mainloop_get_retval;
3834  ma_proc pa_threaded_mainloop_get_api;
3835  ma_proc pa_threaded_mainloop_in_thread;
3836  ma_proc pa_threaded_mainloop_set_name;
3837  ma_proc pa_context_new;
3838  ma_proc pa_context_unref;
3839  ma_proc pa_context_connect;
3840  ma_proc pa_context_disconnect;
3841  ma_proc pa_context_set_state_callback;
3842  ma_proc pa_context_get_state;
3843  ma_proc pa_context_get_sink_info_list;
3844  ma_proc pa_context_get_source_info_list;
3845  ma_proc pa_context_get_sink_info_by_name;
3846  ma_proc pa_context_get_source_info_by_name;
3847  ma_proc pa_operation_unref;
3848  ma_proc pa_operation_get_state;
3849  ma_proc pa_channel_map_init_extend;
3850  ma_proc pa_channel_map_valid;
3851  ma_proc pa_channel_map_compatible;
3852  ma_proc pa_stream_new;
3853  ma_proc pa_stream_unref;
3854  ma_proc pa_stream_connect_playback;
3855  ma_proc pa_stream_connect_record;
3856  ma_proc pa_stream_disconnect;
3857  ma_proc pa_stream_get_state;
3858  ma_proc pa_stream_get_sample_spec;
3859  ma_proc pa_stream_get_channel_map;
3860  ma_proc pa_stream_get_buffer_attr;
3861  ma_proc pa_stream_set_buffer_attr;
3862  ma_proc pa_stream_get_device_name;
3863  ma_proc pa_stream_set_write_callback;
3864  ma_proc pa_stream_set_read_callback;
3865  ma_proc pa_stream_set_suspended_callback;
3866  ma_proc pa_stream_is_suspended;
3867  ma_proc pa_stream_flush;
3868  ma_proc pa_stream_drain;
3869  ma_proc pa_stream_is_corked;
3870  ma_proc pa_stream_cork;
3871  ma_proc pa_stream_trigger;
3872  ma_proc pa_stream_begin_write;
3873  ma_proc pa_stream_write;
3874  ma_proc pa_stream_peek;
3875  ma_proc pa_stream_drop;
3876  ma_proc pa_stream_writable_size;
3877  ma_proc pa_stream_readable_size;
3878 
3879  /*pa_mainloop**/ ma_ptr pMainLoop;
3880  /*pa_context**/ ma_ptr pPulseContext;
3881  } pulse;
3882 #endif
3883 #ifdef MA_SUPPORT_JACK
3884  struct
3885  {
3886  ma_handle jackSO;
3887  ma_proc jack_client_open;
3888  ma_proc jack_client_close;
3889  ma_proc jack_client_name_size;
3890  ma_proc jack_set_process_callback;
3891  ma_proc jack_set_buffer_size_callback;
3892  ma_proc jack_on_shutdown;
3893  ma_proc jack_get_sample_rate;
3894  ma_proc jack_get_buffer_size;
3895  ma_proc jack_get_ports;
3896  ma_proc jack_activate;
3897  ma_proc jack_deactivate;
3898  ma_proc jack_connect;
3899  ma_proc jack_port_register;
3900  ma_proc jack_port_name;
3901  ma_proc jack_port_get_buffer;
3902  ma_proc jack_free;
3903 
3904  char* pClientName;
3905  ma_bool32 tryStartServer;
3906  } jack;
3907 #endif
3908 #ifdef MA_SUPPORT_COREAUDIO
3909  struct
3910  {
3911  ma_handle hCoreFoundation;
3912  ma_proc CFStringGetCString;
3913  ma_proc CFRelease;
3914 
3915  ma_handle hCoreAudio;
3916  ma_proc AudioObjectGetPropertyData;
3917  ma_proc AudioObjectGetPropertyDataSize;
3918  ma_proc AudioObjectSetPropertyData;
3919  ma_proc AudioObjectAddPropertyListener;
3920  ma_proc AudioObjectRemovePropertyListener;
3921 
3922  ma_handle hAudioUnit; /* Could possibly be set to AudioToolbox on later versions of macOS. */
3923  ma_proc AudioComponentFindNext;
3924  ma_proc AudioComponentInstanceDispose;
3925  ma_proc AudioComponentInstanceNew;
3926  ma_proc AudioOutputUnitStart;
3927  ma_proc AudioOutputUnitStop;
3928  ma_proc AudioUnitAddPropertyListener;
3929  ma_proc AudioUnitGetPropertyInfo;
3930  ma_proc AudioUnitGetProperty;
3931  ma_proc AudioUnitSetProperty;
3932  ma_proc AudioUnitInitialize;
3933  ma_proc AudioUnitRender;
3934 
3935  /*AudioComponent*/ ma_ptr component;
3936  ma_bool32 noAudioSessionDeactivate; /* For tracking whether or not the iOS audio session should be explicitly deactivated. Set from the config in ma_context_init__coreaudio(). */
3937  } coreaudio;
3938 #endif
3939 #ifdef MA_SUPPORT_SNDIO
3940  struct
3941  {
3942  ma_handle sndioSO;
3943  ma_proc sio_open;
3944  ma_proc sio_close;
3945  ma_proc sio_setpar;
3946  ma_proc sio_getpar;
3947  ma_proc sio_getcap;
3948  ma_proc sio_start;
3949  ma_proc sio_stop;
3950  ma_proc sio_read;
3951  ma_proc sio_write;
3952  ma_proc sio_onmove;
3953  ma_proc sio_nfds;
3954  ma_proc sio_pollfd;
3955  ma_proc sio_revents;
3956  ma_proc sio_eof;
3957  ma_proc sio_setvol;
3958  ma_proc sio_onvol;
3959  ma_proc sio_initpar;
3960  } sndio;
3961 #endif
3962 #ifdef MA_SUPPORT_AUDIO4
3963  struct
3964  {
3965  int _unused;
3966  } audio4;
3967 #endif
3968 #ifdef MA_SUPPORT_OSS
3969  struct
3970  {
3971  int versionMajor;
3972  int versionMinor;
3973  } oss;
3974 #endif
3975 #ifdef MA_SUPPORT_AAUDIO
3976  struct
3977  {
3978  ma_handle hAAudio; /* libaaudio.so */
3979  ma_proc AAudio_createStreamBuilder;
3980  ma_proc AAudioStreamBuilder_delete;
3981  ma_proc AAudioStreamBuilder_setDeviceId;
3982  ma_proc AAudioStreamBuilder_setDirection;
3983  ma_proc AAudioStreamBuilder_setSharingMode;
3984  ma_proc AAudioStreamBuilder_setFormat;
3985  ma_proc AAudioStreamBuilder_setChannelCount;
3986  ma_proc AAudioStreamBuilder_setSampleRate;
3987  ma_proc AAudioStreamBuilder_setBufferCapacityInFrames;
3988  ma_proc AAudioStreamBuilder_setFramesPerDataCallback;
3989  ma_proc AAudioStreamBuilder_setDataCallback;
3990  ma_proc AAudioStreamBuilder_setErrorCallback;
3991  ma_proc AAudioStreamBuilder_setPerformanceMode;
3992  ma_proc AAudioStreamBuilder_setUsage;
3993  ma_proc AAudioStreamBuilder_setContentType;
3994  ma_proc AAudioStreamBuilder_setInputPreset;
3995  ma_proc AAudioStreamBuilder_openStream;
3996  ma_proc AAudioStream_close;
3997  ma_proc AAudioStream_getState;
3998  ma_proc AAudioStream_waitForStateChange;
3999  ma_proc AAudioStream_getFormat;
4000  ma_proc AAudioStream_getChannelCount;
4001  ma_proc AAudioStream_getSampleRate;
4002  ma_proc AAudioStream_getBufferCapacityInFrames;
4003  ma_proc AAudioStream_getFramesPerDataCallback;
4004  ma_proc AAudioStream_getFramesPerBurst;
4005  ma_proc AAudioStream_requestStart;
4006  ma_proc AAudioStream_requestStop;
4007  } aaudio;
4008 #endif
4009 #ifdef MA_SUPPORT_OPENSL
4010  struct
4011  {
4012  ma_handle libOpenSLES;
4013  ma_handle SL_IID_ENGINE;
4014  ma_handle SL_IID_AUDIOIODEVICECAPABILITIES;
4015  ma_handle SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
4016  ma_handle SL_IID_RECORD;
4017  ma_handle SL_IID_PLAY;
4018  ma_handle SL_IID_OUTPUTMIX;
4019  ma_handle SL_IID_ANDROIDCONFIGURATION;
4020  ma_proc slCreateEngine;
4021  } opensl;
4022 #endif
4023 #ifdef MA_SUPPORT_WEBAUDIO
4024  struct
4025  {
4026  int _unused;
4027  } webaudio;
4028 #endif
4029 #ifdef MA_SUPPORT_NULL
4030  struct
4031  {
4032  int _unused;
4033  } null_backend;
4034 #endif
4035  };
4036 
4037  union
4038  {
4039 #ifdef MA_WIN32
4040  struct
4041  {
4042  /*HMODULE*/ ma_handle hOle32DLL;
4043  ma_proc CoInitializeEx;
4044  ma_proc CoUninitialize;
4045  ma_proc CoCreateInstance;
4046  ma_proc CoTaskMemFree;
4047  ma_proc PropVariantClear;
4048  ma_proc StringFromGUID2;
4049 
4050  /*HMODULE*/ ma_handle hUser32DLL;
4051  ma_proc GetForegroundWindow;
4052  ma_proc GetDesktopWindow;
4053 
4054  /*HMODULE*/ ma_handle hAdvapi32DLL;
4055  ma_proc RegOpenKeyExA;
4056  ma_proc RegCloseKey;
4057  ma_proc RegQueryValueExA;
4058  } win32;
4059 #endif
4060 #ifdef MA_POSIX
4061  struct
4062  {
4079  } posix;
4080 #endif
4081  int _unused;
4082  };
4083 };
4084 
4085 struct ma_device
4086 {
4090  MA_ATOMIC ma_uint32 state; /* The state of the device is variable and can change at any time on any thread. Must be used atomically. */
4091  ma_device_callback_proc onData; /* Set once at initialization time and should not be changed after. */
4092  ma_stop_proc onStop; /* Set once at initialization time and should not be changed after. */
4093  void* pUserData; /* Application defined data. */
4098  ma_thread thread;
4099  ma_result workResult; /* This is set by the worker thread after it's finished doing a job. */
4100  ma_bool8 isOwnerOfContext; /* When set to true, uninitializing the device will also uninitialize the context. Set to true when NULL is passed into ma_device_init(). */
4102  ma_bool8 noClip;
4103  MA_ATOMIC float masterVolumeFactor; /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
4104  ma_duplex_rb duplexRB; /* Intermediary buffer for duplex device on asynchronous backends. */
4105  struct
4106  {
4108  struct
4109  {
4111  } linear;
4112  struct
4113  {
4114  int quality;
4115  } speex;
4116  } resampling;
4117  struct
4118  {
4119  ma_device_id id; /* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
4120  char name[256]; /* Maybe temporary. Likely to be replaced with a query API. */
4121  ma_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */
4122  ma_format format;
4133  } playback;
4134  struct
4135  {
4136  ma_device_id id; /* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
4137  char name[256]; /* Maybe temporary. Likely to be replaced with a query API. */
4138  ma_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */
4139  ma_format format;
4150  } capture;
4151 
4152  union
4153  {
4154 #ifdef MA_SUPPORT_WASAPI
4155  struct
4156  {
4157  /*IAudioClient**/ ma_ptr pAudioClientPlayback;
4158  /*IAudioClient**/ ma_ptr pAudioClientCapture;
4159  /*IAudioRenderClient**/ ma_ptr pRenderClient;
4160  /*IAudioCaptureClient**/ ma_ptr pCaptureClient;
4161  /*IMMDeviceEnumerator**/ ma_ptr pDeviceEnumerator; /* Used for IMMNotificationClient notifications. Required for detecting default device changes. */
4162  ma_IMMNotificationClient notificationClient;
4163  /*HANDLE*/ ma_handle hEventPlayback; /* Auto reset. Initialized to signaled. */
4164  /*HANDLE*/ ma_handle hEventCapture; /* Auto reset. Initialized to unsignaled. */
4165  ma_uint32 actualPeriodSizeInFramesPlayback; /* Value from GetBufferSize(). internalPeriodSizeInFrames is not set to the _actual_ buffer size when low-latency shared mode is being used due to the way the IAudioClient3 API works. */
4166  ma_uint32 actualPeriodSizeInFramesCapture;
4167  ma_uint32 originalPeriodSizeInFrames;
4168  ma_uint32 originalPeriodSizeInMilliseconds;
4169  ma_uint32 originalPeriods;
4170  ma_performance_profile originalPerformanceProfile;
4171  ma_uint32 periodSizeInFramesPlayback;
4172  ma_uint32 periodSizeInFramesCapture;
4173  MA_ATOMIC ma_bool32 isStartedCapture; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */
4174  MA_ATOMIC ma_bool32 isStartedPlayback; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */
4175  ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */
4176  ma_bool8 noDefaultQualitySRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY. */
4177  ma_bool8 noHardwareOffloading;
4178  ma_bool8 allowCaptureAutoStreamRouting;
4179  ma_bool8 allowPlaybackAutoStreamRouting;
4180  ma_bool8 isDetachedPlayback;
4181  ma_bool8 isDetachedCapture;
4182  } wasapi;
4183 #endif
4184 #ifdef MA_SUPPORT_DSOUND
4185  struct
4186  {
4187  /*LPDIRECTSOUND*/ ma_ptr pPlayback;
4188  /*LPDIRECTSOUNDBUFFER*/ ma_ptr pPlaybackPrimaryBuffer;
4189  /*LPDIRECTSOUNDBUFFER*/ ma_ptr pPlaybackBuffer;
4190  /*LPDIRECTSOUNDCAPTURE*/ ma_ptr pCapture;
4191  /*LPDIRECTSOUNDCAPTUREBUFFER*/ ma_ptr pCaptureBuffer;
4192  } dsound;
4193 #endif
4194 #ifdef MA_SUPPORT_WINMM
4195  struct
4196  {
4197  /*HWAVEOUT*/ ma_handle hDevicePlayback;
4198  /*HWAVEIN*/ ma_handle hDeviceCapture;
4199  /*HANDLE*/ ma_handle hEventPlayback;
4200  /*HANDLE*/ ma_handle hEventCapture;
4201  ma_uint32 fragmentSizeInFrames;
4202  ma_uint32 iNextHeaderPlayback; /* [0,periods). Used as an index into pWAVEHDRPlayback. */
4203  ma_uint32 iNextHeaderCapture; /* [0,periods). Used as an index into pWAVEHDRCapture. */
4204  ma_uint32 headerFramesConsumedPlayback; /* The number of PCM frames consumed in the buffer in pWAVEHEADER[iNextHeader]. */
4205  ma_uint32 headerFramesConsumedCapture; /* ^^^ */
4206  /*WAVEHDR**/ ma_uint8* pWAVEHDRPlayback; /* One instantiation for each period. */
4207  /*WAVEHDR**/ ma_uint8* pWAVEHDRCapture; /* One instantiation for each period. */
4208  ma_uint8* pIntermediaryBufferPlayback;
4209  ma_uint8* pIntermediaryBufferCapture;
4210  ma_uint8* _pHeapData; /* Used internally and is used for the heap allocated data for the intermediary buffer and the WAVEHDR structures. */
4211  } winmm;
4212 #endif
4213 #ifdef MA_SUPPORT_ALSA
4214  struct
4215  {
4216  /*snd_pcm_t**/ ma_ptr pPCMPlayback;
4217  /*snd_pcm_t**/ ma_ptr pPCMCapture;
4218  /*struct pollfd**/ void* pPollDescriptorsPlayback;
4219  /*struct pollfd**/ void* pPollDescriptorsCapture;
4220  int pollDescriptorCountPlayback;
4221  int pollDescriptorCountCapture;
4222  int wakeupfdPlayback; /* eventfd for waking up from poll() when the playback device is stopped. */
4223  int wakeupfdCapture; /* eventfd for waking up from poll() when the capture device is stopped. */
4224  ma_bool8 isUsingMMapPlayback;
4225  ma_bool8 isUsingMMapCapture;
4226  } alsa;
4227 #endif
4228 #ifdef MA_SUPPORT_PULSEAUDIO
4229  struct
4230  {
4231  /*pa_stream**/ ma_ptr pStreamPlayback;
4232  /*pa_stream**/ ma_ptr pStreamCapture;
4233  } pulse;
4234 #endif
4235 #ifdef MA_SUPPORT_JACK
4236  struct
4237  {
4238  /*jack_client_t**/ ma_ptr pClient;
4239  /*jack_port_t**/ ma_ptr pPortsPlayback[MA_MAX_CHANNELS];
4240  /*jack_port_t**/ ma_ptr pPortsCapture[MA_MAX_CHANNELS];
4241  float* pIntermediaryBufferPlayback; /* Typed as a float because JACK is always floating point. */
4242  float* pIntermediaryBufferCapture;
4243  } jack;
4244 #endif
4245 #ifdef MA_SUPPORT_COREAUDIO
4246  struct
4247  {
4248  ma_uint32 deviceObjectIDPlayback;
4249  ma_uint32 deviceObjectIDCapture;
4250  /*AudioUnit*/ ma_ptr audioUnitPlayback;
4251  /*AudioUnit*/ ma_ptr audioUnitCapture;
4252  /*AudioBufferList**/ ma_ptr pAudioBufferList; /* Only used for input devices. */
4253  ma_uint32 audioBufferCapInFrames; /* Only used for input devices. The capacity in frames of each buffer in pAudioBufferList. */
4255  ma_uint32 originalPeriodSizeInFrames;
4256  ma_uint32 originalPeriodSizeInMilliseconds;
4257  ma_uint32 originalPeriods;
4258  ma_performance_profile originalPerformanceProfile;
4259  ma_bool32 isDefaultPlaybackDevice;
4260  ma_bool32 isDefaultCaptureDevice;
4261  ma_bool32 isSwitchingPlaybackDevice; /* <-- Set to true when the default device has changed and miniaudio is in the process of switching. */
4262  ma_bool32 isSwitchingCaptureDevice; /* <-- Set to true when the default device has changed and miniaudio is in the process of switching. */
4263  void* pRouteChangeHandler; /* Only used on mobile platforms. Obj-C object for handling route changes. */
4264  } coreaudio;
4265 #endif
4266 #ifdef MA_SUPPORT_SNDIO
4267  struct
4268  {
4269  ma_ptr handlePlayback;
4270  ma_ptr handleCapture;
4271  ma_bool32 isStartedPlayback;
4272  ma_bool32 isStartedCapture;
4273  } sndio;
4274 #endif
4275 #ifdef MA_SUPPORT_AUDIO4
4276  struct
4277  {
4278  int fdPlayback;
4279  int fdCapture;
4280  } audio4;
4281 #endif
4282 #ifdef MA_SUPPORT_OSS
4283  struct
4284  {
4285  int fdPlayback;
4286  int fdCapture;
4287  } oss;
4288 #endif
4289 #ifdef MA_SUPPORT_AAUDIO
4290  struct
4291  {
4292  /*AAudioStream**/ ma_ptr pStreamPlayback;
4293  /*AAudioStream**/ ma_ptr pStreamCapture;
4294  } aaudio;
4295 #endif
4296 #ifdef MA_SUPPORT_OPENSL
4297  struct
4298  {
4299  /*SLObjectItf*/ ma_ptr pOutputMixObj;
4300  /*SLOutputMixItf*/ ma_ptr pOutputMix;
4301  /*SLObjectItf*/ ma_ptr pAudioPlayerObj;
4302  /*SLPlayItf*/ ma_ptr pAudioPlayer;
4303  /*SLObjectItf*/ ma_ptr pAudioRecorderObj;
4304  /*SLRecordItf*/ ma_ptr pAudioRecorder;
4305  /*SLAndroidSimpleBufferQueueItf*/ ma_ptr pBufferQueuePlayback;
4306  /*SLAndroidSimpleBufferQueueItf*/ ma_ptr pBufferQueueCapture;
4307  ma_bool32 isDrainingCapture;
4308  ma_bool32 isDrainingPlayback;
4309  ma_uint32 currentBufferIndexPlayback;
4310  ma_uint32 currentBufferIndexCapture;
4311  ma_uint8* pBufferPlayback; /* This is malloc()'d and is used for storing audio data. Typed as ma_uint8 for easy offsetting. */
4312  ma_uint8* pBufferCapture;
4313  } opensl;
4314 #endif
4315 #ifdef MA_SUPPORT_WEBAUDIO
4316  struct
4317  {
4318  int indexPlayback; /* We use a factory on the JavaScript side to manage devices and use an index for JS/C interop. */
4319  int indexCapture;
4320  } webaudio;
4321 #endif
4322 #ifdef MA_SUPPORT_NULL
4323  struct
4324  {
4331  ma_timer timer;
4332  double priorRunTime;
4337  MA_ATOMIC ma_bool32 isStarted; /* Read and written by multiple threads. Must be used atomically, and must be 32-bit for compiler compatibility. */
4338  } null_device;
4339 #endif
4340  };
4341 };
4342 #if defined(_MSC_VER) && !defined(__clang__)
4343  #pragma warning(pop)
4344 #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
4345  #pragma GCC diagnostic pop /* For ISO C99 doesn't support unnamed structs/unions [-Wpedantic] */
4346 #endif
4347 
4348 /*
4349 Initializes a `ma_context_config` object.
4350 
4351 
4352 Return Value
4353 ------------
4354 A `ma_context_config` initialized to defaults.
4355 
4356 
4357 Remarks
4358 -------
4359 You must always use this to initialize the default state of the `ma_context_config` object. Not using this will result in your program breaking when miniaudio
4360 is updated and new members are added to `ma_context_config`. It also sets logical defaults.
4361 
4362 You can override members of the returned object by changing it's members directly.
4363 
4364 
4365 See Also
4366 --------
4367 ma_context_init()
4368 */
4370 
4371 /*
4372 Initializes a context.
4373 
4374 The context is used for selecting and initializing an appropriate backend and to represent the backend at a more global level than that of an individual
4375 device. There is one context to many devices, and a device is created from a context. A context is required to enumerate devices.
4376 
4377 
4378 Parameters
4379 ----------
4380 backends (in, optional)
4381  A list of backends to try initializing, in priority order. Can be NULL, in which case it uses default priority order.
4382 
4383 backendCount (in, optional)
4384  The number of items in `backend`. Ignored if `backend` is NULL.
4385 
4386 pConfig (in, optional)
4387  The context configuration.
4388 
4389 pContext (in)
4390  A pointer to the context object being initialized.
4391 
4392 
4393 Return Value
4394 ------------
4395 MA_SUCCESS if successful; any other error code otherwise.
4396 
4397 
4398 Thread Safety
4399 -------------
4400 Unsafe. Do not call this function across multiple threads as some backends read and write to global state.
4401 
4402 
4403 Remarks
4404 -------
4405 When `backends` is NULL, the default priority order will be used. Below is a list of backends in priority order:
4406 
4407  |-------------|-----------------------|--------------------------------------------------------|
4408  | Name | Enum Name | Supported Operating Systems |
4409  |-------------|-----------------------|--------------------------------------------------------|
4410  | WASAPI | ma_backend_wasapi | Windows Vista+ |
4411  | DirectSound | ma_backend_dsound | Windows XP+ |
4412  | WinMM | ma_backend_winmm | Windows XP+ (may work on older versions, but untested) |
4413  | Core Audio | ma_backend_coreaudio | macOS, iOS |
4414  | ALSA | ma_backend_alsa | Linux |
4415  | PulseAudio | ma_backend_pulseaudio | Cross Platform (disabled on Windows, BSD and Android) |
4416  | JACK | ma_backend_jack | Cross Platform (disabled on BSD and Android) |
4417  | sndio | ma_backend_sndio | OpenBSD |
4418  | audio(4) | ma_backend_audio4 | NetBSD, OpenBSD |
4419  | OSS | ma_backend_oss | FreeBSD |
4420  | AAudio | ma_backend_aaudio | Android 8+ |
4421  | OpenSL|ES | ma_backend_opensl | Android (API level 16+) |
4422  | Web Audio | ma_backend_webaudio | Web (via Emscripten) |
4423  | Null | ma_backend_null | Cross Platform (not used on Web) |
4424  |-------------|-----------------------|--------------------------------------------------------|
4425 
4426 The context can be configured via the `pConfig` argument. The config object is initialized with `ma_context_config_init()`. Individual configuration settings
4427 can then be set directly on the structure. Below are the members of the `ma_context_config` object.
4428 
4429  pLog
4430  A pointer to the `ma_log` to post log messages to. Can be NULL if the application does not
4431  require logging. See the `ma_log` API for details on how to use the logging system.
4432 
4433  threadPriority
4434  The desired priority to use for the audio thread. Allowable values include the following:
4435 
4436  |--------------------------------------|
4437  | Thread Priority |
4438  |--------------------------------------|
4439  | ma_thread_priority_idle |
4440  | ma_thread_priority_lowest |
4441  | ma_thread_priority_low |
4442  | ma_thread_priority_normal |
4443  | ma_thread_priority_high |
4444  | ma_thread_priority_highest (default) |
4445  | ma_thread_priority_realtime |
4446  | ma_thread_priority_default |
4447  |--------------------------------------|
4448 
4449  pUserData
4450  A pointer to application-defined data. This can be accessed from the context object directly such as `context.pUserData`.
4451 
4452  allocationCallbacks
4453  Structure containing custom allocation callbacks. Leaving this at defaults will cause it to use MA_MALLOC, MA_REALLOC and MA_FREE. These allocation
4454  callbacks will be used for anything tied to the context, including devices.
4455 
4456  alsa.useVerboseDeviceEnumeration
4457  ALSA will typically enumerate many different devices which can be intrusive and not user-friendly. To combat this, miniaudio will enumerate only unique
4458  card/device pairs by default. The problem with this is that you lose a bit of flexibility and control. Setting alsa.useVerboseDeviceEnumeration makes
4459  it so the ALSA backend includes all devices. Defaults to false.
4460 
4461  pulse.pApplicationName
4462  PulseAudio only. The application name to use when initializing the PulseAudio context with `pa_context_new()`.
4463 
4464  pulse.pServerName
4465  PulseAudio only. The name of the server to connect to with `pa_context_connect()`.
4466 
4467  pulse.tryAutoSpawn
4468  PulseAudio only. Whether or not to try automatically starting the PulseAudio daemon. Defaults to false. If you set this to true, keep in mind that
4469  miniaudio uses a trial and error method to find the most appropriate backend, and this will result in the PulseAudio daemon starting which may be
4470  intrusive for the end user.
4471 
4472  coreaudio.sessionCategory
4473  iOS only. The session category to use for the shared AudioSession instance. Below is a list of allowable values and their Core Audio equivalents.
4474 
4475  |-----------------------------------------|-------------------------------------|
4476  | miniaudio Token | Core Audio Token |
4477  |-----------------------------------------|-------------------------------------|
4478  | ma_ios_session_category_ambient | AVAudioSessionCategoryAmbient |
4479  | ma_ios_session_category_solo_ambient | AVAudioSessionCategorySoloAmbient |
4480  | ma_ios_session_category_playback | AVAudioSessionCategoryPlayback |
4481  | ma_ios_session_category_record | AVAudioSessionCategoryRecord |
4482  | ma_ios_session_category_play_and_record | AVAudioSessionCategoryPlayAndRecord |
4483  | ma_ios_session_category_multi_route | AVAudioSessionCategoryMultiRoute |
4484  | ma_ios_session_category_none | AVAudioSessionCategoryAmbient |
4485  | ma_ios_session_category_default | AVAudioSessionCategoryAmbient |
4486  |-----------------------------------------|-------------------------------------|
4487 
4488  coreaudio.sessionCategoryOptions
4489  iOS only. Session category options to use with the shared AudioSession instance. Below is a list of allowable values and their Core Audio equivalents.
4490 
4491  |---------------------------------------------------------------------------|------------------------------------------------------------------|
4492  | miniaudio Token | Core Audio Token |
4493  |---------------------------------------------------------------------------|------------------------------------------------------------------|
4494  | ma_ios_session_category_option_mix_with_others | AVAudioSessionCategoryOptionMixWithOthers |
4495  | ma_ios_session_category_option_duck_others | AVAudioSessionCategoryOptionDuckOthers |
4496  | ma_ios_session_category_option_allow_bluetooth | AVAudioSessionCategoryOptionAllowBluetooth |
4497  | ma_ios_session_category_option_default_to_speaker | AVAudioSessionCategoryOptionDefaultToSpeaker |
4498  | ma_ios_session_category_option_interrupt_spoken_audio_and_mix_with_others | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers |
4499  | ma_ios_session_category_option_allow_bluetooth_a2dp | AVAudioSessionCategoryOptionAllowBluetoothA2DP |
4500  | ma_ios_session_category_option_allow_air_play | AVAudioSessionCategoryOptionAllowAirPlay |
4501  |---------------------------------------------------------------------------|------------------------------------------------------------------|
4502 
4503  jack.pClientName
4504  The name of the client to pass to `jack_client_open()`.
4505 
4506  jack.tryStartServer
4507  Whether or not to try auto-starting the JACK server. Defaults to false.
4508 
4509 
4510 It is recommended that only a single context is active at any given time because it's a bulky data structure which performs run-time linking for the
4511 relevant backends every time it's initialized.
4512 
4513 The location of the context cannot change throughout it's lifetime. Consider allocating the `ma_context` object with `malloc()` if this is an issue. The
4514 reason for this is that a pointer to the context is stored in the `ma_device` structure.
4515 
4516 
4517 Example 1 - Default Initialization
4518 ----------------------------------
4519 The example below shows how to initialize the context using the default configuration.
4520 
4521 ```c
4522 ma_context context;
4523 ma_result result = ma_context_init(NULL, 0, NULL, &context);
4524 if (result != MA_SUCCESS) {
4525  // Error.
4526 }
4527 ```
4528 
4529 
4530 Example 2 - Custom Configuration
4531 --------------------------------
4532 The example below shows how to initialize the context using custom backend priorities and a custom configuration. In this hypothetical example, the program
4533 wants to prioritize ALSA over PulseAudio on Linux. They also want to avoid using the WinMM backend on Windows because it's latency is too high. They also
4534 want an error to be returned if no valid backend is available which they achieve by excluding the Null backend.
4535 
4536 For the configuration, the program wants to capture any log messages so they can, for example, route it to a log file and user interface.
4537 
4538 ```c
4539 ma_backend backends[] = {
4540  ma_backend_alsa,
4541  ma_backend_pulseaudio,
4542  ma_backend_wasapi,
4543  ma_backend_dsound
4544 };
4545 
4546 ma_context_config config = ma_context_config_init();
4547 config.logCallback = my_log_callback;
4548 config.pUserData = pMyUserData;
4549 
4550 ma_context context;
4551 ma_result result = ma_context_init(backends, sizeof(backends)/sizeof(backends[0]), &config, &context);
4552 if (result != MA_SUCCESS) {
4553  // Error.
4554  if (result == MA_NO_BACKEND) {
4555  // Couldn't find an appropriate backend.
4556  }
4557 }
4558 ```
4559 
4560 
4561 See Also
4562 --------
4563 ma_context_config_init()
4564 ma_context_uninit()
4565 */
4566 MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config* pConfig, ma_context* pContext);
4567 
4568 /*
4569 Uninitializes a context.
4570 
4571 
4572 Return Value
4573 ------------
4574 MA_SUCCESS if successful; any other error code otherwise.
4575 
4576 
4577 Thread Safety
4578 -------------
4579 Unsafe. Do not call this function across multiple threads as some backends read and write to global state.
4580 
4581 
4582 Remarks
4583 -------
4584 Results are undefined if you call this while any device created by this context is still active.
4585 
4586 
4587 See Also
4588 --------
4589 ma_context_init()
4590 */
4592 
4593 /*
4594 Retrieves the size of the ma_context object.
4595 
4596 This is mainly for the purpose of bindings to know how much memory to allocate.
4597 */
4598 MA_API size_t ma_context_sizeof(void);
4599 
4600 /*
4601 Retrieves a pointer to the log object associated with this context.
4602 
4603 
4604 Remarks
4605 -------
4606 Pass the returned pointer to `ma_log_post()`, `ma_log_postv()` or `ma_log_postf()` to post a log
4607 message.
4608 
4609 
4610 Return Value
4611 ------------
4612 A pointer to the `ma_log` object that the context uses to post log messages. If some error occurs,
4613 NULL will be returned.
4614 */
4616 
4617 /*
4618 Enumerates over every device (both playback and capture).
4619 
4620 This is a lower-level enumeration function to the easier to use `ma_context_get_devices()`. Use `ma_context_enumerate_devices()` if you would rather not incur
4621 an internal heap allocation, or it simply suits your code better.
4622 
4623 Note that this only retrieves the ID and name/description of the device. The reason for only retrieving basic information is that it would otherwise require
4624 opening the backend device in order to probe it for more detailed information which can be inefficient. Consider using `ma_context_get_device_info()` for this,
4625 but don't call it from within the enumeration callback.
4626 
4627 Returning false from the callback will stop enumeration. Returning true will continue enumeration.
4628 
4629 
4630 Parameters
4631 ----------
4632 pContext (in)
4633  A pointer to the context performing the enumeration.
4634 
4635 callback (in)
4636  The callback to fire for each enumerated device.
4637 
4638 pUserData (in)
4639  A pointer to application-defined data passed to the callback.
4640 
4641 
4642 Return Value
4643 ------------
4644 MA_SUCCESS if successful; any other error code otherwise.
4645 
4646 
4647 Thread Safety
4648 -------------
4649 Safe. This is guarded using a simple mutex lock.
4650 
4651 
4652 Remarks
4653 -------
4654 Do _not_ assume the first enumerated device of a given type is the default device.
4655 
4656 Some backends and platforms may only support default playback and capture devices.
4657 
4658 In general, you should not do anything complicated from within the callback. In particular, do not try initializing a device from within the callback. Also,
4659 do not try to call `ma_context_get_device_info()` from within the callback.
4660 
4661 Consider using `ma_context_get_devices()` for a simpler and safer API, albeit at the expense of an internal heap allocation.
4662 
4663 
4664 Example 1 - Simple Enumeration
4665 ------------------------------
4666 ma_bool32 ma_device_enum_callback(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData)
4667 {
4668  printf("Device Name: %s\n", pInfo->name);
4669  return MA_TRUE;
4670 }
4671 
4672 ma_result result = ma_context_enumerate_devices(&context, my_device_enum_callback, pMyUserData);
4673 if (result != MA_SUCCESS) {
4674  // Error.
4675 }
4676 
4677 
4678 See Also
4679 --------
4680 ma_context_get_devices()
4681 */
4683 
4684 /*
4685 Retrieves basic information about every active playback and/or capture device.
4686 
4687 This function will allocate memory internally for the device lists and return a pointer to them through the `ppPlaybackDeviceInfos` and `ppCaptureDeviceInfos`
4688 parameters. If you do not want to incur the overhead of these allocations consider using `ma_context_enumerate_devices()` which will instead use a callback.
4689 
4690 
4691 Parameters
4692 ----------
4693 pContext (in)
4694  A pointer to the context performing the enumeration.
4695 
4696 ppPlaybackDeviceInfos (out)
4697  A pointer to a pointer that will receive the address of a buffer containing the list of `ma_device_info` structures for playback devices.
4698 
4699 pPlaybackDeviceCount (out)
4700  A pointer to an unsigned integer that will receive the number of playback devices.
4701 
4702 ppCaptureDeviceInfos (out)
4703  A pointer to a pointer that will receive the address of a buffer containing the list of `ma_device_info` structures for capture devices.
4704 
4705 pCaptureDeviceCount (out)
4706  A pointer to an unsigned integer that will receive the number of capture devices.
4707 
4708 
4709 Return Value
4710 ------------
4711 MA_SUCCESS if successful; any other error code otherwise.
4712 
4713 
4714 Thread Safety
4715 -------------
4716 Unsafe. Since each call to this function invalidates the pointers from the previous call, you should not be calling this simultaneously across multiple
4717 threads. Instead, you need to make a copy of the returned data with your own higher level synchronization.
4718 
4719 
4720 Remarks
4721 -------
4722 It is _not_ safe to assume the first device in the list is the default device.
4723 
4724 You can pass in NULL for the playback or capture lists in which case they'll be ignored.
4725 
4726 The returned pointers will become invalid upon the next call this this function, or when the context is uninitialized. Do not free the returned pointers.
4727 
4728 
4729 See Also
4730 --------
4731 ma_context_get_devices()
4732 */
4733 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);
4734 
4735 /*
4736 Retrieves information about a device of the given type, with the specified ID and share mode.
4737 
4738 
4739 Parameters
4740 ----------
4741 pContext (in)
4742  A pointer to the context performing the query.
4743 
4744 deviceType (in)
4745  The type of the device being queried. Must be either `ma_device_type_playback` or `ma_device_type_capture`.
4746 
4747 pDeviceID (in)
4748  The ID of the device being queried.
4749 
4750 shareMode (in)
4751  The share mode to query for device capabilities. This should be set to whatever you're intending on using when initializing the device. If you're unsure,
4752  set this to `ma_share_mode_shared`.
4753 
4754 pDeviceInfo (out)
4755  A pointer to the `ma_device_info` structure that will receive the device information.
4756 
4757 
4758 Return Value
4759 ------------
4760 MA_SUCCESS if successful; any other error code otherwise.
4761 
4762 
4763 Thread Safety
4764 -------------
4765 Safe. This is guarded using a simple mutex lock.
4766 
4767 
4768 Remarks
4769 -------
4770 Do _not_ call this from within the `ma_context_enumerate_devices()` callback.
4771 
4772 It's possible for a device to have different information and capabilities depending on whether or not it's opened in shared or exclusive mode. For example, in
4773 shared mode, WASAPI always uses floating point samples for mixing, but in exclusive mode it can be anything. Therefore, this function allows you to specify
4774 which share mode you want information for. Note that not all backends and devices support shared or exclusive mode, in which case this function will fail if
4775 the requested share mode is unsupported.
4776 
4777 This leaves pDeviceInfo unmodified in the result of an error.
4778 */
4779 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);
4780 
4781 /*
4782 Determines if the given context supports loopback mode.
4783 
4784 
4785 Parameters
4786 ----------
4787 pContext (in)
4788  A pointer to the context getting queried.
4789 
4790 
4791 Return Value
4792 ------------
4793 MA_TRUE if the context supports loopback mode; MA_FALSE otherwise.
4794 */
4796 
4797 
4798 
4799 /*
4800 Initializes a device config with default settings.
4801 
4802 
4803 Parameters
4804 ----------
4805 deviceType (in)
4806  The type of the device this config is being initialized for. This must set to one of the following:
4807 
4808  |-------------------------|
4809  | Device Type |
4810  |-------------------------|
4811  | ma_device_type_playback |
4812  | ma_device_type_capture |
4813  | ma_device_type_duplex |
4814  | ma_device_type_loopback |
4815  |-------------------------|
4816 
4817 
4818 Return Value
4819 ------------
4820 A new device config object with default settings. You will typically want to adjust the config after this function returns. See remarks.
4821 
4822 
4823 Thread Safety
4824 -------------
4825 Safe.
4826 
4827 
4828 Callback Safety
4829 ---------------
4830 Safe, but don't try initializing a device in a callback.
4831 
4832 
4833 Remarks
4834 -------
4835 The returned config will be initialized to defaults. You will normally want to customize a few variables before initializing the device. See Example 1 for a
4836 typical configuration which sets the sample format, channel count, sample rate, data callback and user data. These are usually things you will want to change
4837 before initializing the device.
4838 
4839 See `ma_device_init()` for details on specific configuration options.
4840 
4841 
4842 Example 1 - Simple Configuration
4843 --------------------------------
4844 The example below is what a program will typically want to configure for each device at a minimum. Notice how `ma_device_config_init()` is called first, and
4845 then the returned object is modified directly. This is important because it ensures that your program continues to work as new configuration options are added
4846 to the `ma_device_config` structure.
4847 
4848 ```c
4849 ma_device_config config = ma_device_config_init(ma_device_type_playback);
4850 config.playback.format = ma_format_f32;
4851 config.playback.channels = 2;
4852 config.sampleRate = 48000;
4853 config.dataCallback = ma_data_callback;
4854 config.pUserData = pMyUserData;
4855 ```
4856 
4857 
4858 See Also
4859 --------
4860 ma_device_init()
4861 ma_device_init_ex()
4862 */
4864 
4865 
4866 /*
4867 Initializes a device.
4868 
4869 A device represents a physical audio device. The idea is you send or receive audio data from the device to either play it back through a speaker, or capture it
4870 from a microphone. Whether or not you should send or receive data from the device (or both) depends on the type of device you are initializing which can be
4871 playback, capture, full-duplex or loopback. (Note that loopback mode is only supported on select backends.) Sending and receiving audio data to and from the
4872 device is done via a callback which is fired by miniaudio at periodic time intervals.
4873 
4874 The frequency at which data is delivered to and from a device depends on the size of it's period. The size of the period can be defined in terms of PCM frames
4875 or milliseconds, whichever is more convenient. Generally speaking, the smaller the period, the lower the latency at the expense of higher CPU usage and
4876 increased risk of glitching due to the more frequent and granular data deliver intervals. The size of a period will depend on your requirements, but
4877 miniaudio's defaults should work fine for most scenarios. If you're building a game you should leave this fairly small, whereas if you're building a simple
4878 media player you can make it larger. Note that the period size you request is actually just a hint - miniaudio will tell the backend what you want, but the
4879 backend is ultimately responsible for what it gives you. You cannot assume you will get exactly what you ask for.
4880 
4881 When delivering data to and from a device you need to make sure it's in the correct format which you can set through the device configuration. You just set the
4882 format that you want to use and miniaudio will perform all of the necessary conversion for you internally. When delivering data to and from the callback you
4883 can assume the format is the same as what you requested when you initialized the device. See Remarks for more details on miniaudio's data conversion pipeline.
4884 
4885 
4886 Parameters
4887 ----------
4888 pContext (in, optional)
4889  A pointer to the context that owns the device. This can be null, in which case it creates a default context internally.
4890 
4891 pConfig (in)
4892  A pointer to the device configuration. Cannot be null. See remarks for details.
4893 
4894 pDevice (out)
4895  A pointer to the device object being initialized.
4896 
4897 
4898 Return Value
4899 ------------
4900 MA_SUCCESS if successful; any other error code otherwise.
4901 
4902 
4903 Thread Safety
4904 -------------
4905 Unsafe. It is not safe to call this function simultaneously for different devices because some backends depend on and mutate global state. The same applies to
4906 calling this at the same time as `ma_device_uninit()`.
4907 
4908 
4909 Callback Safety
4910 ---------------
4911 Unsafe. It is not safe to call this inside any callback.
4912 
4913 
4914 Remarks
4915 -------
4916 Setting `pContext` to NULL will result in miniaudio creating a default context internally and is equivalent to passing in a context initialized like so:
4917 
4918  ```c
4919  ma_context_init(NULL, 0, NULL, &context);
4920  ```
4921 
4922 Do not set `pContext` to NULL if you are needing to open multiple devices. You can, however, use NULL when initializing the first device, and then use
4923 device.pContext for the initialization of other devices.
4924 
4925 The device can be configured via the `pConfig` argument. The config object is initialized with `ma_device_config_init()`. Individual configuration settings can
4926 then be set directly on the structure. Below are the members of the `ma_device_config` object.
4927 
4928  deviceType
4929  Must be `ma_device_type_playback`, `ma_device_type_capture`, `ma_device_type_duplex` of `ma_device_type_loopback`.
4930 
4931  sampleRate
4932  The sample rate, in hertz. The most common sample rates are 48000 and 44100. Setting this to 0 will use the device's native sample rate.
4933 
4934  periodSizeInFrames
4935  The desired size of a period in PCM frames. If this is 0, `periodSizeInMilliseconds` will be used instead. If both are 0 the default buffer size will
4936  be used depending on the selected performance profile. This value affects latency. See below for details.
4937 
4938  periodSizeInMilliseconds
4939  The desired size of a period in milliseconds. If this is 0, `periodSizeInFrames` will be used instead. If both are 0 the default buffer size will be
4940  used depending on the selected performance profile. The value affects latency. See below for details.
4941 
4942  periods
4943  The number of periods making up the device's entire buffer. The total buffer size is `periodSizeInFrames` or `periodSizeInMilliseconds` multiplied by
4944  this value. This is just a hint as backends will be the ones who ultimately decide how your periods will be configured.
4945 
4946  performanceProfile
4947  A hint to miniaudio as to the performance requirements of your program. Can be either `ma_performance_profile_low_latency` (default) or
4948  `ma_performance_profile_conservative`. This mainly affects the size of default buffers and can usually be left at it's default value.
4949 
4950  noPreZeroedOutputBuffer
4951  When set to true, the contents of the output buffer passed into the data callback will be left undefined. When set to false (default), the contents of
4952  the output buffer will be cleared the zero. You can use this to avoid the overhead of zeroing out the buffer if you can guarantee that your data
4953  callback will write to every sample in the output buffer, or if you are doing your own clearing.
4954 
4955  noClip
4956  When set to true, the contents of the output buffer passed into the data callback will be clipped after returning. When set to false (default), the
4957  contents of the output buffer are left alone after returning and it will be left up to the backend itself to decide whether or not the clip. This only
4958  applies when the playback sample format is f32.
4959 
4960  dataCallback
4961  The callback to fire whenever data is ready to be delivered to or from the device.
4962 
4963  stopCallback
4964  The callback to fire whenever the device has stopped, either explicitly via `ma_device_stop()`, or implicitly due to things like the device being
4965  disconnected.
4966 
4967  pUserData
4968  The user data pointer to use with the device. You can access this directly from the device object like `device.pUserData`.
4969 
4970  resampling.algorithm
4971  The resampling algorithm to use when miniaudio needs to perform resampling between the rate specified by `sampleRate` and the device's native rate. The
4972  default value is `ma_resample_algorithm_linear`, and the quality can be configured with `resampling.linear.lpfOrder`.
4973 
4974  resampling.linear.lpfOrder
4975  The linear resampler applies a low-pass filter as part of it's procesing for anti-aliasing. This setting controls the order of the filter. The higher
4976  the value, the better the quality, in general. Setting this to 0 will disable low-pass filtering altogether. The maximum value is
4977  `MA_MAX_FILTER_ORDER`. The default value is `min(4, MA_MAX_FILTER_ORDER)`.
4978 
4979  playback.pDeviceID
4980  A pointer to a `ma_device_id` structure containing the ID of the playback device to initialize. Setting this NULL (default) will use the system's
4981  default playback device. Retrieve the device ID from the `ma_device_info` structure, which can be retrieved using device enumeration.
4982 
4983  playback.format
4984  The sample format to use for playback. When set to `ma_format_unknown` the device's native format will be used. This can be retrieved after
4985  initialization from the device object directly with `device.playback.format`.
4986 
4987  playback.channels
4988  The number of channels to use for playback. When set to 0 the device's native channel count will be used. This can be retrieved after initialization
4989  from the device object directly with `device.playback.channels`.
4990 
4991  playback.channelMap
4992  The channel map to use for playback. When left empty, the device's native channel map will be used. This can be retrieved after initialization from the
4993  device object direct with `device.playback.channelMap`.
4994 
4995  playback.shareMode
4996  The preferred share mode to use for playback. Can be either `ma_share_mode_shared` (default) or `ma_share_mode_exclusive`. Note that if you specify
4997  exclusive mode, but it's not supported by the backend, initialization will fail. You can then fall back to shared mode if desired by changing this to
4998  ma_share_mode_shared and reinitializing.
4999 
5000  capture.pDeviceID
5001  A pointer to a `ma_device_id` structure containing the ID of the capture device to initialize. Setting this NULL (default) will use the system's
5002  default capture device. Retrieve the device ID from the `ma_device_info` structure, which can be retrieved using device enumeration.
5003 
5004  capture.format
5005  The sample format to use for capture. When set to `ma_format_unknown` the device's native format will be used. This can be retrieved after
5006  initialization from the device object directly with `device.capture.format`.
5007 
5008  capture.channels
5009  The number of channels to use for capture. When set to 0 the device's native channel count will be used. This can be retrieved after initialization
5010  from the device object directly with `device.capture.channels`.
5011 
5012  capture.channelMap
5013  The channel map to use for capture. When left empty, the device's native channel map will be used. This can be retrieved after initialization from the
5014  device object direct with `device.capture.channelMap`.
5015 
5016  capture.shareMode
5017  The preferred share mode to use for capture. Can be either `ma_share_mode_shared` (default) or `ma_share_mode_exclusive`. Note that if you specify
5018  exclusive mode, but it's not supported by the backend, initialization will fail. You can then fall back to shared mode if desired by changing this to
5019  ma_share_mode_shared and reinitializing.
5020 
5021  wasapi.noAutoConvertSRC
5022  WASAPI only. When set to true, disables WASAPI's automatic resampling and forces the use of miniaudio's resampler. Defaults to false.
5023 
5024  wasapi.noDefaultQualitySRC
5025  WASAPI only. Only used when `wasapi.noAutoConvertSRC` is set to false. When set to true, disables the use of `AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY`.
5026  You should usually leave this set to false, which is the default.
5027 
5028  wasapi.noAutoStreamRouting
5029  WASAPI only. When set to true, disables automatic stream routing on the WASAPI backend. Defaults to false.
5030 
5031  wasapi.noHardwareOffloading
5032  WASAPI only. When set to true, disables the use of WASAPI's hardware offloading feature. Defaults to false.
5033 
5034  alsa.noMMap
5035  ALSA only. When set to true, disables MMap mode. Defaults to false.
5036 
5037  alsa.noAutoFormat
5038  ALSA only. When set to true, disables ALSA's automatic format conversion by including the SND_PCM_NO_AUTO_FORMAT flag. Defaults to false.
5039 
5040  alsa.noAutoChannels
5041  ALSA only. When set to true, disables ALSA's automatic channel conversion by including the SND_PCM_NO_AUTO_CHANNELS flag. Defaults to false.
5042 
5043  alsa.noAutoResample
5044  ALSA only. When set to true, disables ALSA's automatic resampling by including the SND_PCM_NO_AUTO_RESAMPLE flag. Defaults to false.
5045 
5046  pulse.pStreamNamePlayback
5047  PulseAudio only. Sets the stream name for playback.
5048 
5049  pulse.pStreamNameCapture
5050  PulseAudio only. Sets the stream name for capture.
5051 
5052  coreaudio.allowNominalSampleRateChange
5053  Core Audio only. Desktop only. When enabled, allows the sample rate of the device to be changed at the operating system level. This
5054  is disabled by default in order to prevent intrusive changes to the user's system. This is useful if you want to use a sample rate
5055  that is known to be natively supported by the hardware thereby avoiding the cost of resampling. When set to true, miniaudio will
5056  find the closest match between the sample rate requested in the device config and the sample rates natively supported by the
5057  hardware. When set to false, the sample rate currently set by the operating system will always be used.
5058 
5059 
5060 Once initialized, the device's config is immutable. If you need to change the config you will need to initialize a new device.
5061 
5062 After initializing the device it will be in a stopped state. To start it, use `ma_device_start()`.
5063 
5064 If both `periodSizeInFrames` and `periodSizeInMilliseconds` are set to zero, it will default to `MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY` or
5065 `MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE`, depending on whether or not `performanceProfile` is set to `ma_performance_profile_low_latency` or
5066 `ma_performance_profile_conservative`.
5067 
5068 If you request exclusive mode and the backend does not support it an error will be returned. For robustness, you may want to first try initializing the device
5069 in exclusive mode, and then fall back to shared mode if required. Alternatively you can just request shared mode (the default if you leave it unset in the
5070 config) which is the most reliable option. Some backends do not have a practical way of choosing whether or not the device should be exclusive or not (ALSA,
5071 for example) in which case it just acts as a hint. Unless you have special requirements you should try avoiding exclusive mode as it's intrusive to the user.
5072 Starting with Windows 10, miniaudio will use low-latency shared mode where possible which may make exclusive mode unnecessary.
5073 
5074 When sending or receiving data to/from a device, miniaudio will internally perform a format conversion to convert between the format specified by the config
5075 and the format used internally by the backend. If you pass in 0 for the sample format, channel count, sample rate _and_ channel map, data transmission will run
5076 on an optimized pass-through fast path. You can retrieve the format, channel count and sample rate by inspecting the `playback/capture.format`,
5077 `playback/capture.channels` and `sampleRate` members of the device object.
5078 
5079 When compiling for UWP you must ensure you call this function on the main UI thread because the operating system may need to present the user with a message
5080 asking for permissions. Please refer to the official documentation for ActivateAudioInterfaceAsync() for more information.
5081 
5082 ALSA Specific: When initializing the default device, requesting shared mode will try using the "dmix" device for playback and the "dsnoop" device for capture.
5083 If these fail it will try falling back to the "hw" device.
5084 
5085 
5086 Example 1 - Simple Initialization
5087 ---------------------------------
5088 This example shows how to initialize a simple playback device using a standard configuration. If you are just needing to do simple playback from the default
5089 playback device this is usually all you need.
5090 
5091 ```c
5092 ma_device_config config = ma_device_config_init(ma_device_type_playback);
5093 config.playback.format = ma_format_f32;
5094 config.playback.channels = 2;
5095 config.sampleRate = 48000;
5096 config.dataCallback = ma_data_callback;
5097 config.pMyUserData = pMyUserData;
5098 
5099 ma_device device;
5100 ma_result result = ma_device_init(NULL, &config, &device);
5101 if (result != MA_SUCCESS) {
5102  // Error
5103 }
5104 ```
5105 
5106 
5107 Example 2 - Advanced Initialization
5108 -----------------------------------
5109 This example shows how you might do some more advanced initialization. In this hypothetical example we want to control the latency by setting the buffer size
5110 and period count. We also want to allow the user to be able to choose which device to output from which means we need a context so we can perform device
5111 enumeration.
5112 
5113 ```c
5114 ma_context context;
5115 ma_result result = ma_context_init(NULL, 0, NULL, &context);
5116 if (result != MA_SUCCESS) {
5117  // Error
5118 }
5119 
5120 ma_device_info* pPlaybackDeviceInfos;
5121 ma_uint32 playbackDeviceCount;
5122 result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, NULL, NULL);
5123 if (result != MA_SUCCESS) {
5124  // Error
5125 }
5126 
5127 // ... choose a device from pPlaybackDeviceInfos ...
5128 
5129 ma_device_config config = ma_device_config_init(ma_device_type_playback);
5130 config.playback.pDeviceID = pMyChosenDeviceID; // <-- Get this from the `id` member of one of the `ma_device_info` objects returned by ma_context_get_devices().
5131 config.playback.format = ma_format_f32;
5132 config.playback.channels = 2;
5133 config.sampleRate = 48000;
5134 config.dataCallback = ma_data_callback;
5135 config.pUserData = pMyUserData;
5136 config.periodSizeInMilliseconds = 10;
5137 config.periods = 3;
5138 
5139 ma_device device;
5140 result = ma_device_init(&context, &config, &device);
5141 if (result != MA_SUCCESS) {
5142  // Error
5143 }
5144 ```
5145 
5146 
5147 See Also
5148 --------
5149 ma_device_config_init()
5150 ma_device_uninit()
5151 ma_device_start()
5152 ma_context_init()
5153 ma_context_get_devices()
5154 ma_context_enumerate_devices()
5155 */
5156 MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice);
5157 
5158 /*
5159 Initializes a device without a context, with extra parameters for controlling the configuration of the internal self-managed context.
5160 
5161 This is the same as `ma_device_init()`, only instead of a context being passed in, the parameters from `ma_context_init()` are passed in instead. This function
5162 allows you to configure the internally created context.
5163 
5164 
5165 Parameters
5166 ----------
5167 backends (in, optional)
5168  A list of backends to try initializing, in priority order. Can be NULL, in which case it uses default priority order.
5169 
5170 backendCount (in, optional)
5171  The number of items in `backend`. Ignored if `backend` is NULL.
5172 
5173 pContextConfig (in, optional)
5174  The context configuration.
5175 
5176 pConfig (in)
5177  A pointer to the device configuration. Cannot be null. See remarks for details.
5178 
5179 pDevice (out)
5180  A pointer to the device object being initialized.
5181 
5182 
5183 Return Value
5184 ------------
5185 MA_SUCCESS if successful; any other error code otherwise.
5186 
5187 
5188 Thread Safety
5189 -------------
5190 Unsafe. It is not safe to call this function simultaneously for different devices because some backends depend on and mutate global state. The same applies to
5191 calling this at the same time as `ma_device_uninit()`.
5192 
5193 
5194 Callback Safety
5195 ---------------
5196 Unsafe. It is not safe to call this inside any callback.
5197 
5198 
5199 Remarks
5200 -------
5201 You only need to use this function if you want to configure the context differently to it's defaults. You should never use this function if you want to manage
5202 your own context.
5203 
5204 See the documentation for `ma_context_init()` for information on the different context configuration options.
5205 
5206 
5207 See Also
5208 --------
5209 ma_device_init()
5210 ma_device_uninit()
5211 ma_device_config_init()
5212 ma_context_init()
5213 */
5214 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);
5215 
5216 /*
5217 Uninitializes a device.
5218 
5219 This will explicitly stop the device. You do not need to call `ma_device_stop()` beforehand, but it's harmless if you do.
5220 
5221 
5222 Parameters
5223 ----------
5224 pDevice (in)
5225  A pointer to the device to stop.
5226 
5227 
5228 Return Value
5229 ------------
5230 Nothing
5231 
5232 
5233 Thread Safety
5234 -------------
5235 Unsafe. As soon as this API is called the device should be considered undefined.
5236 
5237 
5238 Callback Safety
5239 ---------------
5240 Unsafe. It is not safe to call this inside any callback. Doing this will result in a deadlock.
5241 
5242 
5243 See Also
5244 --------
5245 ma_device_init()
5246 ma_device_stop()
5247 */
5248 MA_API void ma_device_uninit(ma_device* pDevice);
5249 
5250 
5251 /*
5252 Retrieves a pointer to the context that owns the given device.
5253 */
5255 
5256 /*
5257 Helper function for retrieving the log object associated with the context that owns this device.
5258 */
5260 
5261 
5262 /*
5263 Starts the device. For playback devices this begins playback. For capture devices it begins recording.
5264 
5265 Use `ma_device_stop()` to stop the device.
5266 
5267 
5268 Parameters
5269 ----------
5270 pDevice (in)
5271  A pointer to the device to start.
5272 
5273 
5274 Return Value
5275 ------------
5276 MA_SUCCESS if successful; any other error code otherwise.
5277 
5278 
5279 Thread Safety
5280 -------------
5281 Safe. It's safe to call this from any thread with the exception of the callback thread.
5282 
5283 
5284 Callback Safety
5285 ---------------
5286 Unsafe. It is not safe to call this inside any callback.
5287 
5288 
5289 Remarks
5290 -------
5291 For a playback device, this will retrieve an initial chunk of audio data from the client before returning. The reason for this is to ensure there is valid
5292 audio data in the buffer, which needs to be done before the device begins playback.
5293 
5294 This API waits until the backend device has been started for real by the worker thread. It also waits on a mutex for thread-safety.
5295 
5296 Do not call this in any callback.
5297 
5298 
5299 See Also
5300 --------
5301 ma_device_stop()
5302 */
5304 
5305 /*
5306 Stops the device. For playback devices this stops playback. For capture devices it stops recording.
5307 
5308 Use `ma_device_start()` to start the device again.
5309 
5310 
5311 Parameters
5312 ----------
5313 pDevice (in)
5314  A pointer to the device to stop.
5315 
5316 
5317 Return Value
5318 ------------
5319 MA_SUCCESS if successful; any other error code otherwise.
5320 
5321 
5322 Thread Safety
5323 -------------
5324 Safe. It's safe to call this from any thread with the exception of the callback thread.
5325 
5326 
5327 Callback Safety
5328 ---------------
5329 Unsafe. It is not safe to call this inside any callback. Doing this will result in a deadlock.
5330 
5331 
5332 Remarks
5333 -------
5334 This API needs to wait on the worker thread to stop the backend device properly before returning. It also waits on a mutex for thread-safety. In addition, some
5335 backends need to wait for the device to finish playback/recording of the current fragment which can take some time (usually proportionate to the buffer size
5336 that was specified at initialization time).
5337 
5338 Backends are required to either pause the stream in-place or drain the buffer if pausing is not possible. The reason for this is that stopping the device and
5339 the resuming it with ma_device_start() (which you might do when your program loses focus) may result in a situation where those samples are never output to the
5340 speakers or received from the microphone which can in turn result in de-syncs.
5341 
5342 Do not call this in any callback.
5343 
5344 This will be called implicitly by `ma_device_uninit()`.
5345 
5346 
5347 See Also
5348 --------
5349 ma_device_start()
5350 */
5352 
5353 /*
5354 Determines whether or not the device is started.
5355 
5356 
5357 Parameters
5358 ----------
5359 pDevice (in)
5360  A pointer to the device whose start state is being retrieved.
5361 
5362 
5363 Return Value
5364 ------------
5365 True if the device is started, false otherwise.
5366 
5367 
5368 Thread Safety
5369 -------------
5370 Safe. If another thread calls `ma_device_start()` or `ma_device_stop()` at this same time as this function is called, there's a very small chance the return
5371 value will be out of sync.
5372 
5373 
5374 Callback Safety
5375 ---------------
5376 Safe. This is implemented as a simple accessor.
5377 
5378 
5379 See Also
5380 --------
5381 ma_device_start()
5382 ma_device_stop()
5383 */
5385 
5386 
5387 /*
5388 Retrieves the state of the device.
5389 
5390 
5391 Parameters
5392 ----------
5393 pDevice (in)
5394  A pointer to the device whose state is being retrieved.
5395 
5396 
5397 Return Value
5398 ------------
5399 The current state of the device. The return value will be one of the following:
5400 
5401  +------------------------+------------------------------------------------------------------------------+
5402  | MA_STATE_UNINITIALIZED | Will only be returned if the device is in the middle of initialization. |
5403  +------------------------+------------------------------------------------------------------------------+
5404  | MA_STATE_STOPPED | The device is stopped. The initial state of the device after initialization. |
5405  +------------------------+------------------------------------------------------------------------------+
5406  | MA_STATE_STARTED | The device started and requesting and/or delivering audio data. |
5407  +------------------------+------------------------------------------------------------------------------+
5408  | MA_STATE_STARTING | The device is in the process of starting. |
5409  +------------------------+------------------------------------------------------------------------------+
5410  | MA_STATE_STOPPING | The device is in the process of stopping. |
5411  +------------------------+------------------------------------------------------------------------------+
5412 
5413 
5414 Thread Safety
5415 -------------
5416 Safe. This is implemented as a simple accessor. Note that if the device is started or stopped at the same time as this function is called,
5417 there's a possibility the return value could be out of sync. See remarks.
5418 
5419 
5420 Callback Safety
5421 ---------------
5422 Safe. This is implemented as a simple accessor.
5423 
5424 
5425 Remarks
5426 -------
5427 The general flow of a devices state goes like this:
5428 
5429  ```
5430  ma_device_init() -> MA_STATE_UNINITIALIZED -> MA_STATE_STOPPED
5431  ma_device_start() -> MA_STATE_STARTING -> MA_STATE_STARTED
5432  ma_device_stop() -> MA_STATE_STOPPING -> MA_STATE_STOPPED
5433  ```
5434 
5435 When the state of the device is changed with `ma_device_start()` or `ma_device_stop()` at this same time as this function is called, the
5436 value returned by this function could potentially be out of sync. If this is significant to your program you need to implement your own
5437 synchronization.
5438 */
5440 
5441 
5442 /*
5443 Sets the master volume factor for the device.
5444 
5445 The volume factor must be between 0 (silence) and 1 (full volume). Use `ma_device_set_master_gain_db()` to use decibel notation, where 0 is full volume and
5446 values less than 0 decreases the volume.
5447 
5448 
5449 Parameters
5450 ----------
5451 pDevice (in)
5452  A pointer to the device whose volume is being set.
5453 
5454 volume (in)
5455  The new volume factor. Must be within the range of [0, 1].
5456 
5457 
5458 Return Value
5459 ------------
5460 MA_SUCCESS if the volume was set successfully.
5461 MA_INVALID_ARGS if pDevice is NULL.
5462 MA_INVALID_ARGS if the volume factor is not within the range of [0, 1].
5463 
5464 
5465 Thread Safety
5466 -------------
5467 Safe. This just sets a local member of the device object.
5468 
5469 
5470 Callback Safety
5471 ---------------
5472 Safe. If you set the volume in the data callback, that data written to the output buffer will have the new volume applied.
5473 
5474 
5475 Remarks
5476 -------
5477 This applies the volume factor across all channels.
5478 
5479 This does not change the operating system's volume. It only affects the volume for the given `ma_device` object's audio stream.
5480 
5481 
5482 See Also
5483 --------
5484 ma_device_get_master_volume()
5485 ma_device_set_master_volume_gain_db()
5486 ma_device_get_master_volume_gain_db()
5487 */
5488 MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume);
5489 
5490 /*
5491 Retrieves the master volume factor for the device.
5492 
5493 
5494 Parameters
5495 ----------
5496 pDevice (in)
5497  A pointer to the device whose volume factor is being retrieved.
5498 
5499 pVolume (in)
5500  A pointer to the variable that will receive the volume factor. The returned value will be in the range of [0, 1].
5501 
5502 
5503 Return Value
5504 ------------
5505 MA_SUCCESS if successful.
5506 MA_INVALID_ARGS if pDevice is NULL.
5507 MA_INVALID_ARGS if pVolume is NULL.
5508 
5509 
5510 Thread Safety
5511 -------------
5512 Safe. This just a simple member retrieval.
5513 
5514 
5515 Callback Safety
5516 ---------------
5517 Safe.
5518 
5519 
5520 Remarks
5521 -------
5522 If an error occurs, `*pVolume` will be set to 0.
5523 
5524 
5525 See Also
5526 --------
5527 ma_device_set_master_volume()
5528 ma_device_set_master_volume_gain_db()
5529 ma_device_get_master_volume_gain_db()
5530 */
5531 MA_API ma_result ma_device_get_master_volume(ma_device* pDevice, float* pVolume);
5532 
5533 /*
5534 Sets the master volume for the device as gain in decibels.
5535 
5536 A gain of 0 is full volume, whereas a gain of < 0 will decrease the volume.
5537 
5538 
5539 Parameters
5540 ----------
5541 pDevice (in)
5542  A pointer to the device whose gain is being set.
5543 
5544 gainDB (in)
5545  The new volume as gain in decibels. Must be less than or equal to 0, where 0 is full volume and anything less than 0 decreases the volume.
5546 
5547 
5548 Return Value
5549 ------------
5550 MA_SUCCESS if the volume was set successfully.
5551 MA_INVALID_ARGS if pDevice is NULL.
5552 MA_INVALID_ARGS if the gain is > 0.
5553 
5554 
5555 Thread Safety
5556 -------------
5557 Safe. This just sets a local member of the device object.
5558 
5559 
5560 Callback Safety
5561 ---------------
5562 Safe. If you set the volume in the data callback, that data written to the output buffer will have the new volume applied.
5563 
5564 
5565 Remarks
5566 -------
5567 This applies the gain across all channels.
5568 
5569 This does not change the operating system's volume. It only affects the volume for the given `ma_device` object's audio stream.
5570 
5571 
5572 See Also
5573 --------
5574 ma_device_get_master_volume_gain_db()
5575 ma_device_set_master_volume()
5576 ma_device_get_master_volume()
5577 */
5578 MA_API ma_result ma_device_set_master_gain_db(ma_device* pDevice, float gainDB);
5579 
5580 /*
5581 Retrieves the master gain in decibels.
5582 
5583 
5584 Parameters
5585 ----------
5586 pDevice (in)
5587  A pointer to the device whose gain is being retrieved.
5588 
5589 pGainDB (in)
5590  A pointer to the variable that will receive the gain in decibels. The returned value will be <= 0.
5591 
5592 
5593 Return Value
5594 ------------
5595 MA_SUCCESS if successful.
5596 MA_INVALID_ARGS if pDevice is NULL.
5597 MA_INVALID_ARGS if pGainDB is NULL.
5598 
5599 
5600 Thread Safety
5601 -------------
5602 Safe. This just a simple member retrieval.
5603 
5604 
5605 Callback Safety
5606 ---------------
5607 Safe.
5608 
5609 
5610 Remarks
5611 -------
5612 If an error occurs, `*pGainDB` will be set to 0.
5613 
5614 
5615 See Also
5616 --------
5617 ma_device_set_master_volume_gain_db()
5618 ma_device_set_master_volume()
5619 ma_device_get_master_volume()
5620 */
5621 MA_API ma_result ma_device_get_master_gain_db(ma_device* pDevice, float* pGainDB);
5622 
5623 
5624 /*
5625 Called from the data callback of asynchronous backends to allow miniaudio to process the data and fire the miniaudio data callback.
5626 
5627 
5628 Parameters
5629 ----------
5630 pDevice (in)
5631  A pointer to device whose processing the data callback.
5632 
5633 pOutput (out)
5634  A pointer to the buffer that will receive the output PCM frame data. On a playback device this must not be NULL. On a duplex device
5635  this can be NULL, in which case pInput must not be NULL.
5636 
5637 pInput (in)
5638  A pointer to the buffer containing input PCM frame data. On a capture device this must not be NULL. On a duplex device this can be
5639  NULL, in which case `pOutput` must not be NULL.
5640 
5641 frameCount (in)
5642  The number of frames being processed.
5643 
5644 
5645 Return Value
5646 ------------
5647 MA_SUCCESS if successful; any other result code otherwise.
5648 
5649 
5650 Thread Safety
5651 -------------
5652 This function should only ever be called from the internal data callback of the backend. It is safe to call this simultaneously between a
5653 playback and capture device in duplex setups.
5654 
5655 
5656 Callback Safety
5657 ---------------
5658 Do not call this from the miniaudio data callback. It should only ever be called from the internal data callback of the backend.
5659 
5660 
5661 Remarks
5662 -------
5663 If both `pOutput` and `pInput` are NULL, and error will be returned. In duplex scenarios, both `pOutput` and `pInput` can be non-NULL, in
5664 which case `pInput` will be processed first, followed by `pOutput`.
5665 
5666 If you are implementing a custom backend, and that backend uses a callback for data delivery, you'll need to call this from inside that
5667 callback.
5668 */
5669 MA_API ma_result ma_device_handle_backend_data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
5670 
5671 
5672 /*
5673 Calculates an appropriate buffer size from a descriptor, native sample rate and performance profile.
5674 
5675 This function is used by backends for helping determine an appropriately sized buffer to use with
5676 the device depending on the values of `periodSizeInFrames` and `periodSizeInMilliseconds` in the
5677 `pDescriptor` object. Since buffer size calculations based on time depends on the sample rate, a
5678 best guess at the device's native sample rate is also required which is where `nativeSampleRate`
5679 comes in. In addition, the performance profile is also needed for cases where both the period size
5680 in frames and milliseconds are both zero.
5681 
5682 
5683 Parameters
5684 ----------
5685 pDescriptor (in)
5686  A pointer to device descriptor whose `periodSizeInFrames` and `periodSizeInMilliseconds` members
5687  will be used for the calculation of the buffer size.
5688 
5689 nativeSampleRate (in)
5690  The device's native sample rate. This is only ever used when the `periodSizeInFrames` member of
5691  `pDescriptor` is zero. In this case, `periodSizeInMilliseconds` will be used instead, in which
5692  case a sample rate is required to convert to a size in frames.
5693 
5694 performanceProfile (in)
5695  When both the `periodSizeInFrames` and `periodSizeInMilliseconds` members of `pDescriptor` are
5696  zero, miniaudio will fall back to a buffer size based on the performance profile. The profile
5697  to use for this calculation is determine by this parameter.
5698 
5699 
5700 Return Value
5701 ------------
5702 The calculated buffer size in frames.
5703 
5704 
5705 Thread Safety
5706 -------------
5707 This is safe so long as nothing modifies `pDescriptor` at the same time. However, this function
5708 should only ever be called from within the backend's device initialization routine and therefore
5709 shouldn't have any multithreading concerns.
5710 
5711 
5712 Callback Safety
5713 ---------------
5714 This is safe to call within the data callback, but there is no reason to ever do this.
5715 
5716 
5717 Remarks
5718 -------
5719 If `nativeSampleRate` is zero, this function will fall back to `pDescriptor->sampleRate`. If that
5720 is also zero, `MA_DEFAULT_SAMPLE_RATE` will be used instead.
5721 */
5723 
5724 
5725 
5726 /*
5727 Retrieves a friendly name for a backend.
5728 */
5729 MA_API const char* ma_get_backend_name(ma_backend backend);
5730 
5731 /*
5732 Determines whether or not the given backend is available by the compilation environment.
5733 */
5735 
5736 /*
5737 Retrieves compile-time enabled backends.
5738 
5739 
5740 Parameters
5741 ----------
5742 pBackends (out, optional)
5743  A pointer to the buffer that will receive the enabled backends. Set to NULL to retrieve the backend count. Setting
5744  the capacity of the buffer to `MA_BUFFER_COUNT` will guarantee it's large enough for all backends.
5745 
5746 backendCap (in)
5747  The capacity of the `pBackends` buffer.
5748 
5749 pBackendCount (out)
5750  A pointer to the variable that will receive the enabled backend count.
5751 
5752 
5753 Return Value
5754 ------------
5755 MA_SUCCESS if successful.
5756 MA_INVALID_ARGS if `pBackendCount` is NULL.
5757 MA_NO_SPACE if the capacity of `pBackends` is not large enough.
5758 
5759 If `MA_NO_SPACE` is returned, the `pBackends` buffer will be filled with `*pBackendCount` values.
5760 
5761 
5762 Thread Safety
5763 -------------
5764 Safe.
5765 
5766 
5767 Callback Safety
5768 ---------------
5769 Safe.
5770 
5771 
5772 Remarks
5773 -------
5774 If you want to retrieve the number of backends so you can determine the capacity of `pBackends` buffer, you can call
5775 this function with `pBackends` set to NULL.
5776 
5777 This will also enumerate the null backend. If you don't want to include this you need to check for `ma_backend_null`
5778 when you enumerate over the returned backends and handle it appropriately. Alternatively, you can disable it at
5779 compile time with `MA_NO_NULL`.
5780 
5781 The returned backends are determined based on compile time settings, not the platform it's currently running on. For
5782 example, PulseAudio will be returned if it was enabled at compile time, even when the user doesn't actually have
5783 PulseAudio installed.
5784 
5785 
5786 Example 1
5787 ---------
5788 The example below retrieves the enabled backend count using a fixed sized buffer allocated on the stack. The buffer is
5789 given a capacity of `MA_BACKEND_COUNT` which will guarantee it'll be large enough to store all available backends.
5790 Since `MA_BACKEND_COUNT` is always a relatively small value, this should be suitable for most scenarios.
5791 
5792 ```
5793 ma_backend enabledBackends[MA_BACKEND_COUNT];
5794 size_t enabledBackendCount;
5795 
5796 result = ma_get_enabled_backends(enabledBackends, MA_BACKEND_COUNT, &enabledBackendCount);
5797 if (result != MA_SUCCESS) {
5798  // Failed to retrieve enabled backends. Should never happen in this example since all inputs are valid.
5799 }
5800 ```
5801 
5802 
5803 See Also
5804 --------
5805 ma_is_backend_enabled()
5806 */
5807 MA_API ma_result ma_get_enabled_backends(ma_backend* pBackends, size_t backendCap, size_t* pBackendCount);
5808 
5809 /*
5810 Determines whether or not loopback mode is support by a backend.
5811 */
5813 
5814 #endif /* MA_NO_DEVICE_IO */
5815 
5816 
5817 #ifndef MA_NO_THREADING
5818 
5819 /*
5820 Locks a spinlock.
5821 */
5822 MA_API ma_result ma_spinlock_lock(volatile ma_spinlock* pSpinlock);
5823 
5824 /*
5825 Locks a spinlock, but does not yield() when looping.
5826 */
5828 
5829 /*
5830 Unlocks a spinlock.
5831 */
5832 MA_API ma_result ma_spinlock_unlock(volatile ma_spinlock* pSpinlock);
5833 
5834 
5835 /*
5836 Creates a mutex.
5837 
5838 A mutex must be created from a valid context. A mutex is initially unlocked.
5839 */
5841 
5842 /*
5843 Deletes a mutex.
5844 */
5845 MA_API void ma_mutex_uninit(ma_mutex* pMutex);
5846 
5847 /*
5848 Locks a mutex with an infinite timeout.
5849 */
5850 MA_API void ma_mutex_lock(ma_mutex* pMutex);
5851 
5852 /*
5853 Unlocks a mutex.
5854 */
5855 MA_API void ma_mutex_unlock(ma_mutex* pMutex);
5856 
5857 
5858 /*
5859 Initializes an auto-reset event.
5860 */
5862 
5863 /*
5864 Uninitializes an auto-reset event.
5865 */
5866 MA_API void ma_event_uninit(ma_event* pEvent);
5867 
5868 /*
5869 Waits for the specified auto-reset event to become signalled.
5870 */
5872 
5873 /*
5874 Signals the specified auto-reset event.
5875 */
5877 #endif /* MA_NO_THREADING */
5878 
5879 
5880 /************************************************************************************************************************************************************
5881 
5882 Utiltities
5883 
5884 ************************************************************************************************************************************************************/
5885 
5886 /*
5887 Adjust buffer size based on a scaling factor.
5888 
5889 This just multiplies the base size by the scaling factor, making sure it's a size of at least 1.
5890 */
5891 MA_API ma_uint32 ma_scale_buffer_size(ma_uint32 baseBufferSize, float scale);
5892 
5893 /*
5894 Calculates a buffer size in milliseconds from the specified number of frames and sample rate.
5895 */
5897 
5898 /*
5899 Calculates a buffer size in frames from the specified number of milliseconds and sample rate.
5900 */
5902 
5903 /*
5904 Copies PCM frames from one buffer to another.
5905 */
5906 MA_API void ma_copy_pcm_frames(void* dst, const void* src, ma_uint64 frameCount, ma_format format, ma_uint32 channels);
5907 
5908 /*
5909 Copies silent frames into the given buffer.
5910 
5911 Remarks
5912 -------
5913 For all formats except `ma_format_u8`, the output buffer will be filled with 0. For `ma_format_u8` it will be filled with 128. The reason for this is that it
5914 makes more sense for the purpose of mixing to initialize it to the center point.
5915 */
5916 MA_API void ma_silence_pcm_frames(void* p, ma_uint64 frameCount, ma_format format, ma_uint32 channels);
5917 static MA_INLINE void ma_zero_pcm_frames(void* p, ma_uint64 frameCount, ma_format format, ma_uint32 channels) { ma_silence_pcm_frames(p, frameCount, format, channels); }
5918 
5919 
5920 /*
5921 Offsets a pointer by the specified number of PCM frames.
5922 */
5923 MA_API void* ma_offset_pcm_frames_ptr(void* p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels);
5924 MA_API const void* ma_offset_pcm_frames_const_ptr(const void* p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels);
5925 static MA_INLINE float* ma_offset_pcm_frames_ptr_f32(float* p, ma_uint64 offsetInFrames, ma_uint32 channels) { return (float*)ma_offset_pcm_frames_ptr((void*)p, offsetInFrames, ma_format_f32, channels); }
5926 static MA_INLINE const float* ma_offset_pcm_frames_const_ptr_f32(const float* p, ma_uint64 offsetInFrames, ma_uint32 channels) { return (const float*)ma_offset_pcm_frames_const_ptr((const void*)p, offsetInFrames, ma_format_f32, channels); }
5927 
5928 
5929 /*
5930 Clips f32 samples.
5931 */
5932 MA_API void ma_clip_samples_f32(float* p, ma_uint64 sampleCount);
5933 static MA_INLINE void ma_clip_pcm_frames_f32(float* p, ma_uint64 frameCount, ma_uint32 channels) { ma_clip_samples_f32(p, frameCount*channels); }
5934 
5935 /*
5936 Helper for applying a volume factor to samples.
5937 
5938 Note that the source and destination buffers can be the same, in which case it'll perform the operation in-place.
5939 */
5940 MA_API void ma_copy_and_apply_volume_factor_u8(ma_uint8* pSamplesOut, const ma_uint8* pSamplesIn, ma_uint64 sampleCount, float factor);
5941 MA_API void ma_copy_and_apply_volume_factor_s16(ma_int16* pSamplesOut, const ma_int16* pSamplesIn, ma_uint64 sampleCount, float factor);
5942 MA_API void ma_copy_and_apply_volume_factor_s24(void* pSamplesOut, const void* pSamplesIn, ma_uint64 sampleCount, float factor);
5943 MA_API void ma_copy_and_apply_volume_factor_s32(ma_int32* pSamplesOut, const ma_int32* pSamplesIn, ma_uint64 sampleCount, float factor);
5944 MA_API void ma_copy_and_apply_volume_factor_f32(float* pSamplesOut, const float* pSamplesIn, ma_uint64 sampleCount, float factor);
5945 
5946 MA_API void ma_apply_volume_factor_u8(ma_uint8* pSamples, ma_uint64 sampleCount, float factor);
5947 MA_API void ma_apply_volume_factor_s16(ma_int16* pSamples, ma_uint64 sampleCount, float factor);
5948 MA_API void ma_apply_volume_factor_s24(void* pSamples, ma_uint64 sampleCount, float factor);
5949 MA_API void ma_apply_volume_factor_s32(ma_int32* pSamples, ma_uint64 sampleCount, float factor);
5950 MA_API void ma_apply_volume_factor_f32(float* pSamples, ma_uint64 sampleCount, float factor);
5951 
5952 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);
5953 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);
5954 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);
5955 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);
5956 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);
5957 MA_API void ma_copy_and_apply_volume_factor_pcm_frames(void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor);
5958 
5959 MA_API void ma_apply_volume_factor_pcm_frames_u8(ma_uint8* pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor);
5960 MA_API void ma_apply_volume_factor_pcm_frames_s16(ma_int16* pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor);
5961 MA_API void ma_apply_volume_factor_pcm_frames_s24(void* pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor);
5962 MA_API void ma_apply_volume_factor_pcm_frames_s32(ma_int32* pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor);
5963 MA_API void ma_apply_volume_factor_pcm_frames_f32(float* pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor);
5964 MA_API void ma_apply_volume_factor_pcm_frames(void* pFrames, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor);
5965 
5966 
5967 /*
5968 Helper for converting a linear factor to gain in decibels.
5969 */
5970 MA_API float ma_factor_to_gain_db(float factor);
5971 
5972 /*
5973 Helper for converting gain in decibels to a linear factor.
5974 */
5975 MA_API float ma_gain_db_to_factor(float gain);
5976 
5977 
5978 typedef void ma_data_source;
5979 
5980 typedef struct
5981 {
5982  ma_result (* onRead)(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
5983  ma_result (* onSeek)(ma_data_source* pDataSource, ma_uint64 frameIndex);
5984  ma_result (* onMap)(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
5985  ma_result (* onUnmap)(ma_data_source* pDataSource, ma_uint64 frameCount);
5986  ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
5987  ma_result (* onGetCursor)(ma_data_source* pDataSource, ma_uint64* pCursor);
5988  ma_result (* onGetLength)(ma_data_source* pDataSource, ma_uint64* pLength);
5989 } ma_data_source_vtable, ma_data_source_callbacks; /* TODO: Remove ma_data_source_callbacks in version 0.11. */
5990 
5991 typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource);
5992 
5993 typedef struct
5994 {
5995  const ma_data_source_vtable* vtable; /* Can be null, which is useful for proxies. */
5997 
5999 
6000 
6001 typedef struct
6002 {
6003  ma_data_source_callbacks cb; /* TODO: Remove this. */
6004 
6005  /* Variables below are placeholder and not yet used. */
6006  const ma_data_source_vtable* vtable;
6007  ma_uint64 rangeBegInFrames;
6008  ma_uint64 rangeEndInFrames; /* Set to -1 for unranged (default). */
6009  ma_uint64 loopBegInFrames; /* Relative to rangeBegInFrames. */
6010  ma_uint64 loopEndInFrames; /* Relative to rangeBegInFrames. Set to -1 for the end of the range. */
6011  ma_data_source* pCurrent; /* When non-NULL, the data source being initialized will act as a proxy and will route all operations to pCurrent. Used in conjunction with pNext/onGetNext for seamless chaining. */
6012  ma_data_source* pNext; /* When set to NULL, onGetNext will be used. */
6013  ma_data_source_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
6015 
6017 MA_API void ma_data_source_uninit(ma_data_source* pDataSource);
6018 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); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */
6019 MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked, ma_bool32 loop); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount); */
6021 MA_API ma_result ma_data_source_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount); /* Returns MA_NOT_IMPLEMENTED if mapping is not supported. */
6022 MA_API ma_result ma_data_source_unmap(ma_data_source* pDataSource, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. */
6023 MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
6025 MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength); /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */
6026 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
6027 MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames);
6028 MA_API void ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames);
6029 MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames);
6030 MA_API void ma_data_source_get_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLoopBegInFrames, ma_uint64* pLoopEndInFrames);
6031 MA_API ma_result ma_data_source_set_current(ma_data_source* pDataSource, ma_data_source* pCurrentDataSource);
6032 MA_API ma_data_source* ma_data_source_get_current(ma_data_source* pDataSource);
6033 MA_API ma_result ma_data_source_set_next(ma_data_source* pDataSource, ma_data_source* pNextDataSource);
6034 MA_API ma_data_source* ma_data_source_get_next(ma_data_source* pDataSource);
6035 MA_API ma_result ma_data_source_set_next_callback(ma_data_source* pDataSource, ma_data_source_get_next_proc onGetNext);
6036 MA_API ma_data_source_get_next_proc ma_data_source_get_next_callback(ma_data_source* pDataSource);
6037 #endif
6038 
6039 
6040 typedef struct
6041 {
6043  ma_format format;
6044  ma_uint32 channels;
6045  ma_uint64 cursor;
6046  ma_uint64 sizeInFrames;
6047  const void* pData;
6049 
6050 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);
6052 MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames);
6053 MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
6055 MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount);
6056 MA_API ma_result ma_audio_buffer_ref_unmap(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
6061 
6062 
6063 
6064 typedef struct
6065 {
6066  ma_format format;
6067  ma_uint32 channels;
6068  ma_uint64 sizeInFrames;
6069  const void* pData; /* If set to NULL, will allocate a block of memory for you. */
6070  ma_allocation_callbacks allocationCallbacks;
6072 
6073 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);
6074 
6075 typedef struct
6076 {
6077  ma_audio_buffer_ref ref;
6078  ma_allocation_callbacks allocationCallbacks;
6079  ma_bool32 ownsData; /* Used to control whether or not miniaudio owns the data buffer. If set to true, pData will be freed in ma_audio_buffer_uninit(). */
6080  ma_uint8 _pExtraData[1]; /* For allocating a buffer with the memory located directly after the other memory of the structure. */
6081 } ma_audio_buffer;
6082 
6085 MA_API ma_result ma_audio_buffer_alloc_and_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer** ppAudioBuffer); /* Always copies the data. Doesn't make sense to use this otherwise. Use ma_audio_buffer_uninit_and_free() to uninit. */
6086 MA_API void ma_audio_buffer_uninit(ma_audio_buffer* pAudioBuffer);
6088 MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
6090 MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount);
6091 MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer* pAudioBuffer, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
6095 MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames);
6096 
6097 
6098 
6099 /************************************************************************************************************************************************************
6100 
6101 VFS
6102 ===
6103 
6104 The VFS object (virtual file system) is what's used to customize file access. This is useful in cases where stdio FILE* based APIs may not be entirely
6105 appropriate for a given situation.
6106 
6107 ************************************************************************************************************************************************************/
6108 typedef void ma_vfs;
6110 
6111 #define MA_OPEN_MODE_READ 0x00000001
6112 #define MA_OPEN_MODE_WRITE 0x00000002
6113 
6114 typedef enum
6115 {
6118  ma_seek_origin_end /* Not used by decoders. */
6119 } ma_seek_origin;
6120 
6121 typedef struct
6122 {
6123  ma_uint64 sizeInBytes;
6124 } ma_file_info;
6125 
6126 typedef struct
6127 {
6128  ma_result (* onOpen) (ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
6129  ma_result (* onOpenW)(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
6130  ma_result (* onClose)(ma_vfs* pVFS, ma_vfs_file file);
6131  ma_result (* onRead) (ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead);
6132  ma_result (* onWrite)(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten);
6133  ma_result (* onSeek) (ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin);
6134  ma_result (* onTell) (ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor);
6135  ma_result (* onInfo) (ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo);
6137 
6138 MA_API ma_result ma_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
6139 MA_API ma_result ma_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
6141 MA_API ma_result ma_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead);
6142 MA_API ma_result ma_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten);
6144 MA_API ma_result ma_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor);
6146 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);
6147 
6148 typedef struct
6149 {
6150  ma_vfs_callbacks cb;
6151  ma_allocation_callbacks allocationCallbacks; /* Only used for the wchar_t version of open() on non-Windows platforms. */
6152 } ma_default_vfs;
6153 
6154 MA_API ma_result ma_default_vfs_init(ma_default_vfs* pVFS, const ma_allocation_callbacks* pAllocationCallbacks);
6155 
6156 
6157 
6158 typedef ma_result (* ma_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead);
6159 typedef ma_result (* ma_seek_proc)(void* pUserData, ma_int64 offset, ma_seek_origin origin);
6160 typedef ma_result (* ma_tell_proc)(void* pUserData, ma_int64* pCursor);
6161 
6162 
6163 
6164 #if !defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING)
6165 typedef enum
6166 {
6169 
6170 typedef enum
6171 {
6178 #endif
6179 
6180 /************************************************************************************************************************************************************
6181 
6182 Decoding
6183 ========
6184 
6185 Decoders are independent of the main device API. Decoding APIs can be called freely inside the device's data callback, but they are not thread safe unless
6186 you do your own synchronization.
6187 
6188 ************************************************************************************************************************************************************/
6189 #ifndef MA_NO_DECODING
6190 typedef struct ma_decoder ma_decoder;
6191 
6192 
6193 typedef struct
6194 {
6195  ma_format preferredFormat;
6197 
6199 
6200 
6201 typedef struct
6202 {
6203  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);
6204  ma_result (* onInitFile )(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend); /* Optional. */
6205  ma_result (* onInitFileW )(void* pUserData, const wchar_t* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend); /* Optional. */
6206  ma_result (* onInitMemory )(void* pUserData, const void* pData, size_t dataSize, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend); /* Optional. */
6207  void (* onUninit )(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks);
6208  ma_result (* onGetChannelMap)(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap);
6210 
6211 
6212 /* TODO: Convert read and seek to be consistent with the VFS API (ma_result return value, bytes read moved to an output parameter). */
6213 typedef size_t (* ma_decoder_read_proc)(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead); /* Returns the number of bytes read. */
6214 typedef ma_bool32 (* ma_decoder_seek_proc)(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin);
6215 typedef ma_result (* ma_decoder_tell_proc)(ma_decoder* pDecoder, ma_int64* pCursor);
6216 
6217 typedef struct
6218 {
6219  ma_format format; /* Set to 0 or ma_format_unknown to use the stream's internal format. */
6220  ma_uint32 channels; /* Set to 0 to use the stream's internal channels. */
6221  ma_uint32 sampleRate; /* Set to 0 to use the stream's internal sample rate. */
6222  ma_channel channelMap[MA_MAX_CHANNELS];
6223  ma_channel_mix_mode channelMixMode;
6224  ma_dither_mode ditherMode;
6225  struct
6226  {
6227  ma_resample_algorithm algorithm;
6228  struct
6229  {
6230  ma_uint32 lpfOrder;
6231  } linear;
6232  struct
6233  {
6234  int quality;
6235  } speex;
6236  } resampling;
6238  ma_encoding_format encodingFormat;
6239  ma_decoding_backend_vtable** ppCustomBackendVTables;
6240  ma_uint32 customBackendCount;
6241  void* pCustomBackendUserData;
6243 
6244 struct ma_decoder
6245 {
6247  ma_data_source* pBackend; /* The decoding backend we'll be pulling data from. */
6248  const ma_decoding_backend_vtable* pBackendVTable; /* The vtable for the decoding backend. This needs to be stored so we can access the onUninit() callback. */
6249  void* pBackendUserData;
6253  void* pUserData;
6254  ma_uint64 readPointerInPCMFrames; /* In output sample rate. Used for keeping track of how many frames are available for decoding. */
6259  ma_data_converter converter; /* <-- Data conversion is achieved by running frames through this. */
6261  union
6262  {
6263  struct
6264  {
6265  ma_vfs* pVFS;
6266  ma_vfs_file file;
6267  } vfs;
6268  struct
6269  {
6270  const ma_uint8* pData;
6271  size_t dataSize;
6272  size_t currentReadPos;
6273  } memory; /* Only used for decoders that were opened against a block of memory. */
6274  } data;
6275 };
6276 
6277 MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint32 outputChannels, ma_uint32 outputSampleRate);
6279 
6280 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);
6281 MA_API ma_result ma_decoder_init_memory(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6282 MA_API ma_result ma_decoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6283 MA_API ma_result ma_decoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6284 MA_API ma_result ma_decoder_init_file(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6285 MA_API ma_result ma_decoder_init_file_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6286 
6287 /*
6288 Uninitializes a decoder.
6289 */
6291 
6292 /*
6293 Retrieves the current position of the read cursor in PCM frames.
6294 */
6296 
6297 /*
6298 Retrieves the length of the decoder in PCM frames.
6299 
6300 Do not call this on streams of an undefined length, such as internet radio.
6301 
6302 If the length is unknown or an error occurs, 0 will be returned.
6303 
6304 This will always return 0 for Vorbis decoders. This is due to a limitation with stb_vorbis in push mode which is what miniaudio
6305 uses internally.
6306 
6307 For MP3's, this will decode the entire file. Do not call this in time critical scenarios.
6308 
6309 This function is not thread safe without your own synchronization.
6310 */
6312 
6313 /*
6314 Reads PCM frames from the given decoder.
6315 
6316 This is not thread safe without your own synchronization.
6317 */
6318 MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount);
6319 
6320 /*
6321 Seeks to a PCM frame based on it's absolute index.
6322 
6323 This is not thread safe without your own synchronization.
6324 */
6326 
6327 /*
6328 Retrieves the number of frames that can be read before reaching the end.
6329 
6330 This calls `ma_decoder_get_length_in_pcm_frames()` so you need to be aware of the rules for that function, in
6331 particular ensuring you do not call it on streams of an undefined length, such as internet radio.
6332 
6333 If the total length of the decoder cannot be retrieved, such as with Vorbis decoders, `MA_NOT_IMPLEMENTED` will be
6334 returned.
6335 */
6337 
6338 /*
6339 Helper for opening and decoding a file into a heap allocated block of memory. Free the returned pointer with ma_free(). On input,
6340 pConfig should be set to what you want. On output it will be set to what you got.
6341 */
6342 MA_API ma_result ma_decode_from_vfs(ma_vfs* pVFS, const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut);
6343 MA_API ma_result ma_decode_file(const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut);
6344 MA_API ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut);
6345 
6346 
6347 
6348 
6349 /*
6350 DEPRECATED
6351 
6352 Set the "encodingFormat" variable in the decoder config instead:
6353 
6354  decoderConfig.encodingFormat = ma_encoding_format_wav;
6355 
6356 These functions will be removed in version 0.11.
6357 */
6358 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);
6359 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);
6360 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);
6361 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);
6362 MA_API ma_result ma_decoder_init_memory_wav(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6363 MA_API ma_result ma_decoder_init_memory_flac(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6364 MA_API ma_result ma_decoder_init_memory_mp3(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6365 MA_API ma_result ma_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6366 MA_API ma_result ma_decoder_init_vfs_wav(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6367 MA_API ma_result ma_decoder_init_vfs_flac(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6368 MA_API ma_result ma_decoder_init_vfs_mp3(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6369 MA_API ma_result ma_decoder_init_vfs_vorbis(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6370 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);
6371 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);
6372 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);
6373 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);
6374 MA_API ma_result ma_decoder_init_file_wav(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6375 MA_API ma_result ma_decoder_init_file_flac(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6376 MA_API ma_result ma_decoder_init_file_mp3(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6377 MA_API ma_result ma_decoder_init_file_vorbis(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6378 MA_API ma_result ma_decoder_init_file_wav_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6379 MA_API ma_result ma_decoder_init_file_flac_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6380 MA_API ma_result ma_decoder_init_file_mp3_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6381 MA_API ma_result ma_decoder_init_file_vorbis_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
6382 
6383 #endif /* MA_NO_DECODING */
6384 
6385 
6386 /************************************************************************************************************************************************************
6387 
6388 Encoding
6389 ========
6390 
6391 Encoders do not perform any format conversion for you. If your target format does not support the format, and error will be returned.
6392 
6393 ************************************************************************************************************************************************************/
6394 #ifndef MA_NO_ENCODING
6395 typedef struct ma_encoder ma_encoder;
6396 
6397 typedef size_t (* ma_encoder_write_proc) (ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite); /* Returns the number of bytes written. */
6398 typedef ma_bool32 (* ma_encoder_seek_proc) (ma_encoder* pEncoder, int byteOffset, ma_seek_origin origin);
6400 typedef void (* ma_encoder_uninit_proc) (ma_encoder* pEncoder);
6401 typedef ma_uint64 (* ma_encoder_write_pcm_frames_proc)(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount);
6402 
6403 typedef struct
6404 {
6405  ma_resource_format resourceFormat;
6406  ma_format format;
6407  ma_uint32 channels;
6408  ma_uint32 sampleRate;
6409  ma_allocation_callbacks allocationCallbacks;
6411 
6412 MA_API ma_encoder_config ma_encoder_config_init(ma_resource_format resourceFormat, ma_format format, ma_uint32 channels, ma_uint32 sampleRate);
6413 
6414 struct ma_encoder
6415 {
6422  void* pUserData;
6423  void* pInternalEncoder; /* <-- The drwav/drflac/stb_vorbis/etc. objects. */
6424  void* pFile; /* FILE*. Only used when initialized with ma_encoder_init_file(). */
6425 };
6426 
6427 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);
6428 MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
6429 MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
6430 MA_API void ma_encoder_uninit(ma_encoder* pEncoder);
6431 MA_API ma_uint64 ma_encoder_write_pcm_frames(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount);
6432 
6433 #endif /* MA_NO_ENCODING */
6434 
6435 
6436 /************************************************************************************************************************************************************
6437 
6438 Generation
6439 
6440 ************************************************************************************************************************************************************/
6441 #ifndef MA_NO_GENERATION
6442 typedef enum
6443 {
6450 typedef struct
6452  ma_format format;
6453  ma_uint32 channels;
6454  ma_uint32 sampleRate;
6455  ma_waveform_type type;
6456  double amplitude;
6457  double frequency;
6459 
6460 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);
6461 
6462 typedef struct
6463 {
6466  double advance;
6467  double time;
6468 } ma_waveform;
6469 
6470 MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform);
6471 MA_API void ma_waveform_uninit(ma_waveform* pWaveform);
6472 MA_API ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount);
6474 MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude);
6475 MA_API ma_result ma_waveform_set_frequency(ma_waveform* pWaveform, double frequency);
6478 
6479 typedef enum
6480 {
6484 } ma_noise_type;
6485 
6486 typedef struct
6487 {
6488  ma_format format;
6489  ma_uint32 channels;
6490  ma_noise_type type;
6491  ma_int32 seed;
6492  double amplitude;
6493  ma_bool32 duplicateChannels;
6494 } ma_noise_config;
6495 
6496 MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels, ma_noise_type type, ma_int32 seed, double amplitude);
6497 
6498 typedef struct
6499 {
6502  ma_lcg lcg;
6503  union
6504  {
6505  struct
6506  {
6507  double bin[MA_MAX_CHANNELS][16];
6508  double accumulation[MA_MAX_CHANNELS];
6509  ma_uint32 counter[MA_MAX_CHANNELS];
6510  } pink;
6511  struct
6512  {
6513  double accumulation[MA_MAX_CHANNELS];
6514  } brownian;
6515  } state;
6516 } ma_noise;
6517 
6518 MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise);
6519 MA_API void ma_noise_uninit(ma_noise* pNoise);
6520 MA_API ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount);
6521 MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude);
6524 
6525 #endif /* MA_NO_GENERATION */
6526 
6527 #ifdef __cplusplus
6528 }
6529 #endif
6530 #endif /* miniaudio_h */
6531 
6532 
6533 
6534 /************************************************************************************************************************************************************
6535 *************************************************************************************************************************************************************
6536 
6537 IMPLEMENTATION
6538 
6539 *************************************************************************************************************************************************************
6540 ************************************************************************************************************************************************************/
6541 #if defined(MINIAUDIO_IMPLEMENTATION) || defined(MA_IMPLEMENTATION)
6542 #ifndef miniaudio_c
6543 #define miniaudio_c
6544 
6545 #include <assert.h>
6546 #include <limits.h> /* For INT_MAX */
6547 #include <math.h> /* sin(), etc. */
6548 
6549 #include <stdarg.h>
6550 #include <stdio.h>
6551 #if !defined(_MSC_VER) && !defined(__DMC__)
6552  #include <strings.h> /* For strcasecmp(). */
6553  #include <wchar.h> /* For wcslen(), wcsrtombs() */
6554 #endif
6555 
6556 #ifdef MA_WIN32
6557 #include <windows.h>
6558 #else
6559 #include <stdlib.h> /* For malloc(), free(), wcstombs(). */
6560 #include <string.h> /* For memset() */
6561 #include <sched.h>
6562 #include <sys/time.h> /* select() (used for ma_sleep()). */
6563 #endif
6564 
6565 #include <sys/stat.h> /* For fstat(), etc. */
6566 
6567 #ifdef MA_EMSCRIPTEN
6568 #include <emscripten/emscripten.h>
6569 #endif
6570 
6571 #if !defined(MA_64BIT) && !defined(MA_32BIT)
6572 #ifdef _WIN32
6573 #ifdef _WIN64
6574 #define MA_64BIT
6575 #else
6576 #define MA_32BIT
6577 #endif
6578 #endif
6579 #endif
6580 
6581 #if !defined(MA_64BIT) && !defined(MA_32BIT)
6582 #ifdef __GNUC__
6583 #ifdef __LP64__
6584 #define MA_64BIT
6585 #else
6586 #define MA_32BIT
6587 #endif
6588 #endif
6589 #endif
6590 
6591 #if !defined(MA_64BIT) && !defined(MA_32BIT)
6592 #include <stdint.h>
6593 #if INTPTR_MAX == INT64_MAX
6594 #define MA_64BIT
6595 #else
6596 #define MA_32BIT
6597 #endif
6598 #endif
6599 
6600 /* Architecture Detection */
6601 #if defined(__x86_64__) || defined(_M_X64)
6602 #define MA_X64
6603 #elif defined(__i386) || defined(_M_IX86)
6604 #define MA_X86
6605 #elif defined(__arm__) || defined(_M_ARM)
6606 #define MA_ARM
6607 #endif
6608 
6609 /* Cannot currently support AVX-512 if AVX is disabled. */
6610 #if !defined(MA_NO_AVX512) && defined(MA_NO_AVX2)
6611 #define MA_NO_AVX512
6612 #endif
6613 
6614 /* Intrinsics Support */
6615 #if defined(MA_X64) || defined(MA_X86)
6616  #if defined(_MSC_VER) && !defined(__clang__)
6617  /* MSVC. */
6618  #if _MSC_VER >= 1400 && !defined(MA_NO_SSE2) /* 2005 */
6619  #define MA_SUPPORT_SSE2
6620  #endif
6621  /*#if _MSC_VER >= 1600 && !defined(MA_NO_AVX)*/ /* 2010 */
6622  /* #define MA_SUPPORT_AVX*/
6623  /*#endif*/
6624  #if _MSC_VER >= 1700 && !defined(MA_NO_AVX2) /* 2012 */
6625  #define MA_SUPPORT_AVX2
6626  #endif
6627  #if _MSC_VER >= 1910 && !defined(MA_NO_AVX512) /* 2017 */
6628  #define MA_SUPPORT_AVX512
6629  #endif
6630  #else
6631  /* Assume GNUC-style. */
6632  #if defined(__SSE2__) && !defined(MA_NO_SSE2)
6633  #define MA_SUPPORT_SSE2
6634  #endif
6635  /*#if defined(__AVX__) && !defined(MA_NO_AVX)*/
6636  /* #define MA_SUPPORT_AVX*/
6637  /*#endif*/
6638  #if defined(__AVX2__) && !defined(MA_NO_AVX2)
6639  #define MA_SUPPORT_AVX2
6640  #endif
6641  #if defined(__AVX512F__) && !defined(MA_NO_AVX512)
6642  #define MA_SUPPORT_AVX512
6643  #endif
6644  #endif
6645 
6646  /* If at this point we still haven't determined compiler support for the intrinsics just fall back to __has_include. */
6647  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
6648  #if !defined(MA_SUPPORT_SSE2) && !defined(MA_NO_SSE2) && __has_include(<emmintrin.h>)
6649  #define MA_SUPPORT_SSE2
6650  #endif
6651  /*#if !defined(MA_SUPPORT_AVX) && !defined(MA_NO_AVX) && __has_include(<immintrin.h>)*/
6652  /* #define MA_SUPPORT_AVX*/
6653  /*#endif*/
6654  #if !defined(MA_SUPPORT_AVX2) && !defined(MA_NO_AVX2) && __has_include(<immintrin.h>)
6655  #define MA_SUPPORT_AVX2
6656  #endif
6657  #if !defined(MA_SUPPORT_AVX512) && !defined(MA_NO_AVX512) && __has_include(<zmmintrin.h>)
6658  #define MA_SUPPORT_AVX512
6659  #endif
6660  #endif
6661 
6662  #if defined(MA_SUPPORT_AVX512)
6663  #include <immintrin.h> /* Not a mistake. Intentionally including <immintrin.h> instead of <zmmintrin.h> because otherwise the compiler will complain. */
6664  #elif defined(MA_SUPPORT_AVX2) || defined(MA_SUPPORT_AVX)
6665  #include <immintrin.h>
6666  #elif defined(MA_SUPPORT_SSE2)
6667  #include <emmintrin.h>
6668  #endif
6669 #endif
6670 
6671 #if defined(MA_ARM)
6672  #if !defined(MA_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
6673  #define MA_SUPPORT_NEON
6674  #endif
6675 
6676  /* Fall back to looking for the #include file. */
6677  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
6678  #if !defined(MA_SUPPORT_NEON) && !defined(MA_NO_NEON) && __has_include(<arm_neon.h>)
6679  #define MA_SUPPORT_NEON
6680  #endif
6681  #endif
6682 
6683  #if defined(MA_SUPPORT_NEON)
6684  #include <arm_neon.h>
6685  #endif
6686 #endif
6687 
6688 /* Begin globally disabled warnings. */
6689 #if defined(_MSC_VER)
6690  #pragma warning(push)
6691  #pragma warning(disable:4752) /* found Intel(R) Advanced Vector Extensions; consider using /arch:AVX */
6692 #endif
6693 
6694 #if defined(MA_X64) || defined(MA_X86)
6695  #if defined(_MSC_VER) && !defined(__clang__)
6696  #if _MSC_VER >= 1400
6697  #include <intrin.h>
6698  static MA_INLINE void ma_cpuid(int info[4], int fid)
6699  {
6700  __cpuid(info, fid);
6701  }
6702  #else
6703  #define MA_NO_CPUID
6704  #endif
6705 
6706  #if _MSC_VER >= 1600 && (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219)
6707  static MA_INLINE unsigned __int64 ma_xgetbv(int reg)
6708  {
6709  return _xgetbv(reg);
6710  }
6711  #else
6712  #define MA_NO_XGETBV
6713  #endif
6714  #elif (defined(__GNUC__) || defined(__clang__)) && !defined(MA_ANDROID)
6715  static MA_INLINE void ma_cpuid(int info[4], int fid)
6716  {
6717  /*
6718  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
6719  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
6720  supporting different assembly dialects.
6721 
6722  What's basically happening is that we're saving and restoring the ebx register manually.
6723  */
6724  #if defined(DRFLAC_X86) && defined(__PIC__)
6725  __asm__ __volatile__ (
6726  "xchg{l} {%%}ebx, %k1;"
6727  "cpuid;"
6728  "xchg{l} {%%}ebx, %k1;"
6729  : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
6730  );
6731  #else
6732  __asm__ __volatile__ (
6733  "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
6734  );
6735  #endif
6736  }
6737 
6738  static MA_INLINE ma_uint64 ma_xgetbv(int reg)
6739  {
6740  unsigned int hi;
6741  unsigned int lo;
6742 
6743  __asm__ __volatile__ (
6744  "xgetbv" : "=a"(lo), "=d"(hi) : "c"(reg)
6745  );
6746 
6747  return ((ma_uint64)hi << 32) | (ma_uint64)lo;
6748  }
6749  #else
6750  #define MA_NO_CPUID
6751  #define MA_NO_XGETBV
6752  #endif
6753 #else
6754  #define MA_NO_CPUID
6755  #define MA_NO_XGETBV
6756 #endif
6757 
6758 static MA_INLINE ma_bool32 ma_has_sse2(void)
6759 {
6760 #if defined(MA_SUPPORT_SSE2)
6761  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_SSE2)
6762  #if defined(MA_X64)
6763  return MA_TRUE; /* 64-bit targets always support SSE2. */
6764  #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
6765  return MA_TRUE; /* If the compiler is allowed to freely generate SSE2 code we can assume support. */
6766  #else
6767  #if defined(MA_NO_CPUID)
6768  return MA_FALSE;
6769  #else
6770  int info[4];
6771  ma_cpuid(info, 1);
6772  return (info[3] & (1 << 26)) != 0;
6773  #endif
6774  #endif
6775  #else
6776  return MA_FALSE; /* SSE2 is only supported on x86 and x64 architectures. */
6777  #endif
6778 #else
6779  return MA_FALSE; /* No compiler support. */
6780 #endif
6781 }
6782 
6783 #if 0
6784 static MA_INLINE ma_bool32 ma_has_avx()
6785 {
6786 #if defined(MA_SUPPORT_AVX)
6787  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX)
6788  #if defined(_AVX_) || defined(__AVX__)
6789  return MA_TRUE; /* If the compiler is allowed to freely generate AVX code we can assume support. */
6790  #else
6791  /* AVX requires both CPU and OS support. */
6792  #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
6793  return MA_FALSE;
6794  #else
6795  int info[4];
6796  ma_cpuid(info, 1);
6797  if (((info[2] & (1 << 27)) != 0) && ((info[2] & (1 << 28)) != 0)) {
6798  ma_uint64 xrc = ma_xgetbv(0);
6799  if ((xrc & 0x06) == 0x06) {
6800  return MA_TRUE;
6801  } else {
6802  return MA_FALSE;
6803  }
6804  } else {
6805  return MA_FALSE;
6806  }
6807  #endif
6808  #endif
6809  #else
6810  return MA_FALSE; /* AVX is only supported on x86 and x64 architectures. */
6811  #endif
6812 #else
6813  return MA_FALSE; /* No compiler support. */
6814 #endif
6815 }
6816 #endif
6817 
6818 static MA_INLINE ma_bool32 ma_has_avx2(void)
6819 {
6820 #if defined(MA_SUPPORT_AVX2)
6821  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX2)
6822  #if defined(_AVX2_) || defined(__AVX2__)
6823  return MA_TRUE; /* If the compiler is allowed to freely generate AVX2 code we can assume support. */
6824  #else
6825  /* AVX2 requires both CPU and OS support. */
6826  #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
6827  return MA_FALSE;
6828  #else
6829  int info1[4];
6830  int info7[4];
6831  ma_cpuid(info1, 1);
6832  ma_cpuid(info7, 7);
6833  if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 5)) != 0)) {
6834  ma_uint64 xrc = ma_xgetbv(0);
6835  if ((xrc & 0x06) == 0x06) {
6836  return MA_TRUE;
6837  } else {
6838  return MA_FALSE;
6839  }
6840  } else {
6841  return MA_FALSE;
6842  }
6843  #endif
6844  #endif
6845  #else
6846  return MA_FALSE; /* AVX2 is only supported on x86 and x64 architectures. */
6847  #endif
6848 #else
6849  return MA_FALSE; /* No compiler support. */
6850 #endif
6851 }
6852 
6853 static MA_INLINE ma_bool32 ma_has_avx512f(void)
6854 {
6855 #if defined(MA_SUPPORT_AVX512)
6856  #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX512)
6857  #if defined(__AVX512F__)
6858  return MA_TRUE; /* If the compiler is allowed to freely generate AVX-512F code we can assume support. */
6859  #else
6860  /* AVX-512 requires both CPU and OS support. */
6861  #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
6862  return MA_FALSE;
6863  #else
6864  int info1[4];
6865  int info7[4];
6866  ma_cpuid(info1, 1);
6867  ma_cpuid(info7, 7);
6868  if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 16)) != 0)) {
6869  ma_uint64 xrc = ma_xgetbv(0);
6870  if ((xrc & 0xE6) == 0xE6) {
6871  return MA_TRUE;
6872  } else {
6873  return MA_FALSE;
6874  }
6875  } else {
6876  return MA_FALSE;
6877  }
6878  #endif
6879  #endif
6880  #else
6881  return MA_FALSE; /* AVX-512F is only supported on x86 and x64 architectures. */
6882  #endif
6883 #else
6884  return MA_FALSE; /* No compiler support. */
6885 #endif
6886 }
6887 
6888 static MA_INLINE ma_bool32 ma_has_neon(void)
6889 {
6890 #if defined(MA_SUPPORT_NEON)
6891  #if defined(MA_ARM) && !defined(MA_NO_NEON)
6892  #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
6893  return MA_TRUE; /* If the compiler is allowed to freely generate NEON code we can assume support. */
6894  #else
6895  /* TODO: Runtime check. */
6896  return MA_FALSE;
6897  #endif
6898  #else
6899  return MA_FALSE; /* NEON is only supported on ARM architectures. */
6900  #endif
6901 #else
6902  return MA_FALSE; /* No compiler support. */
6903 #endif
6904 }
6905 
6906 #define MA_SIMD_NONE 0
6907 #define MA_SIMD_SSE2 1
6908 #define MA_SIMD_AVX2 2
6909 #define MA_SIMD_NEON 3
6910 
6911 #ifndef MA_PREFERRED_SIMD
6912  # if defined(MA_SUPPORT_SSE2) && defined(MA_PREFER_SSE2)
6913  #define MA_PREFERRED_SIMD MA_SIMD_SSE2
6914  #elif defined(MA_SUPPORT_AVX2) && defined(MA_PREFER_AVX2)
6915  #define MA_PREFERRED_SIMD MA_SIMD_AVX2
6916  #elif defined(MA_SUPPORT_NEON) && defined(MA_PREFER_NEON)
6917  #define MA_PREFERRED_SIMD MA_SIMD_NEON
6918  #else
6919  #define MA_PREFERRED_SIMD MA_SIMD_NONE
6920  #endif
6921 #endif
6922 
6923 #if defined(__has_builtin)
6924  #define MA_COMPILER_HAS_BUILTIN(x) __has_builtin(x)
6925 #else
6926  #define MA_COMPILER_HAS_BUILTIN(x) 0
6927 #endif
6928 
6929 #ifndef MA_ASSUME
6930  #if MA_COMPILER_HAS_BUILTIN(__builtin_assume)
6931  #define MA_ASSUME(x) __builtin_assume(x)
6932  #elif MA_COMPILER_HAS_BUILTIN(__builtin_unreachable)
6933  #define MA_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0)
6934  #elif defined(_MSC_VER)
6935  #define MA_ASSUME(x) __assume(x)
6936  #else
6937  #define MA_ASSUME(x) while(0)
6938  #endif
6939 #endif
6940 
6941 #ifndef MA_RESTRICT
6942  #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
6943  #define MA_RESTRICT __restrict
6944  #else
6945  #define MA_RESTRICT
6946  #endif
6947 #endif
6948 
6949 #if defined(_MSC_VER) && _MSC_VER >= 1400
6950  #define MA_HAS_BYTESWAP16_INTRINSIC
6951  #define MA_HAS_BYTESWAP32_INTRINSIC
6952  #define MA_HAS_BYTESWAP64_INTRINSIC
6953 #elif defined(__clang__)
6954  #if MA_COMPILER_HAS_BUILTIN(__builtin_bswap16)
6955  #define MA_HAS_BYTESWAP16_INTRINSIC
6956  #endif
6957  #if MA_COMPILER_HAS_BUILTIN(__builtin_bswap32)
6958  #define MA_HAS_BYTESWAP32_INTRINSIC
6959  #endif
6960  #if MA_COMPILER_HAS_BUILTIN(__builtin_bswap64)
6961  #define MA_HAS_BYTESWAP64_INTRINSIC
6962  #endif
6963 #elif defined(__GNUC__)
6964  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
6965  #define MA_HAS_BYTESWAP32_INTRINSIC
6966  #define MA_HAS_BYTESWAP64_INTRINSIC
6967  #endif
6968  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
6969  #define MA_HAS_BYTESWAP16_INTRINSIC
6970  #endif
6971 #endif
6972 
6973 
6975 {
6976 #if defined(MA_X86) || defined(MA_X64)
6977  return MA_TRUE;
6978 #else
6979  int n = 1;
6980  return (*(char*)&n) == 1;
6981 #endif
6982 }
6983 
6985 {
6986  return !ma_is_little_endian();
6987 }
6988 
6989 
6991 {
6992 #ifdef MA_HAS_BYTESWAP32_INTRINSIC
6993  #if defined(_MSC_VER)
6994  return _byteswap_ulong(n);
6995  #elif defined(__GNUC__) || defined(__clang__)
6996  #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. */
6997  /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
6998  ma_uint32 r;
6999  __asm__ __volatile__ (
7000  #if defined(MA_64BIT)
7001  "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! */
7002  #else
7003  "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
7004  #endif
7005  );
7006  return r;
7007  #else
7008  return __builtin_bswap32(n);
7009  #endif
7010  #else
7011  #error "This compiler does not support the byte swap intrinsic."
7012  #endif
7013 #else
7014  return ((n & 0xFF000000) >> 24) |
7015  ((n & 0x00FF0000) >> 8) |
7016  ((n & 0x0000FF00) << 8) |
7017  ((n & 0x000000FF) << 24);
7018 #endif
7019 }
7020 
7021 
7022 #if !defined(MA_EMSCRIPTEN)
7023 #ifdef MA_WIN32
7024 static void ma_sleep__win32(ma_uint32 milliseconds)
7025 {
7026  Sleep((DWORD)milliseconds);
7027 }
7028 #endif
7029 #ifdef MA_POSIX
7030 static void ma_sleep__posix(ma_uint32 milliseconds)
7031 {
7032 #ifdef MA_EMSCRIPTEN
7033  (void)milliseconds;
7034  MA_ASSERT(MA_FALSE); /* The Emscripten build should never sleep. */
7035 #else
7036  #if _POSIX_C_SOURCE >= 199309L
7037  struct timespec ts;
7038  ts.tv_sec = milliseconds / 1000;
7039  ts.tv_nsec = milliseconds % 1000 * 1000000;
7040  nanosleep(&ts, NULL);
7041  #else
7042  struct timeval tv;
7043  tv.tv_sec = milliseconds / 1000;
7044  tv.tv_usec = milliseconds % 1000 * 1000;
7045  select(0, NULL, NULL, NULL, &tv);
7046  #endif
7047 #endif
7048 }
7049 #endif
7050 
7051 static void ma_sleep(ma_uint32 milliseconds)
7052 {
7053 #ifdef MA_WIN32
7054  ma_sleep__win32(milliseconds);
7055 #endif
7056 #ifdef MA_POSIX
7057  ma_sleep__posix(milliseconds);
7058 #endif
7059 }
7060 #endif
7061 
7062 static MA_INLINE void ma_yield()
7063 {
7064 #if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
7065  /* x86/x64 */
7066  #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)) && !defined(__clang__)
7067  #if _MSC_VER >= 1400
7068  _mm_pause();
7069  #else
7070  #if defined(__DMC__)
7071  /* Digital Mars does not recognize the PAUSE opcode. Fall back to NOP. */
7072  __asm nop;
7073  #else
7074  __asm pause;
7075  #endif
7076  #endif
7077  #else
7078  __asm__ __volatile__ ("pause");
7079  #endif
7080 #elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || (defined(_M_ARM) && _M_ARM >= 7) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
7081  /* ARM */
7082  #if defined(_MSC_VER)
7083  /* 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. */
7084  __yield();
7085  #else
7086  __asm__ __volatile__ ("yield"); /* ARMv6K/ARMv6T2 and above. */
7087  #endif
7088 #else
7089  /* Unknown or unsupported architecture. No-op. */
7090 #endif
7091 }
7092 
7093 
7094 
7095 #ifndef MA_COINIT_VALUE
7096 #define MA_COINIT_VALUE 0 /* 0 = COINIT_MULTITHREADED */
7097 #endif
7098 
7099 
7100 #ifndef MA_FLT_MAX
7101  #ifdef FLT_MAX
7102  #define MA_FLT_MAX FLT_MAX
7103  #else
7104  #define MA_FLT_MAX 3.402823466e+38F
7105  #endif
7106 #endif
7107 
7108 
7109 #ifndef MA_PI
7110 #define MA_PI 3.14159265358979323846264f
7111 #endif
7112 #ifndef MA_PI_D
7113 #define MA_PI_D 3.14159265358979323846264
7114 #endif
7115 #ifndef MA_TAU
7116 #define MA_TAU 6.28318530717958647693f
7117 #endif
7118 #ifndef MA_TAU_D
7119 #define MA_TAU_D 6.28318530717958647693
7120 #endif
7121 
7122 
7123 /* The default format when ma_format_unknown (0) is requested when initializing a device. */
7124 #ifndef MA_DEFAULT_FORMAT
7125 #define MA_DEFAULT_FORMAT ma_format_f32
7126 #endif
7127 
7128 /* The default channel count to use when 0 is used when initializing a device. */
7129 #ifndef MA_DEFAULT_CHANNELS
7130 #define MA_DEFAULT_CHANNELS 2
7131 #endif
7132 
7133 /* The default sample rate to use when 0 is used when initializing a device. */
7134 #ifndef MA_DEFAULT_SAMPLE_RATE
7135 #define MA_DEFAULT_SAMPLE_RATE 48000
7136 #endif
7137 
7138 /* Default periods when none is specified in ma_device_init(). More periods means more work on the CPU. */
7139 #ifndef MA_DEFAULT_PERIODS
7140 #define MA_DEFAULT_PERIODS 3
7141 #endif
7142 
7143 /* The default period size in milliseconds for low latency mode. */
7144 #ifndef MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY
7145 #define MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY 10
7146 #endif
7147 
7148 /* The default buffer size in milliseconds for conservative mode. */
7149 #ifndef MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE
7150 #define MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE 100
7151 #endif
7152 
7153 /* The default LPF filter order for linear resampling. Note that this is clamped to MA_MAX_FILTER_ORDER. */
7154 #ifndef MA_DEFAULT_RESAMPLER_LPF_ORDER
7155  #if MA_MAX_FILTER_ORDER >= 4
7156  #define MA_DEFAULT_RESAMPLER_LPF_ORDER 4
7157  #else
7158  #define MA_DEFAULT_RESAMPLER_LPF_ORDER MA_MAX_FILTER_ORDER
7159  #endif
7160 #endif
7161 
7162 
7163 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
7164  #pragma GCC diagnostic push
7165  #pragma GCC diagnostic ignored "-Wunused-variable"
7166 #endif
7167 
7168 /* Standard sample rates, in order of priority. */
7172 
7176 
7181 
7185 
7188 };
7189 
7191 {
7192  ma_uint32 iSampleRate;
7193 
7194  for (iSampleRate = 0; iSampleRate < sizeof(g_maStandardSampleRatePriorities) / sizeof(g_maStandardSampleRatePriorities[0]); iSampleRate += 1) {
7195  if (g_maStandardSampleRatePriorities[iSampleRate] == sampleRate) {
7196  return MA_TRUE;
7197  }
7198  }
7199 
7200  /* Getting here means the sample rate is not supported. */
7201  return MA_FALSE;
7202 }
7203 
7204 
7205 static ma_format g_maFormatPriorities[] = {
7206  ma_format_s16, /* Most common */
7207  ma_format_f32,
7208 
7209  /*ma_format_s24_32,*/ /* Clean alignment */
7210  ma_format_s32,
7211 
7212  ma_format_s24, /* Unclean alignment */
7213 
7214  ma_format_u8 /* Low quality */
7215 };
7216 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
7217  #pragma GCC diagnostic pop
7218 #endif
7219 
7220 
7221 MA_API void ma_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* pRevision)
7222 {
7223  if (pMajor) {
7224  *pMajor = MA_VERSION_MAJOR;
7225  }
7226 
7227  if (pMinor) {
7228  *pMinor = MA_VERSION_MINOR;
7229  }
7230 
7231  if (pRevision) {
7232  *pRevision = MA_VERSION_REVISION;
7233  }
7234 }
7235 
7236 MA_API const char* ma_version_string(void)
7237 {
7238  return MA_VERSION_STRING;
7239 }
7240 
7241 
7242 /******************************************************************************
7243 
7244 Standard Library Stuff
7245 
7246 ******************************************************************************/
7247 #ifndef MA_MALLOC
7248 #ifdef MA_WIN32
7249 #define MA_MALLOC(sz) HeapAlloc(GetProcessHeap(), 0, (sz))
7250 #else
7251 #define MA_MALLOC(sz) malloc((sz))
7252 #endif
7253 #endif
7254 
7255 #ifndef MA_REALLOC
7256 #ifdef MA_WIN32
7257 #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)))
7258 #else
7259 #define MA_REALLOC(p, sz) realloc((p), (sz))
7260 #endif
7261 #endif
7262 
7263 #ifndef MA_FREE
7264 #ifdef MA_WIN32
7265 #define MA_FREE(p) HeapFree(GetProcessHeap(), 0, (p))
7266 #else
7267 #define MA_FREE(p) free((p))
7268 #endif
7269 #endif
7270 
7271 #ifndef MA_ZERO_MEMORY
7272 #ifdef MA_WIN32
7273 #define MA_ZERO_MEMORY(p, sz) ZeroMemory((p), (sz))
7274 #else
7275 #define MA_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
7276 #endif
7277 #endif
7278 
7279 #ifndef MA_COPY_MEMORY
7280 #ifdef MA_WIN32
7281 #define MA_COPY_MEMORY(dst, src, sz) CopyMemory((dst), (src), (sz))
7282 #else
7283 #define MA_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
7284 #endif
7285 #endif
7286 
7287 #ifndef MA_MOVE_MEMORY
7288 #ifdef MA_WIN32
7289 #define MA_MOVE_MEMORY(dst, src, sz) MoveMemory((dst), (src), (sz))
7290 #else
7291 #define MA_MOVE_MEMORY(dst, src, sz) memmove((dst), (src), (sz))
7292 #endif
7293 #endif
7294 
7295 #ifndef MA_ASSERT
7296 #ifdef MA_WIN32
7297 #define MA_ASSERT(condition) assert(condition)
7298 #else
7299 #define MA_ASSERT(condition) assert(condition)
7300 #endif
7301 #endif
7302 
7303 #define MA_ZERO_OBJECT(p) MA_ZERO_MEMORY((p), sizeof(*(p)))
7304 
7305 #define ma_countof(x) (sizeof(x) / sizeof(x[0]))
7306 #define ma_max(x, y) (((x) > (y)) ? (x) : (y))
7307 #define ma_min(x, y) (((x) < (y)) ? (x) : (y))
7308 #define ma_abs(x) (((x) > 0) ? (x) : -(x))
7309 #define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
7310 #define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
7311 #define ma_align(x, a) ((x + (a-1)) & ~(a-1))
7312 #define ma_align_64(x) ma_align(x, 8)
7313 
7314 #define ma_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / ma_get_bytes_per_sample(format) / (channels))
7315 
7316 static MA_INLINE double ma_sind(double x)
7317 {
7318  /* TODO: Implement custom sin(x). */
7319  return sin(x);
7320 }
7321 
7322 static MA_INLINE double ma_expd(double x)
7323 {
7324  /* TODO: Implement custom exp(x). */
7325  return exp(x);
7326 }
7327 
7328 static MA_INLINE double ma_logd(double x)
7329 {
7330  /* TODO: Implement custom log(x). */
7331  return log(x);
7332 }
7333 
7334 static MA_INLINE double ma_powd(double x, double y)
7335 {
7336  /* TODO: Implement custom pow(x, y). */
7337  return pow(x, y);
7338 }
7339 
7340 static MA_INLINE double ma_sqrtd(double x)
7341 {
7342  /* TODO: Implement custom sqrt(x). */
7343  return sqrt(x);
7344 }
7345 
7346 
7347 static MA_INLINE double ma_cosd(double x)
7348 {
7349  return ma_sind((MA_PI_D*0.5) - x);
7350 }
7351 
7352 static MA_INLINE double ma_log10d(double x)
7353 {
7354  return ma_logd(x) * 0.43429448190325182765;
7355 }
7356 
7357 static MA_INLINE float ma_powf(float x, float y)
7358 {
7359  return (float)ma_powd((double)x, (double)y);
7360 }
7361 
7362 static MA_INLINE float ma_log10f(float x)
7363 {
7364  return (float)ma_log10d((double)x);
7365 }
7366 
7367 
7368 static MA_INLINE double ma_degrees_to_radians(double degrees)
7369 {
7370  return degrees * 0.01745329252;
7371 }
7372 
7373 static MA_INLINE double ma_radians_to_degrees(double radians)
7374 {
7375  return radians * 57.295779512896;
7376 }
7377 
7378 static MA_INLINE float ma_degrees_to_radians_f(float degrees)
7379 {
7380  return degrees * 0.01745329252f;
7381 }
7382 
7383 static MA_INLINE float ma_radians_to_degrees_f(float radians)
7384 {
7385  return radians * 57.295779512896f;
7386 }
7387 
7388 
7389 /*
7390 Return Values:
7391  0: Success
7392  22: EINVAL
7393  34: ERANGE
7394 
7395 Not using symbolic constants for errors because I want to avoid #including errno.h
7396 */
7397 MA_API int ma_strcpy_s(char* dst, size_t dstSizeInBytes, const char* src)
7398 {
7399  size_t i;
7400 
7401  if (dst == 0) {
7402  return 22;
7403  }
7404  if (dstSizeInBytes == 0) {
7405  return 34;
7406  }
7407  if (src == 0) {
7408  dst[0] = '\0';
7409  return 22;
7410  }
7411 
7412  for (i = 0; i < dstSizeInBytes && src[i] != '\0'; ++i) {
7413  dst[i] = src[i];
7414  }
7415 
7416  if (i < dstSizeInBytes) {
7417  dst[i] = '\0';
7418  return 0;
7419  }
7420 
7421  dst[0] = '\0';
7422  return 34;
7423 }
7424 
7425 MA_API int ma_wcscpy_s(wchar_t* dst, size_t dstCap, const wchar_t* src)
7426 {
7427  size_t i;
7428 
7429  if (dst == 0) {
7430  return 22;
7431  }
7432  if (dstCap == 0) {
7433  return 34;
7434  }
7435  if (src == 0) {
7436  dst[0] = '\0';
7437  return 22;
7438  }
7439 
7440  for (i = 0; i < dstCap && src[i] != '\0'; ++i) {
7441  dst[i] = src[i];
7442  }
7443 
7444  if (i < dstCap) {
7445  dst[i] = '\0';
7446  return 0;
7447  }
7448 
7449  dst[0] = '\0';
7450  return 34;
7451 }
7452 
7453 
7454 MA_API int ma_strncpy_s(char* dst, size_t dstSizeInBytes, const char* src, size_t count)
7455 {
7456  size_t maxcount;
7457  size_t i;
7458 
7459  if (dst == 0) {
7460  return 22;
7461  }
7462  if (dstSizeInBytes == 0) {
7463  return 34;
7464  }
7465  if (src == 0) {
7466  dst[0] = '\0';
7467  return 22;
7468  }
7469 
7470  maxcount = count;
7471  if (count == ((size_t)-1) || count >= dstSizeInBytes) { /* -1 = _TRUNCATE */
7472  maxcount = dstSizeInBytes - 1;
7473  }
7474 
7475  for (i = 0; i < maxcount && src[i] != '\0'; ++i) {
7476  dst[i] = src[i];
7477  }
7478 
7479  if (src[i] == '\0' || i == count || count == ((size_t)-1)) {
7480  dst[i] = '\0';
7481  return 0;
7482  }
7483 
7484  dst[0] = '\0';
7485  return 34;
7486 }
7487 
7488 MA_API int ma_strcat_s(char* dst, size_t dstSizeInBytes, const char* src)
7489 {
7490  char* dstorig;
7491 
7492  if (dst == 0) {
7493  return 22;
7494  }
7495  if (dstSizeInBytes == 0) {
7496  return 34;
7497  }
7498  if (src == 0) {
7499  dst[0] = '\0';
7500  return 22;
7501  }
7502 
7503  dstorig = dst;
7504 
7505  while (dstSizeInBytes > 0 && dst[0] != '\0') {
7506  dst += 1;
7507  dstSizeInBytes -= 1;
7508  }
7509 
7510  if (dstSizeInBytes == 0) {
7511  return 22; /* Unterminated. */
7512  }
7513 
7514 
7515  while (dstSizeInBytes > 0 && src[0] != '\0') {
7516  *dst++ = *src++;
7517  dstSizeInBytes -= 1;
7518  }
7519 
7520  if (dstSizeInBytes > 0) {
7521  dst[0] = '\0';
7522  } else {
7523  dstorig[0] = '\0';
7524  return 34;
7525  }
7526 
7527  return 0;
7528 }
7529 
7530 MA_API int ma_strncat_s(char* dst, size_t dstSizeInBytes, const char* src, size_t count)
7531 {
7532  char* dstorig;
7533 
7534  if (dst == 0) {
7535  return 22;
7536  }
7537  if (dstSizeInBytes == 0) {
7538  return 34;
7539  }
7540  if (src == 0) {
7541  return 22;
7542  }
7543 
7544  dstorig = dst;
7545 
7546  while (dstSizeInBytes > 0 && dst[0] != '\0') {
7547  dst += 1;
7548  dstSizeInBytes -= 1;
7549  }
7550 
7551  if (dstSizeInBytes == 0) {
7552  return 22; /* Unterminated. */
7553  }
7554 
7555 
7556  if (count == ((size_t)-1)) { /* _TRUNCATE */
7557  count = dstSizeInBytes - 1;
7558  }
7559 
7560  while (dstSizeInBytes > 0 && src[0] != '\0' && count > 0) {
7561  *dst++ = *src++;
7562  dstSizeInBytes -= 1;
7563  count -= 1;
7564  }
7565 
7566  if (dstSizeInBytes > 0) {
7567  dst[0] = '\0';
7568  } else {
7569  dstorig[0] = '\0';
7570  return 34;
7571  }
7572 
7573  return 0;
7574 }
7575 
7576 MA_API int ma_itoa_s(int value, char* dst, size_t dstSizeInBytes, int radix)
7577 {
7578  int sign;
7579  unsigned int valueU;
7580  char* dstEnd;
7581 
7582  if (dst == NULL || dstSizeInBytes == 0) {
7583  return 22;
7584  }
7585  if (radix < 2 || radix > 36) {
7586  dst[0] = '\0';
7587  return 22;
7588  }
7589 
7590  sign = (value < 0 && radix == 10) ? -1 : 1; /* The negative sign is only used when the base is 10. */
7591 
7592  if (value < 0) {
7593  valueU = -value;
7594  } else {
7595  valueU = value;
7596  }
7597 
7598  dstEnd = dst;
7599  do
7600  {
7601  int remainder = valueU % radix;
7602  if (remainder > 9) {
7603  *dstEnd = (char)((remainder - 10) + 'a');
7604  } else {
7605  *dstEnd = (char)(remainder + '0');
7606  }
7607 
7608  dstEnd += 1;
7609  dstSizeInBytes -= 1;
7610  valueU /= radix;
7611  } while (dstSizeInBytes > 0 && valueU > 0);
7612 
7613  if (dstSizeInBytes == 0) {
7614  dst[0] = '\0';
7615  return 22; /* Ran out of room in the output buffer. */
7616  }
7617 
7618  if (sign < 0) {
7619  *dstEnd++ = '-';
7620  dstSizeInBytes -= 1;
7621  }
7622 
7623  if (dstSizeInBytes == 0) {
7624  dst[0] = '\0';
7625  return 22; /* Ran out of room in the output buffer. */
7626  }
7627 
7628  *dstEnd = '\0';
7629 
7630 
7631  /* At this point the string will be reversed. */
7632  dstEnd -= 1;
7633  while (dst < dstEnd) {
7634  char temp = *dst;
7635  *dst = *dstEnd;
7636  *dstEnd = temp;
7637 
7638  dst += 1;
7639  dstEnd -= 1;
7640  }
7641 
7642  return 0;
7643 }
7644 
7645 MA_API int ma_strcmp(const char* str1, const char* str2)
7646 {
7647  if (str1 == str2) return 0;
7648 
7649  /* These checks differ from the standard implementation. It's not important, but I prefer it just for sanity. */
7650  if (str1 == NULL) return -1;
7651  if (str2 == NULL) return 1;
7652 
7653  for (;;) {
7654  if (str1[0] == '\0') {
7655  break;
7656  }
7657  if (str1[0] != str2[0]) {
7658  break;
7659  }
7660 
7661  str1 += 1;
7662  str2 += 1;
7663  }
7664 
7665  return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
7666 }
7667 
7668 MA_API int ma_strappend(char* dst, size_t dstSize, const char* srcA, const char* srcB)
7669 {
7670  int result;
7671 
7672  result = ma_strncpy_s(dst, dstSize, srcA, (size_t)-1);
7673  if (result != 0) {
7674  return result;
7675  }
7676 
7677  result = ma_strncat_s(dst, dstSize, srcB, (size_t)-1);
7678  if (result != 0) {
7679  return result;
7680  }
7681 
7682  return result;
7683 }
7684 
7685 MA_API char* ma_copy_string(const char* src, const ma_allocation_callbacks* pAllocationCallbacks)
7686 {
7687  size_t sz = strlen(src)+1;
7688  char* dst = (char*)ma_malloc(sz, pAllocationCallbacks);
7689  if (dst == NULL) {
7690  return NULL;
7691  }
7692 
7693  ma_strcpy_s(dst, sz, src);
7694 
7695  return dst;
7696 }
7697 
7698 MA_API wchar_t* ma_copy_string_w(const wchar_t* src, const ma_allocation_callbacks* pAllocationCallbacks)
7699 {
7700  size_t sz = wcslen(src)+1;
7701  wchar_t* dst = (wchar_t*)ma_malloc(sz * sizeof(*dst), pAllocationCallbacks);
7702  if (dst == NULL) {
7703  return NULL;
7704  }
7705 
7706  ma_wcscpy_s(dst, sz, src);
7707 
7708  return dst;
7709 }
7710 
7711 
7712 #include <errno.h>
7713 static ma_result ma_result_from_errno(int e)
7714 {
7715  switch (e)
7716  {
7717  case 0: return MA_SUCCESS;
7718  #ifdef EPERM
7719  case EPERM: return MA_INVALID_OPERATION;
7720  #endif
7721  #ifdef ENOENT
7722  case ENOENT: return MA_DOES_NOT_EXIST;
7723  #endif
7724  #ifdef ESRCH
7725  case ESRCH: return MA_DOES_NOT_EXIST;
7726  #endif
7727  #ifdef EINTR
7728  case EINTR: return MA_INTERRUPT;
7729  #endif
7730  #ifdef EIO
7731  case EIO: return MA_IO_ERROR;
7732  #endif
7733  #ifdef ENXIO
7734  case ENXIO: return MA_DOES_NOT_EXIST;
7735  #endif
7736  #ifdef E2BIG
7737  case E2BIG: return MA_INVALID_ARGS;
7738  #endif
7739  #ifdef ENOEXEC
7740  case ENOEXEC: return MA_INVALID_FILE;
7741  #endif
7742  #ifdef EBADF
7743  case EBADF: return MA_INVALID_FILE;
7744  #endif
7745  #ifdef ECHILD
7746  case ECHILD: return MA_ERROR;
7747  #endif
7748  #ifdef EAGAIN
7749  case EAGAIN: return MA_UNAVAILABLE;
7750  #endif
7751  #ifdef ENOMEM
7752  case ENOMEM: return MA_OUT_OF_MEMORY;
7753  #endif
7754  #ifdef EACCES
7755  case EACCES: return MA_ACCESS_DENIED;
7756  #endif
7757  #ifdef EFAULT
7758  case EFAULT: return MA_BAD_ADDRESS;
7759  #endif
7760  #ifdef ENOTBLK
7761  case ENOTBLK: return MA_ERROR;
7762  #endif
7763  #ifdef EBUSY
7764  case EBUSY: return MA_BUSY;
7765  #endif
7766  #ifdef EEXIST
7767  case EEXIST: return MA_ALREADY_EXISTS;
7768  #endif
7769  #ifdef EXDEV
7770  case EXDEV: return MA_ERROR;
7771  #endif
7772  #ifdef ENODEV
7773  case ENODEV: return MA_DOES_NOT_EXIST;
7774  #endif
7775  #ifdef ENOTDIR
7776  case ENOTDIR: return MA_NOT_DIRECTORY;
7777  #endif
7778  #ifdef EISDIR
7779  case EISDIR: return MA_IS_DIRECTORY;
7780  #endif
7781  #ifdef EINVAL
7782  case EINVAL: return MA_INVALID_ARGS;
7783  #endif
7784  #ifdef ENFILE
7785  case ENFILE: return MA_TOO_MANY_OPEN_FILES;
7786  #endif
7787  #ifdef EMFILE
7788  case EMFILE: return MA_TOO_MANY_OPEN_FILES;
7789  #endif
7790  #ifdef ENOTTY
7791  case ENOTTY: return MA_INVALID_OPERATION;
7792  #endif
7793  #ifdef ETXTBSY
7794  case ETXTBSY: return MA_BUSY;
7795  #endif
7796  #ifdef EFBIG
7797  case EFBIG: return MA_TOO_BIG;
7798  #endif
7799  #ifdef ENOSPC
7800  case ENOSPC: return MA_NO_SPACE;
7801  #endif
7802  #ifdef ESPIPE
7803  case ESPIPE: return MA_BAD_SEEK;
7804  #endif
7805  #ifdef EROFS
7806  case EROFS: return MA_ACCESS_DENIED;
7807  #endif
7808  #ifdef EMLINK
7809  case EMLINK: return MA_TOO_MANY_LINKS;
7810  #endif
7811  #ifdef EPIPE
7812  case EPIPE: return MA_BAD_PIPE;
7813  #endif
7814  #ifdef EDOM
7815  case EDOM: return MA_OUT_OF_RANGE;
7816  #endif
7817  #ifdef ERANGE
7818  case ERANGE: return MA_OUT_OF_RANGE;
7819  #endif
7820  #ifdef EDEADLK
7821  case EDEADLK: return MA_DEADLOCK;
7822  #endif
7823  #ifdef ENAMETOOLONG
7824  case ENAMETOOLONG: return MA_PATH_TOO_LONG;
7825  #endif
7826  #ifdef ENOLCK
7827  case ENOLCK: return MA_ERROR;
7828  #endif
7829  #ifdef ENOSYS
7830  case ENOSYS: return MA_NOT_IMPLEMENTED;
7831  #endif
7832  #ifdef ENOTEMPTY
7833  case ENOTEMPTY: return MA_DIRECTORY_NOT_EMPTY;
7834  #endif
7835  #ifdef ELOOP
7836  case ELOOP: return MA_TOO_MANY_LINKS;
7837  #endif
7838  #ifdef ENOMSG
7839  case ENOMSG: return MA_NO_MESSAGE;
7840  #endif
7841  #ifdef EIDRM
7842  case EIDRM: return MA_ERROR;
7843  #endif
7844  #ifdef ECHRNG
7845  case ECHRNG: return MA_ERROR;
7846  #endif
7847  #ifdef EL2NSYNC
7848  case EL2NSYNC: return MA_ERROR;
7849  #endif
7850  #ifdef EL3HLT
7851  case EL3HLT: return MA_ERROR;
7852  #endif
7853  #ifdef EL3RST
7854  case EL3RST: return MA_ERROR;
7855  #endif
7856  #ifdef ELNRNG
7857  case ELNRNG: return MA_OUT_OF_RANGE;
7858  #endif
7859  #ifdef EUNATCH
7860  case EUNATCH: return MA_ERROR;
7861  #endif
7862  #ifdef ENOCSI
7863  case ENOCSI: return MA_ERROR;
7864  #endif
7865  #ifdef EL2HLT
7866  case EL2HLT: return MA_ERROR;
7867  #endif
7868  #ifdef EBADE
7869  case EBADE: return MA_ERROR;
7870  #endif
7871  #ifdef EBADR
7872  case EBADR: return MA_ERROR;
7873  #endif
7874  #ifdef EXFULL
7875  case EXFULL: return MA_ERROR;
7876  #endif
7877  #ifdef ENOANO
7878  case ENOANO: return MA_ERROR;
7879  #endif
7880  #ifdef EBADRQC
7881  case EBADRQC: return MA_ERROR;
7882  #endif
7883  #ifdef EBADSLT
7884  case EBADSLT: return MA_ERROR;
7885  #endif
7886  #ifdef EBFONT
7887  case EBFONT: return MA_INVALID_FILE;
7888  #endif
7889  #ifdef ENOSTR
7890  case ENOSTR: return MA_ERROR;
7891  #endif
7892  #ifdef ENODATA
7893  case ENODATA: return MA_NO_DATA_AVAILABLE;
7894  #endif
7895  #ifdef ETIME
7896  case ETIME: return MA_TIMEOUT;
7897  #endif
7898  #ifdef ENOSR
7899  case ENOSR: return MA_NO_DATA_AVAILABLE;
7900  #endif
7901  #ifdef ENONET
7902  case ENONET: return MA_NO_NETWORK;
7903  #endif
7904  #ifdef ENOPKG
7905  case ENOPKG: return MA_ERROR;
7906  #endif
7907  #ifdef EREMOTE
7908  case EREMOTE: return MA_ERROR;
7909  #endif
7910  #ifdef ENOLINK
7911  case ENOLINK: return MA_ERROR;
7912  #endif
7913  #ifdef EADV
7914  case EADV: return MA_ERROR;
7915  #endif
7916  #ifdef ESRMNT
7917  case ESRMNT: return MA_ERROR;
7918  #endif
7919  #ifdef ECOMM
7920  case ECOMM: return MA_ERROR;
7921  #endif
7922  #ifdef EPROTO
7923  case EPROTO: return MA_ERROR;
7924  #endif
7925  #ifdef EMULTIHOP
7926  case EMULTIHOP: return MA_ERROR;
7927  #endif
7928  #ifdef EDOTDOT
7929  case EDOTDOT: return MA_ERROR;
7930  #endif
7931  #ifdef EBADMSG
7932  case EBADMSG: return MA_BAD_MESSAGE;
7933  #endif
7934  #ifdef EOVERFLOW
7935  case EOVERFLOW: return MA_TOO_BIG;
7936  #endif
7937  #ifdef ENOTUNIQ
7938  case ENOTUNIQ: return MA_NOT_UNIQUE;
7939  #endif
7940  #ifdef EBADFD
7941  case EBADFD: return MA_ERROR;
7942  #endif
7943  #ifdef EREMCHG
7944  case EREMCHG: return MA_ERROR;
7945  #endif
7946  #ifdef ELIBACC
7947  case ELIBACC: return MA_ACCESS_DENIED;
7948  #endif
7949  #ifdef ELIBBAD
7950  case ELIBBAD: return MA_INVALID_FILE;
7951  #endif
7952  #ifdef ELIBSCN
7953  case ELIBSCN: return MA_INVALID_FILE;
7954  #endif
7955  #ifdef ELIBMAX
7956  case ELIBMAX: return MA_ERROR;
7957  #endif
7958  #ifdef ELIBEXEC
7959  case ELIBEXEC: return MA_ERROR;
7960  #endif
7961  #ifdef EILSEQ
7962  case EILSEQ: return MA_INVALID_DATA;
7963  #endif
7964  #ifdef ERESTART
7965  case ERESTART: return MA_ERROR;
7966  #endif
7967  #ifdef ESTRPIPE
7968  case ESTRPIPE: return MA_ERROR;
7969  #endif
7970  #ifdef EUSERS
7971  case EUSERS: return MA_ERROR;
7972  #endif
7973  #ifdef ENOTSOCK
7974  case ENOTSOCK: return MA_NOT_SOCKET;
7975  #endif
7976  #ifdef EDESTADDRREQ
7977  case EDESTADDRREQ: return MA_NO_ADDRESS;
7978  #endif
7979  #ifdef EMSGSIZE
7980  case EMSGSIZE: return MA_TOO_BIG;
7981  #endif
7982  #ifdef EPROTOTYPE
7983  case EPROTOTYPE: return MA_BAD_PROTOCOL;
7984  #endif
7985  #ifdef ENOPROTOOPT
7986  case ENOPROTOOPT: return MA_PROTOCOL_UNAVAILABLE;
7987  #endif
7988  #ifdef EPROTONOSUPPORT
7989  case EPROTONOSUPPORT: return MA_PROTOCOL_NOT_SUPPORTED;
7990  #endif
7991  #ifdef ESOCKTNOSUPPORT
7992  case ESOCKTNOSUPPORT: return MA_SOCKET_NOT_SUPPORTED;
7993  #endif
7994  #ifdef EOPNOTSUPP
7995  case EOPNOTSUPP: return MA_INVALID_OPERATION;
7996  #endif
7997  #ifdef EPFNOSUPPORT
7998  case EPFNOSUPPORT: return MA_PROTOCOL_FAMILY_NOT_SUPPORTED;
7999  #endif
8000  #ifdef EAFNOSUPPORT
8001  case EAFNOSUPPORT: return MA_ADDRESS_FAMILY_NOT_SUPPORTED;
8002  #endif
8003  #ifdef EADDRINUSE
8004  case EADDRINUSE: return MA_ALREADY_IN_USE;
8005  #endif
8006  #ifdef EADDRNOTAVAIL
8007  case EADDRNOTAVAIL: return MA_ERROR;
8008  #endif
8009  #ifdef ENETDOWN
8010  case ENETDOWN: return MA_NO_NETWORK;
8011  #endif
8012  #ifdef ENETUNREACH
8013  case ENETUNREACH: return MA_NO_NETWORK;
8014  #endif
8015  #ifdef ENETRESET
8016  case ENETRESET: return MA_NO_NETWORK;
8017  #endif
8018  #ifdef ECONNABORTED
8019  case ECONNABORTED: return MA_NO_NETWORK;
8020  #endif
8021  #ifdef ECONNRESET
8022  case ECONNRESET: return MA_CONNECTION_RESET;
8023  #endif
8024  #ifdef ENOBUFS
8025  case ENOBUFS: return MA_NO_SPACE;
8026  #endif
8027  #ifdef EISCONN
8028  case EISCONN: return MA_ALREADY_CONNECTED;
8029  #endif
8030  #ifdef ENOTCONN
8031  case ENOTCONN: return MA_NOT_CONNECTED;
8032  #endif
8033  #ifdef ESHUTDOWN
8034  case ESHUTDOWN: return MA_ERROR;
8035  #endif
8036  #ifdef ETOOMANYREFS
8037  case ETOOMANYREFS: return MA_ERROR;
8038  #endif
8039  #ifdef ETIMEDOUT
8040  case ETIMEDOUT: return MA_TIMEOUT;
8041  #endif
8042  #ifdef ECONNREFUSED
8043  case ECONNREFUSED: return MA_CONNECTION_REFUSED;
8044  #endif
8045  #ifdef EHOSTDOWN
8046  case EHOSTDOWN: return MA_NO_HOST;
8047  #endif
8048  #ifdef EHOSTUNREACH
8049  case EHOSTUNREACH: return MA_NO_HOST;
8050  #endif
8051  #ifdef EALREADY
8052  case EALREADY: return MA_IN_PROGRESS;
8053  #endif
8054  #ifdef EINPROGRESS
8055  case EINPROGRESS: return MA_IN_PROGRESS;
8056  #endif
8057  #ifdef ESTALE
8058  case ESTALE: return MA_INVALID_FILE;
8059  #endif
8060  #ifdef EUCLEAN
8061  case EUCLEAN: return MA_ERROR;
8062  #endif
8063  #ifdef ENOTNAM
8064  case ENOTNAM: return MA_ERROR;
8065  #endif
8066  #ifdef ENAVAIL
8067  case ENAVAIL: return MA_ERROR;
8068  #endif
8069  #ifdef EISNAM
8070  case EISNAM: return MA_ERROR;
8071  #endif
8072  #ifdef EREMOTEIO
8073  case EREMOTEIO: return MA_IO_ERROR;
8074  #endif
8075  #ifdef EDQUOT
8076  case EDQUOT: return MA_NO_SPACE;
8077  #endif
8078  #ifdef ENOMEDIUM
8079  case ENOMEDIUM: return MA_DOES_NOT_EXIST;
8080  #endif
8081  #ifdef EMEDIUMTYPE
8082  case EMEDIUMTYPE: return MA_ERROR;
8083  #endif
8084  #ifdef ECANCELED
8085  case ECANCELED: return MA_CANCELLED;
8086  #endif
8087  #ifdef ENOKEY
8088  case ENOKEY: return MA_ERROR;
8089  #endif
8090  #ifdef EKEYEXPIRED
8091  case EKEYEXPIRED: return MA_ERROR;
8092  #endif
8093  #ifdef EKEYREVOKED
8094  case EKEYREVOKED: return MA_ERROR;
8095  #endif
8096  #ifdef EKEYREJECTED
8097  case EKEYREJECTED: return MA_ERROR;
8098  #endif
8099  #ifdef EOWNERDEAD
8100  case EOWNERDEAD: return MA_ERROR;
8101  #endif
8102  #ifdef ENOTRECOVERABLE
8103  case ENOTRECOVERABLE: return MA_ERROR;
8104  #endif
8105  #ifdef ERFKILL
8106  case ERFKILL: return MA_ERROR;
8107  #endif
8108  #ifdef EHWPOISON
8109  case EHWPOISON: return MA_ERROR;
8110  #endif
8111  default: return MA_ERROR;
8112  }
8113 }
8114 
8115 MA_API ma_result ma_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
8116 {
8117 #if defined(_MSC_VER) && _MSC_VER >= 1400
8118  errno_t err;
8119 #endif
8120 
8121  if (ppFile != NULL) {
8122  *ppFile = NULL; /* Safety. */
8123  }
8124 
8125  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
8126  return MA_INVALID_ARGS;
8127  }
8128 
8129 #if defined(_MSC_VER) && _MSC_VER >= 1400
8130  err = fopen_s(ppFile, pFilePath, pOpenMode);
8131  if (err != 0) {
8132  return ma_result_from_errno(err);
8133  }
8134 #else
8135 #if defined(_WIN32) || defined(__APPLE__)
8136  *ppFile = fopen(pFilePath, pOpenMode);
8137 #else
8138  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
8139  *ppFile = fopen64(pFilePath, pOpenMode);
8140  #else
8141  *ppFile = fopen(pFilePath, pOpenMode);
8142  #endif
8143 #endif
8144  if (*ppFile == NULL) {
8146  if (result == MA_SUCCESS) {
8147  result = MA_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
8148  }
8149 
8150  return result;
8151  }
8152 #endif
8153 
8154  return MA_SUCCESS;
8155 }
8156 
8157 
8158 
8159 /*
8160 _wfopen() isn't always available in all compilation environments.
8161 
8162  * Windows only.
8163  * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
8164  * MinGW-64 (both 32- and 64-bit) seems to support it.
8165  * MinGW wraps it in !defined(__STRICT_ANSI__).
8166  * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
8167 
8168 This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
8169 fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
8170 */
8171 #if defined(_WIN32)
8172  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
8173  #define MA_HAS_WFOPEN
8174  #endif
8175 #endif
8176 
8177 MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const ma_allocation_callbacks* pAllocationCallbacks)
8178 {
8179  if (ppFile != NULL) {
8180  *ppFile = NULL; /* Safety. */
8181  }
8182 
8183  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
8184  return MA_INVALID_ARGS;
8185  }
8186 
8187 #if defined(MA_HAS_WFOPEN)
8188  {
8189  /* Use _wfopen() on Windows. */
8190  #if defined(_MSC_VER) && _MSC_VER >= 1400
8191  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
8192  if (err != 0) {
8193  return ma_result_from_errno(err);
8194  }
8195  #else
8196  *ppFile = _wfopen(pFilePath, pOpenMode);
8197  if (*ppFile == NULL) {
8198  return ma_result_from_errno(errno);
8199  }
8200  #endif
8201  (void)pAllocationCallbacks;
8202  }
8203 #else
8204  /*
8205  Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
8206  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
8207  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.
8208  */
8209  {
8210  mbstate_t mbs;
8211  size_t lenMB;
8212  const wchar_t* pFilePathTemp = pFilePath;
8213  char* pFilePathMB = NULL;
8214  char pOpenModeMB[32] = {0};
8215 
8216  /* Get the length first. */
8217  MA_ZERO_OBJECT(&mbs);
8218  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
8219  if (lenMB == (size_t)-1) {
8220  return ma_result_from_errno(errno);
8221  }
8222 
8223  pFilePathMB = (char*)ma_malloc(lenMB + 1, pAllocationCallbacks);
8224  if (pFilePathMB == NULL) {
8225  return MA_OUT_OF_MEMORY;
8226  }
8227 
8228  pFilePathTemp = pFilePath;
8229  MA_ZERO_OBJECT(&mbs);
8230  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
8231 
8232  /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
8233  {
8234  size_t i = 0;
8235  for (;;) {
8236  if (pOpenMode[i] == 0) {
8237  pOpenModeMB[i] = '\0';
8238  break;
8239  }
8240 
8241  pOpenModeMB[i] = (char)pOpenMode[i];
8242  i += 1;
8243  }
8244  }
8245 
8246  *ppFile = fopen(pFilePathMB, pOpenModeMB);
8247 
8248  ma_free(pFilePathMB, pAllocationCallbacks);
8249  }
8250 
8251  if (*ppFile == NULL) {
8252  return MA_ERROR;
8253  }
8254 #endif
8255 
8256  return MA_SUCCESS;
8257 }
8258 
8259 
8260 
8261 static MA_INLINE void ma_copy_memory_64(void* dst, const void* src, ma_uint64 sizeInBytes)
8262 {
8263 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
8264  MA_COPY_MEMORY(dst, src, (size_t)sizeInBytes);
8265 #else
8266  while (sizeInBytes > 0) {
8267  ma_uint64 bytesToCopyNow = sizeInBytes;
8268  if (bytesToCopyNow > MA_SIZE_MAX) {
8269  bytesToCopyNow = MA_SIZE_MAX;
8270  }
8271 
8272  MA_COPY_MEMORY(dst, src, (size_t)bytesToCopyNow); /* Safe cast to size_t. */
8273 
8274  sizeInBytes -= bytesToCopyNow;
8275  dst = ( void*)(( ma_uint8*)dst + bytesToCopyNow);
8276  src = (const void*)((const ma_uint8*)src + bytesToCopyNow);
8277  }
8278 #endif
8279 }
8280 
8281 static MA_INLINE void ma_zero_memory_64(void* dst, ma_uint64 sizeInBytes)
8282 {
8283 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
8284  MA_ZERO_MEMORY(dst, (size_t)sizeInBytes);
8285 #else
8286  while (sizeInBytes > 0) {
8287  ma_uint64 bytesToZeroNow = sizeInBytes;
8288  if (bytesToZeroNow > MA_SIZE_MAX) {
8289  bytesToZeroNow = MA_SIZE_MAX;
8290  }
8291 
8292  MA_ZERO_MEMORY(dst, (size_t)bytesToZeroNow); /* Safe cast to size_t. */
8293 
8294  sizeInBytes -= bytesToZeroNow;
8295  dst = (void*)((ma_uint8*)dst + bytesToZeroNow);
8296  }
8297 #endif
8298 }
8299 
8300 
8301 /* Thanks to good old Bit Twiddling Hacks for this one: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
8302 static MA_INLINE unsigned int ma_next_power_of_2(unsigned int x)
8303 {
8304  x--;
8305  x |= x >> 1;
8306  x |= x >> 2;
8307  x |= x >> 4;
8308  x |= x >> 8;
8309  x |= x >> 16;
8310  x++;
8311 
8312  return x;
8313 }
8314 
8315 static MA_INLINE unsigned int ma_prev_power_of_2(unsigned int x)
8316 {
8317  return ma_next_power_of_2(x) >> 1;
8318 }
8319 
8320 static MA_INLINE unsigned int ma_round_to_power_of_2(unsigned int x)
8321 {
8322  unsigned int prev = ma_prev_power_of_2(x);
8323  unsigned int next = ma_next_power_of_2(x);
8324  if ((next - x) > (x - prev)) {
8325  return prev;
8326  } else {
8327  return next;
8328  }
8329 }
8330 
8331 static MA_INLINE unsigned int ma_count_set_bits(unsigned int x)
8332 {
8333  unsigned int count = 0;
8334  while (x != 0) {
8335  if (x & 1) {
8336  count += 1;
8337  }
8338 
8339  x = x >> 1;
8340  }
8341 
8342  return count;
8343 }
8344 
8345 
8346 
8347 /**************************************************************************************************************************************************************
8348 
8349 Allocation Callbacks
8350 
8351 **************************************************************************************************************************************************************/
8352 static void* ma__malloc_default(size_t sz, void* pUserData)
8353 {
8354  (void)pUserData;
8355  return MA_MALLOC(sz);
8356 }
8357 
8358 static void* ma__realloc_default(void* p, size_t sz, void* pUserData)
8359 {
8360  (void)pUserData;
8361  return MA_REALLOC(p, sz);
8362 }
8363 
8364 static void ma__free_default(void* p, void* pUserData)
8365 {
8366  (void)pUserData;
8367  MA_FREE(p);
8368 }
8369 
8370 
8371 static void* ma__malloc_from_callbacks(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
8372 {
8373  if (pAllocationCallbacks == NULL) {
8374  return NULL;
8375  }
8376 
8377  if (pAllocationCallbacks->onMalloc != NULL) {
8378  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
8379  }
8380 
8381  /* Try using realloc(). */
8382  if (pAllocationCallbacks->onRealloc != NULL) {
8383  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
8384  }
8385 
8386  return NULL;
8387 }
8388 
8389 static void* ma__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const ma_allocation_callbacks* pAllocationCallbacks)
8390 {
8391  if (pAllocationCallbacks == NULL) {
8392  return NULL;
8393  }
8394 
8395  if (pAllocationCallbacks->onRealloc != NULL) {
8396  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
8397  }
8398 
8399  /* Try emulating realloc() in terms of malloc()/free(). */
8400  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
8401  void* p2;
8402 
8403  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
8404  if (p2 == NULL) {
8405  return NULL;
8406  }
8407 
8408  if (p != NULL) {
8409  MA_COPY_MEMORY(p2, p, szOld);
8410  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
8411  }
8412 
8413  return p2;
8414  }
8415 
8416  return NULL;
8417 }
8418 
8419 static MA_INLINE void* ma__calloc_from_callbacks(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
8420 {
8421  void* p = ma__malloc_from_callbacks(sz, pAllocationCallbacks);
8422  if (p != NULL) {
8423  MA_ZERO_MEMORY(p, sz);
8424  }
8425 
8426  return p;
8427 }
8428 
8429 static void ma__free_from_callbacks(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
8430 {
8431  if (p == NULL || pAllocationCallbacks == NULL) {
8432  return;
8433  }
8434 
8435  if (pAllocationCallbacks->onFree != NULL) {
8436  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
8437  }
8438 }
8439 
8441 {
8442  ma_allocation_callbacks callbacks;
8443  callbacks.pUserData = NULL;
8444  callbacks.onMalloc = ma__malloc_default;
8445  callbacks.onRealloc = ma__realloc_default;
8446  callbacks.onFree = ma__free_default;
8447 
8448  return callbacks;
8449 }
8450 
8452 {
8453  if (pDst == NULL) {
8454  return MA_INVALID_ARGS;
8455  }
8456 
8457  if (pSrc == NULL) {
8459  } else {
8460  if (pSrc->pUserData == NULL && pSrc->onFree == NULL && pSrc->onMalloc == NULL && pSrc->onRealloc == NULL) {
8462  } else {
8463  if (pSrc->onFree == NULL || (pSrc->onMalloc == NULL && pSrc->onRealloc == NULL)) {
8464  return MA_INVALID_ARGS; /* Invalid allocation callbacks. */
8465  } else {
8466  *pDst = *pSrc;
8467  }
8468  }
8469  }
8470 
8471  return MA_SUCCESS;
8472 }
8473 
8474 
8475 
8476 
8477 /**************************************************************************************************************************************************************
8478 
8479 Logging
8480 
8481 **************************************************************************************************************************************************************/
8482 MA_API const char* ma_log_level_to_string(ma_uint32 logLevel)
8483 {
8484  switch (logLevel)
8485  {
8486  case MA_LOG_LEVEL_DEBUG: return "DEBUG";
8487  case MA_LOG_LEVEL_INFO: return "INFO";
8488  case MA_LOG_LEVEL_WARNING: return "WARNING";
8489  case MA_LOG_LEVEL_ERROR: return "ERROR";
8490  default: return "ERROR";
8491  }
8492 }
8493 
8494 #if defined(MA_DEBUG_OUTPUT)
8495 
8496 /* Customize this to use a specific tag in __android_log_print() for debug output messages. */
8497 #ifndef MA_ANDROID_LOG_TAG
8498 #define MA_ANDROID_LOG_TAG "miniaudio"
8499 #endif
8500 
8501 void ma_log_callback_debug(void* pUserData, ma_uint32 level, const char* pMessage)
8502 {
8503  (void)pUserData;
8504 
8505  /* Special handling for some platforms. */
8506  #if defined(MA_ANDROID)
8507  {
8508  /* Android. */
8509  __android_log_print(ANDROID_LOG_DEBUG, MA_ANDROID_LOG_TAG, "%s: %s", ma_log_level_to_string(level), pMessage);
8510  }
8511  #else
8512  {
8513  /* Everything else. */
8514  printf("%s: %s", ma_log_level_to_string(level), pMessage);
8515  }
8516  #endif
8517 }
8518 #endif
8519 
8521 {
8522  ma_log_callback callback;
8523 
8524  MA_ZERO_OBJECT(&callback);
8525  callback.onLog = onLog;
8526  callback.pUserData = pUserData;
8527 
8528  return callback;
8529 }
8530 
8531 
8532 MA_API ma_result ma_log_init(const ma_allocation_callbacks* pAllocationCallbacks, ma_log* pLog)
8533 {
8534  if (pLog == NULL) {
8535  return MA_INVALID_ARGS;
8536  }
8537 
8538  MA_ZERO_OBJECT(pLog);
8539  ma_allocation_callbacks_init_copy(&pLog->allocationCallbacks, pAllocationCallbacks);
8540 
8541  /* We need a mutex for thread safety. */
8542  #ifndef MA_NO_THREADING
8543  {
8544  ma_result result = ma_mutex_init(&pLog->lock);
8545  if (result != MA_SUCCESS) {
8546  return result;
8547  }
8548  }
8549  #endif
8550 
8551  /* If we're using debug output, enable it. */
8552  #if defined(MA_DEBUG_OUTPUT)
8553  {
8554  ma_log_register_callback(pLog, ma_log_callback_init(ma_log_callback_debug, NULL)); /* Doesn't really matter if this fails. */
8555  }
8556  #endif
8557 
8558  return MA_SUCCESS;
8559 }
8560 
8561 MA_API void ma_log_uninit(ma_log* pLog)
8562 {
8563  if (pLog == NULL) {
8564  return;
8565  }
8566 
8567 #ifndef MA_NO_THREADING
8568  ma_mutex_uninit(&pLog->lock);
8569 #endif
8570 }
8571 
8572 static void ma_log_lock(ma_log* pLog)
8573 {
8574 #ifndef MA_NO_THREADING
8575  ma_mutex_lock(&pLog->lock);
8576 #else
8577  (void)pLog;
8578 #endif
8579 }
8580 
8581 static void ma_log_unlock(ma_log* pLog)
8582 {
8583 #ifndef MA_NO_THREADING
8584  ma_mutex_unlock(&pLog->lock);
8585 #else
8586  (void)pLog;
8587 #endif
8588 }
8589 
8591 {
8592  ma_result result = MA_SUCCESS;
8593 
8594  if (pLog == NULL || callback.onLog == NULL) {
8595  return MA_INVALID_ARGS;
8596  }
8597 
8598  ma_log_lock(pLog);
8599  {
8600  if (pLog->callbackCount == ma_countof(pLog->callbacks)) {
8601  result = MA_OUT_OF_MEMORY; /* Reached the maximum allowed log callbacks. */
8602  } else {
8603  pLog->callbacks[pLog->callbackCount] = callback;
8604  pLog->callbackCount += 1;
8605  }
8606  }
8607  ma_log_unlock(pLog);
8608 
8609  return result;
8610 }
8611 
8613 {
8614  if (pLog == NULL) {
8615  return MA_INVALID_ARGS;
8616  }
8617 
8618  ma_log_lock(pLog);
8619  {
8620  ma_uint32 iLog;
8621  for (iLog = 0; iLog < pLog->callbackCount; ) {
8622  if (pLog->callbacks[iLog].onLog == callback.onLog) {
8623  /* Found. Move everything down a slot. */
8624  ma_uint32 jLog;
8625  for (jLog = iLog; jLog < pLog->callbackCount-1; jLog += 1) {
8626  pLog->callbacks[jLog] = pLog->callbacks[jLog + 1];
8627  }
8628 
8629  pLog->callbackCount -= 1;
8630  } else {
8631  /* Not found. */
8632  iLog += 1;
8633  }
8634  }
8635  }
8636  ma_log_unlock(pLog);
8637 
8638  return MA_SUCCESS;
8639 }
8640 
8641 MA_API ma_result ma_log_post(ma_log* pLog, ma_uint32 level, const char* pMessage)
8642 {
8643  if (pLog == NULL || pMessage == NULL) {
8644  return MA_INVALID_ARGS;
8645  }
8646 
8647  /* If it's a debug log, ignore it unless MA_DEBUG_OUTPUT is enabled. */
8648  #if !defined(MA_DEBUG_OUTPUT)
8649  {
8650  if (level == MA_LOG_LEVEL_DEBUG) {
8651  return MA_INVALID_ARGS; /* Don't post debug messages if debug output is disabled. */
8652  }
8653  }
8654  #endif
8655 
8656  ma_log_lock(pLog);
8657  {
8658  ma_uint32 iLog;
8659  for (iLog = 0; iLog < pLog->callbackCount; iLog += 1) {
8660  if (pLog->callbacks[iLog].onLog) {
8661  pLog->callbacks[iLog].onLog(pLog->callbacks[iLog].pUserData, level, pMessage);
8662  }
8663  }
8664  }
8665  ma_log_unlock(pLog);
8666 
8667  return MA_SUCCESS;
8668 }
8669 
8670 
8671 /*
8672 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
8673 logging function, I'm happy to keep this simple. In the VC6 build we can implement this in terms of _vsnprintf().
8674 */
8675 #if defined(_MSC_VER) && _MSC_VER < 1900
8676 static int ma_vscprintf(const ma_allocation_callbacks* pAllocationCallbacks, const char* format, va_list args)
8677 {
8678 #if _MSC_VER > 1200
8679  return _vscprintf(format, args);
8680 #else
8681  int result;
8682  char* pTempBuffer = NULL;
8683  size_t tempBufferCap = 1024;
8684 
8685  if (format == NULL) {
8686  errno = EINVAL;
8687  return -1;
8688  }
8689 
8690  for (;;) {
8691  char* pNewTempBuffer = (char*)ma_realloc(pTempBuffer, tempBufferCap, pAllocationCallbacks);
8692  if (pNewTempBuffer == NULL) {
8693  ma_free(pTempBuffer, pAllocationCallbacks);
8694  errno = ENOMEM;
8695  return -1; /* Out of memory. */
8696  }
8697 
8698  pTempBuffer = pNewTempBuffer;
8699 
8700  result = _vsnprintf(pTempBuffer, tempBufferCap, format, args);
8701  ma_free(pTempBuffer, NULL);
8702 
8703  if (result != -1) {
8704  break; /* Got it. */
8705  }
8706 
8707  /* 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. */
8708  tempBufferCap *= 2;
8709  }
8710 
8711  return result;
8712 #endif
8713 }
8714 #endif
8715 
8716 MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat, va_list args)
8717 {
8718  if (pLog == NULL || pFormat == NULL) {
8719  return MA_INVALID_ARGS;
8720  }
8721 
8722  /*
8723  If it's a debug log, ignore it unless MA_DEBUG_OUTPUT is enabled. Do this before generating the
8724  formatted message string so that we don't waste time only to have ma_log_post() reject it.
8725  */
8726  #if !defined(MA_DEBUG_OUTPUT)
8727  {
8728  if (level == MA_LOG_LEVEL_DEBUG) {
8729  return MA_INVALID_ARGS; /* Don't post debug messages if debug output is disabled. */
8730  }
8731  }
8732  #endif
8733 
8734  #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || ((!defined(_MSC_VER) || _MSC_VER >= 1900) && !defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
8735  {
8736  ma_result result;
8737  int length;
8738  char pFormattedMessageStack[1024];
8739  char* pFormattedMessageHeap = NULL;
8740 
8741  /* First try formatting into our fixed sized stack allocated buffer. If this is too small we'll fallback to a heap allocation. */
8742  length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args);
8743  if (length < 0) {
8744  return MA_INVALID_OPERATION; /* An error occured when trying to convert the buffer. */
8745  }
8746 
8747  if ((size_t)length < sizeof(pFormattedMessageStack)) {
8748  /* The string was written to the stack. */
8749  result = ma_log_post(pLog, level, pFormattedMessageStack);
8750  } else {
8751  /* The stack buffer was too small, try the heap. */
8752  pFormattedMessageHeap = (char*)ma_malloc(length + 1, &pLog->allocationCallbacks);
8753  if (pFormattedMessageHeap == NULL) {
8754  return MA_OUT_OF_MEMORY;
8755  }
8756 
8757  length = vsnprintf(pFormattedMessageHeap, length + 1, pFormat, args);
8758  if (length < 0) {
8759  ma_free(pFormattedMessageHeap, &pLog->allocationCallbacks);
8760  return MA_INVALID_OPERATION;
8761  }
8762 
8763  result = ma_log_post(pLog, level, pFormattedMessageHeap);
8764  ma_free(pFormattedMessageHeap, &pLog->allocationCallbacks);
8765  }
8766 
8767  return result;
8768  }
8769  #else
8770  {
8771  /*
8772  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
8773  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
8774  a fixed sized stack allocated buffer.
8775  */
8776  #if defined(_MSC_VER) && _MSC_VER >= 1200 /* 1200 = VC6 */
8777  {
8778  ma_result result;
8779  int formattedLen;
8780  char* pFormattedMessage = NULL;
8781  va_list args2;
8782 
8783  #if _MSC_VER >= 1800
8784  {
8785  va_copy(args2, args);
8786  }
8787  #else
8788  {
8789  args2 = args;
8790  }
8791  #endif
8792 
8793  formattedLen = ma_vscprintf(&pLog->allocationCallbacks, pFormat, args2);
8794  va_end(args2);
8795 
8796  if (formattedLen <= 0) {
8797  return MA_INVALID_OPERATION;
8798  }
8799 
8800  pFormattedMessage = (char*)ma_malloc(formattedLen + 1, &pLog->allocationCallbacks);
8801  if (pFormattedMessage == NULL) {
8802  return MA_OUT_OF_MEMORY;
8803  }
8804 
8805  /* We'll get errors on newer versions of Visual Studio if we try to use vsprintf(). */
8806  #if _MSC_VER >= 1400 /* 1400 = Visual Studio 2005 */
8807  {
8808  vsprintf_s(pFormattedMessage, formattedLen + 1, pFormat, args);
8809  }
8810  #else
8811  {
8812  vsprintf(pFormattedMessage, pFormat, args);
8813  }
8814  #endif
8815 
8816  result = ma_log_post(pLog, level, pFormattedMessage);
8817  ma_free(pFormattedMessage, &pLog->allocationCallbacks);
8818 
8819  return result;
8820  }
8821  #else
8822  {
8823  /* Can't do anything because we don't have a safe way of to emulate vsnprintf() without a manual solution. */
8824  (void)level;
8825  (void)args;
8826 
8827  return MA_INVALID_OPERATION;
8828  }
8829  #endif
8830  }
8831  #endif
8832 }
8833 
8834 MA_API ma_result ma_log_postf(ma_log* pLog, ma_uint32 level, const char* pFormat, ...)
8835 {
8836  ma_result result;
8837  va_list args;
8838 
8839  if (pLog == NULL || pFormat == NULL) {
8840  return MA_INVALID_ARGS;
8841  }
8842 
8843  /*
8844  If it's a debug log, ignore it unless MA_DEBUG_OUTPUT is enabled. Do this before generating the
8845  formatted message string so that we don't waste time only to have ma_log_post() reject it.
8846  */
8847  #if !defined(MA_DEBUG_OUTPUT)
8848  {
8849  if (level == MA_LOG_LEVEL_DEBUG) {
8850  return MA_INVALID_ARGS; /* Don't post debug messages if debug output is disabled. */
8851  }
8852  }
8853  #endif
8854 
8855  va_start(args, pFormat);
8856  {
8857  result = ma_log_postv(pLog, level, pFormat, args);
8858  }
8859  va_end(args);
8860 
8861  return result;
8862 }
8863 
8864 
8865 
8866 
8867 /* Clamps an f32 sample to -1..1 */
8868 static MA_INLINE float ma_clip_f32(float x)
8869 {
8870  if (x < -1) return -1;
8871  if (x > +1) return +1;
8872  return x;
8873 }
8874 
8875 static MA_INLINE float ma_mix_f32(float x, float y, float a)
8876 {
8877  return x*(1-a) + y*a;
8878 }
8879 static MA_INLINE float ma_mix_f32_fast(float x, float y, float a)
8880 {
8881  float r0 = (y - x);
8882  float r1 = r0*a;
8883  return x + r1;
8884  /*return x + (y - x)*a;*/
8885 }
8886 
8887 #if defined(MA_SUPPORT_SSE2)
8888 static MA_INLINE __m128 ma_mix_f32_fast__sse2(__m128 x, __m128 y, __m128 a)
8889 {
8890  return _mm_add_ps(x, _mm_mul_ps(_mm_sub_ps(y, x), a));
8891 }
8892 #endif
8893 #if defined(MA_SUPPORT_AVX2)
8894 static MA_INLINE __m256 ma_mix_f32_fast__avx2(__m256 x, __m256 y, __m256 a)
8895 {
8896  return _mm256_add_ps(x, _mm256_mul_ps(_mm256_sub_ps(y, x), a));
8897 }
8898 #endif
8899 #if defined(MA_SUPPORT_AVX512)
8900 static MA_INLINE __m512 ma_mix_f32_fast__avx512(__m512 x, __m512 y, __m512 a)
8901 {
8902  return _mm512_add_ps(x, _mm512_mul_ps(_mm512_sub_ps(y, x), a));
8903 }
8904 #endif
8905 #if defined(MA_SUPPORT_NEON)
8906 static MA_INLINE float32x4_t ma_mix_f32_fast__neon(float32x4_t x, float32x4_t y, float32x4_t a)
8907 {
8908  return vaddq_f32(x, vmulq_f32(vsubq_f32(y, x), a));
8909 }
8910 #endif
8911 
8912 
8913 static MA_INLINE double ma_mix_f64(double x, double y, double a)
8914 {
8915  return x*(1-a) + y*a;
8916 }
8917 static MA_INLINE double ma_mix_f64_fast(double x, double y, double a)
8918 {
8919  return x + (y - x)*a;
8920 }
8921 
8922 static MA_INLINE float ma_scale_to_range_f32(float x, float lo, float hi)
8923 {
8924  return lo + x*(hi-lo);
8925 }
8926 
8927 
8928 /*
8929 Greatest common factor using Euclid's algorithm iteratively.
8930 */
8932 {
8933  for (;;) {
8934  if (b == 0) {
8935  break;
8936  } else {
8937  ma_uint32 t = a;
8938  a = b;
8939  b = t % a;
8940  }
8941  }
8942 
8943  return a;
8944 }
8945 
8946 
8947 /*
8948 Random Number Generation
8949 
8950 miniaudio uses the LCG random number generation algorithm. This is good enough for audio.
8951 
8952 Note that miniaudio's global LCG implementation uses global state which is _not_ thread-local. When this is called across
8953 multiple threads, results will be unpredictable. However, it won't crash and results will still be random enough for
8954 miniaudio's purposes.
8955 */
8956 #ifndef MA_DEFAULT_LCG_SEED
8957 #define MA_DEFAULT_LCG_SEED 4321
8958 #endif
8959 
8960 #define MA_LCG_M 2147483647
8961 #define MA_LCG_A 48271
8962 #define MA_LCG_C 0
8963 
8964 static ma_lcg g_maLCG = {MA_DEFAULT_LCG_SEED}; /* Non-zero initial seed. Use ma_seed() to use an explicit seed. */
8965 
8966 static MA_INLINE void ma_lcg_seed(ma_lcg* pLCG, ma_int32 seed)
8967 {
8968  MA_ASSERT(pLCG != NULL);
8969  pLCG->state = seed;
8970 }
8971 
8973 {
8974  pLCG->state = (MA_LCG_A * pLCG->state + MA_LCG_C) % MA_LCG_M;
8975  return pLCG->state;
8976 }
8977 
8979 {
8980  return (ma_uint32)ma_lcg_rand_s32(pLCG);
8981 }
8982 
8984 {
8985  return (ma_int16)(ma_lcg_rand_s32(pLCG) & 0xFFFF);
8986 }
8987 
8988 static MA_INLINE double ma_lcg_rand_f64(ma_lcg* pLCG)
8989 {
8990  return ma_lcg_rand_s32(pLCG) / (double)0x7FFFFFFF;
8991 }
8992 
8993 static MA_INLINE float ma_lcg_rand_f32(ma_lcg* pLCG)
8994 {
8995  return (float)ma_lcg_rand_f64(pLCG);
8996 }
8997 
8998 static MA_INLINE float ma_lcg_rand_range_f32(ma_lcg* pLCG, float lo, float hi)
8999 {
9000  return ma_scale_to_range_f32(ma_lcg_rand_f32(pLCG), lo, hi);
9001 }
9002 
9004 {
9005  if (lo == hi) {
9006  return lo;
9007  }
9008 
9009  return lo + ma_lcg_rand_u32(pLCG) / (0xFFFFFFFF / (hi - lo + 1) + 1);
9010 }
9011 
9012 
9013 
9014 static MA_INLINE void ma_seed(ma_int32 seed)
9015 {
9016  ma_lcg_seed(&g_maLCG, seed);
9017 }
9018 
9019 static MA_INLINE ma_int32 ma_rand_s32(void)
9020 {
9021  return ma_lcg_rand_s32(&g_maLCG);
9022 }
9023 
9024 static MA_INLINE ma_uint32 ma_rand_u32(void)
9025 {
9026  return ma_lcg_rand_u32(&g_maLCG);
9027 }
9028 
9029 static MA_INLINE double ma_rand_f64(void)
9030 {
9031  return ma_lcg_rand_f64(&g_maLCG);
9032 }
9033 
9034 static MA_INLINE float ma_rand_f32(void)
9035 {
9036  return ma_lcg_rand_f32(&g_maLCG);
9037 }
9038 
9039 static MA_INLINE float ma_rand_range_f32(float lo, float hi)
9040 {
9041  return ma_lcg_rand_range_f32(&g_maLCG, lo, hi);
9042 }
9043 
9045 {
9046  return ma_lcg_rand_range_s32(&g_maLCG, lo, hi);
9047 }
9048 
9049 
9050 static MA_INLINE float ma_dither_f32_rectangle(float ditherMin, float ditherMax)
9051 {
9052  return ma_rand_range_f32(ditherMin, ditherMax);
9053 }
9054 
9055 static MA_INLINE float ma_dither_f32_triangle(float ditherMin, float ditherMax)
9056 {
9057  float a = ma_rand_range_f32(ditherMin, 0);
9058  float b = ma_rand_range_f32(0, ditherMax);
9059  return a + b;
9060 }
9061 
9062 static MA_INLINE float ma_dither_f32(ma_dither_mode ditherMode, float ditherMin, float ditherMax)
9063 {
9064  if (ditherMode == ma_dither_mode_rectangle) {
9065  return ma_dither_f32_rectangle(ditherMin, ditherMax);
9066  }
9067  if (ditherMode == ma_dither_mode_triangle) {
9068  return ma_dither_f32_triangle(ditherMin, ditherMax);
9069  }
9070 
9071  return 0;
9072 }
9073 
9074 static MA_INLINE ma_int32 ma_dither_s32(ma_dither_mode ditherMode, ma_int32 ditherMin, ma_int32 ditherMax)
9075 {
9076  if (ditherMode == ma_dither_mode_rectangle) {
9077  ma_int32 a = ma_rand_range_s32(ditherMin, ditherMax);
9078  return a;
9079  }
9080  if (ditherMode == ma_dither_mode_triangle) {
9081  ma_int32 a = ma_rand_range_s32(ditherMin, 0);
9082  ma_int32 b = ma_rand_range_s32(0, ditherMax);
9083  return a + b;
9084  }
9085 
9086  return 0;
9087 }
9088 
9089 
9090 /**************************************************************************************************************************************************************
9091 
9092 Atomics
9093 
9094 **************************************************************************************************************************************************************/
9095 /* c89atomic.h begin */
9096 #ifndef c89atomic_h
9097 #define c89atomic_h
9098 #if defined(__cplusplus)
9099 extern "C" {
9100 #endif
9101 typedef signed char c89atomic_int8;
9102 typedef unsigned char c89atomic_uint8;
9103 typedef signed short c89atomic_int16;
9104 typedef unsigned short c89atomic_uint16;
9105 typedef signed int c89atomic_int32;
9106 typedef unsigned int c89atomic_uint32;
9107 #if defined(_MSC_VER)
9108  typedef signed __int64 c89atomic_int64;
9109  typedef unsigned __int64 c89atomic_uint64;
9110 #else
9111  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
9112  #pragma GCC diagnostic push
9113  #pragma GCC diagnostic ignored "-Wlong-long"
9114  #if defined(__clang__)
9115  #pragma GCC diagnostic ignored "-Wc++11-long-long"
9116  #endif
9117  #endif
9118  typedef signed long long c89atomic_int64;
9119  typedef unsigned long long c89atomic_uint64;
9120  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
9121  #pragma GCC diagnostic pop
9122  #endif
9123 #endif
9124 typedef int c89atomic_memory_order;
9125 typedef unsigned char c89atomic_bool;
9126 #if !defined(C89ATOMIC_64BIT) && !defined(C89ATOMIC_32BIT)
9127 #ifdef _WIN32
9128 #ifdef _WIN64
9129 #define C89ATOMIC_64BIT
9130 #else
9131 #define C89ATOMIC_32BIT
9132 #endif
9133 #endif
9134 #endif
9135 #if !defined(C89ATOMIC_64BIT) && !defined(C89ATOMIC_32BIT)
9136 #ifdef __GNUC__
9137 #ifdef __LP64__
9138 #define C89ATOMIC_64BIT
9139 #else
9140 #define C89ATOMIC_32BIT
9141 #endif
9142 #endif
9143 #endif
9144 #if !defined(C89ATOMIC_64BIT) && !defined(C89ATOMIC_32BIT)
9145 #include <stdint.h>
9146 #if INTPTR_MAX == INT64_MAX
9147 #define C89ATOMIC_64BIT
9148 #else
9149 #define C89ATOMIC_32BIT
9150 #endif
9151 #endif
9152 #if defined(__x86_64__) || defined(_M_X64)
9153 #define C89ATOMIC_X64
9154 #elif defined(__i386) || defined(_M_IX86)
9155 #define C89ATOMIC_X86
9156 #elif defined(__arm__) || defined(_M_ARM)
9157 #define C89ATOMIC_ARM
9158 #endif
9159 #if defined(_MSC_VER)
9160  #define C89ATOMIC_INLINE __forceinline
9161 #elif defined(__GNUC__)
9162  #if defined(__STRICT_ANSI__)
9163  #define C89ATOMIC_INLINE __inline__ __attribute__((always_inline))
9164  #else
9165  #define C89ATOMIC_INLINE inline __attribute__((always_inline))
9166  #endif
9167 #elif defined(__WATCOMC__) || defined(__DMC__)
9168  #define C89ATOMIC_INLINE __inline
9169 #else
9170  #define C89ATOMIC_INLINE
9171 #endif
9172 #define C89ATOMIC_HAS_8
9173 #define C89ATOMIC_HAS_16
9174 #define C89ATOMIC_HAS_32
9175 #define C89ATOMIC_HAS_64
9176 #if (defined(_MSC_VER) ) || defined(__WATCOMC__) || defined(__DMC__)
9177  #define c89atomic_memory_order_relaxed 0
9178  #define c89atomic_memory_order_consume 1
9179  #define c89atomic_memory_order_acquire 2
9180  #define c89atomic_memory_order_release 3
9181  #define c89atomic_memory_order_acq_rel 4
9182  #define c89atomic_memory_order_seq_cst 5
9183  #if _MSC_VER < 1600 && defined(C89ATOMIC_32BIT)
9184  #define C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY
9185  #endif
9186  #if _MSC_VER < 1600
9187  #undef C89ATOMIC_HAS_8
9188  #undef C89ATOMIC_HAS_16
9189  #endif
9190  #if !defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
9191  #include <intrin.h>
9192  #endif
9193  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
9194  #if defined(C89ATOMIC_HAS_8)
9196  {
9197  c89atomic_uint8 result = 0;
9198  __asm {
9199  mov ecx, dst
9200  mov al, expected
9201  mov dl, desired
9202  lock cmpxchg [ecx], dl
9203  mov result, al
9204  }
9205  return result;
9206  }
9207  #endif
9208  #if defined(C89ATOMIC_HAS_16)
9210  {
9211  c89atomic_uint16 result = 0;
9212  __asm {
9213  mov ecx, dst
9214  mov ax, expected
9215  mov dx, desired
9216  lock cmpxchg [ecx], dx
9217  mov result, ax
9218  }
9219  return result;
9220  }
9221  #endif
9222  #if defined(C89ATOMIC_HAS_32)
9224  {
9225  c89atomic_uint32 result = 0;
9226  __asm {
9227  mov ecx, dst
9228  mov eax, expected
9229  mov edx, desired
9230  lock cmpxchg [ecx], edx
9231  mov result, eax
9232  }
9233  return result;
9234  }
9235  #endif
9236  #if defined(C89ATOMIC_HAS_64)
9238  {
9239  c89atomic_uint32 resultEAX = 0;
9240  c89atomic_uint32 resultEDX = 0;
9241  __asm {
9242  mov esi, dst
9243  mov eax, dword ptr expected
9244  mov edx, dword ptr expected + 4
9245  mov ebx, dword ptr desired
9246  mov ecx, dword ptr desired + 4
9247  lock cmpxchg8b qword ptr [esi]
9248  mov resultEAX, eax
9249  mov resultEDX, edx
9250  }
9251  return ((c89atomic_uint64)resultEDX << 32) | resultEAX;
9252  }
9253  #endif
9254  #else
9255  #if defined(C89ATOMIC_HAS_8)
9256  #define c89atomic_compare_and_swap_8( dst, expected, desired) (c89atomic_uint8 )_InterlockedCompareExchange8((volatile char*)dst, (char)desired, (char)expected)
9257  #endif
9258  #if defined(C89ATOMIC_HAS_16)
9259  #define c89atomic_compare_and_swap_16(dst, expected, desired) (c89atomic_uint16)_InterlockedCompareExchange16((volatile short*)dst, (short)desired, (short)expected)
9260  #endif
9261  #if defined(C89ATOMIC_HAS_32)
9262  #define c89atomic_compare_and_swap_32(dst, expected, desired) (c89atomic_uint32)_InterlockedCompareExchange((volatile long*)dst, (long)desired, (long)expected)
9263  #endif
9264  #if defined(C89ATOMIC_HAS_64)
9265  #define c89atomic_compare_and_swap_64(dst, expected, desired) (c89atomic_uint64)_InterlockedCompareExchange64((volatile long long*)dst, (long long)desired, (long long)expected)
9266  #endif
9267  #endif
9268  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
9269  #if defined(C89ATOMIC_HAS_8)
9271  {
9272  c89atomic_uint8 result = 0;
9273  (void)order;
9274  __asm {
9275  mov ecx, dst
9276  mov al, src
9277  lock xchg [ecx], al
9278  mov result, al
9279  }
9280  return result;
9281  }
9282  #endif
9283  #if defined(C89ATOMIC_HAS_16)
9285  {
9286  c89atomic_uint16 result = 0;
9287  (void)order;
9288  __asm {
9289  mov ecx, dst
9290  mov ax, src
9291  lock xchg [ecx], ax
9292  mov result, ax
9293  }
9294  return result;
9295  }
9296  #endif
9297  #if defined(C89ATOMIC_HAS_32)
9299  {
9300  c89atomic_uint32 result = 0;
9301  (void)order;
9302  __asm {
9303  mov ecx, dst
9304  mov eax, src
9305  lock xchg [ecx], eax
9306  mov result, eax
9307  }
9308  return result;
9309  }
9310  #endif
9311  #else
9312  #if defined(C89ATOMIC_HAS_8)
9314  {
9315  (void)order;
9316  return (c89atomic_uint8)_InterlockedExchange8((volatile char*)dst, (char)src);
9317  }
9318  #endif
9319  #if defined(C89ATOMIC_HAS_16)
9321  {
9322  (void)order;
9323  return (c89atomic_uint16)_InterlockedExchange16((volatile short*)dst, (short)src);
9324  }
9325  #endif
9326  #if defined(C89ATOMIC_HAS_32)
9328  {
9329  (void)order;
9330  return (c89atomic_uint32)_InterlockedExchange((volatile long*)dst, (long)src);
9331  }
9332  #endif
9333  #if defined(C89ATOMIC_HAS_64) && defined(C89ATOMIC_64BIT)
9335  {
9336  (void)order;
9337  return (c89atomic_uint64)_InterlockedExchange64((volatile long long*)dst, (long long)src);
9338  }
9339  #else
9340  #endif
9341  #endif
9342  #if defined(C89ATOMIC_HAS_64) && !defined(C89ATOMIC_64BIT)
9344  {
9345  c89atomic_uint64 oldValue;
9346  do {
9347  oldValue = *dst;
9348  } while (c89atomic_compare_and_swap_64(dst, oldValue, src) != oldValue);
9349  (void)order;
9350  return oldValue;
9351  }
9352  #endif
9353  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
9354  #if defined(C89ATOMIC_HAS_8)
9356  {
9357  c89atomic_uint8 result = 0;
9358  (void)order;
9359  __asm {
9360  mov ecx, dst
9361  mov al, src
9362  lock xadd [ecx], al
9363  mov result, al
9364  }
9365  return result;
9366  }
9367  #endif
9368  #if defined(C89ATOMIC_HAS_16)
9370  {
9371  c89atomic_uint16 result = 0;
9372  (void)order;
9373  __asm {
9374  mov ecx, dst
9375  mov ax, src
9376  lock xadd [ecx], ax
9377  mov result, ax
9378  }
9379  return result;
9380  }
9381  #endif
9382  #if defined(C89ATOMIC_HAS_32)
9384  {
9385  c89atomic_uint32 result = 0;
9386  (void)order;
9387  __asm {
9388  mov ecx, dst
9389  mov eax, src
9390  lock xadd [ecx], eax
9391  mov result, eax
9392  }
9393  return result;
9394  }
9395  #endif
9396  #else
9397  #if defined(C89ATOMIC_HAS_8)
9399  {
9400  (void)order;
9401  return (c89atomic_uint8)_InterlockedExchangeAdd8((volatile char*)dst, (char)src);
9402  }
9403  #endif
9404  #if defined(C89ATOMIC_HAS_16)
9406  {
9407  (void)order;
9408  return (c89atomic_uint16)_InterlockedExchangeAdd16((volatile short*)dst, (short)src);
9409  }
9410  #endif
9411  #if defined(C89ATOMIC_HAS_32)
9413  {
9414  (void)order;
9415  return (c89atomic_uint32)_InterlockedExchangeAdd((volatile long*)dst, (long)src);
9416  }
9417  #endif
9418  #if defined(C89ATOMIC_HAS_64) && defined(C89ATOMIC_64BIT)
9420  {
9421  (void)order;
9422  return (c89atomic_uint64)_InterlockedExchangeAdd64((volatile long long*)dst, (long long)src);
9423  }
9424  #else
9425  #endif
9426  #endif
9427  #if defined(C89ATOMIC_HAS_64) && !defined(C89ATOMIC_64BIT)
9429  {
9430  c89atomic_uint64 oldValue;
9431  c89atomic_uint64 newValue;
9432  do {
9433  oldValue = *dst;
9434  newValue = oldValue + src;
9435  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
9436  (void)order;
9437  return oldValue;
9438  }
9439  #endif
9440  #if defined(C89ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
9441  static C89ATOMIC_INLINE void __stdcall c89atomic_thread_fence(c89atomic_memory_order order)
9442  {
9443  (void)order;
9444  __asm {
9445  lock add [esp], 0
9446  }
9447  }
9448  #else
9449  #if defined(C89ATOMIC_X64)
9450  #define c89atomic_thread_fence(order) __faststorefence(), (void)order
9451  #else
9452  static C89ATOMIC_INLINE void c89atomic_thread_fence(c89atomic_memory_order order)
9453  {
9454  volatile c89atomic_uint32 barrier = 0;
9455  c89atomic_fetch_add_explicit_32(&barrier, 0, order);
9456  }
9457  #endif
9458  #endif
9459  #define c89atomic_compiler_fence() c89atomic_thread_fence(c89atomic_memory_order_seq_cst)
9460  #define c89atomic_signal_fence(order) c89atomic_thread_fence(order)
9461  #if defined(C89ATOMIC_HAS_8)
9463  {
9464  (void)order;
9465  return c89atomic_compare_and_swap_8((volatile c89atomic_uint8*)ptr, 0, 0);
9466  }
9467  #endif
9468  #if defined(C89ATOMIC_HAS_16)
9470  {
9471  (void)order;
9472  return c89atomic_compare_and_swap_16((volatile c89atomic_uint16*)ptr, 0, 0);
9473  }
9474  #endif
9475  #if defined(C89ATOMIC_HAS_32)
9477  {
9478  (void)order;
9479  return c89atomic_compare_and_swap_32((volatile c89atomic_uint32*)ptr, 0, 0);
9480  }
9481  #endif
9482  #if defined(C89ATOMIC_HAS_64)
9484  {
9485  (void)order;
9486  return c89atomic_compare_and_swap_64((volatile c89atomic_uint64*)ptr, 0, 0);
9487  }
9488  #endif
9489  #if defined(C89ATOMIC_HAS_8)
9490  #define c89atomic_store_explicit_8( dst, src, order) (void)c89atomic_exchange_explicit_8 (dst, src, order)
9491  #endif
9492  #if defined(C89ATOMIC_HAS_16)
9493  #define c89atomic_store_explicit_16(dst, src, order) (void)c89atomic_exchange_explicit_16(dst, src, order)
9494  #endif
9495  #if defined(C89ATOMIC_HAS_32)
9496  #define c89atomic_store_explicit_32(dst, src, order) (void)c89atomic_exchange_explicit_32(dst, src, order)
9497  #endif
9498  #if defined(C89ATOMIC_HAS_64)
9499  #define c89atomic_store_explicit_64(dst, src, order) (void)c89atomic_exchange_explicit_64(dst, src, order)
9500  #endif
9501  #if defined(C89ATOMIC_HAS_8)
9503  {
9504  c89atomic_uint8 oldValue;
9505  c89atomic_uint8 newValue;
9506  do {
9507  oldValue = *dst;
9508  newValue = (c89atomic_uint8)(oldValue - src);
9509  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
9510  (void)order;
9511  return oldValue;
9512  }
9513  #endif
9514  #if defined(C89ATOMIC_HAS_16)
9516  {
9517  c89atomic_uint16 oldValue;
9518  c89atomic_uint16 newValue;
9519  do {
9520  oldValue = *dst;
9521  newValue = (c89atomic_uint16)(oldValue - src);
9522  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
9523  (void)order;
9524  return oldValue;
9525  }
9526  #endif
9527  #if defined(C89ATOMIC_HAS_32)
9529  {
9530  c89atomic_uint32 oldValue;
9531  c89atomic_uint32 newValue;
9532  do {
9533  oldValue = *dst;
9534  newValue = oldValue - src;
9535  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
9536  (void)order;
9537  return oldValue;
9538  }
9539  #endif
9540  #if defined(C89ATOMIC_HAS_64)
9542  {
9543  c89atomic_uint64 oldValue;
9544  c89atomic_uint64 newValue;
9545  do {
9546  oldValue = *dst;
9547  newValue = oldValue - src;
9548  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
9549  (void)order;
9550  return oldValue;
9551  }
9552  #endif
9553  #if defined(C89ATOMIC_HAS_8)
9555  {
9556  c89atomic_uint8 oldValue;
9557  c89atomic_uint8 newValue;
9558  do {
9559  oldValue = *dst;
9560  newValue = (c89atomic_uint8)(oldValue & src);
9561  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
9562  (void)order;
9563  return oldValue;
9564  }
9565  #endif
9566  #if defined(C89ATOMIC_HAS_16)
9568  {
9569  c89atomic_uint16 oldValue;
9570  c89atomic_uint16 newValue;
9571  do {
9572  oldValue = *dst;
9573  newValue = (c89atomic_uint16)(oldValue & src);
9574  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
9575  (void)order;
9576  return oldValue;
9577  }
9578  #endif
9579  #if defined(C89ATOMIC_HAS_32)
9581  {
9582  c89atomic_uint32 oldValue;
9583  c89atomic_uint32 newValue;
9584  do {
9585  oldValue = *dst;
9586  newValue = oldValue & src;
9587  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
9588  (void)order;
9589  return oldValue;
9590  }
9591  #endif
9592  #if defined(C89ATOMIC_HAS_64)
9594  {
9595  c89atomic_uint64 oldValue;
9596  c89atomic_uint64 newValue;
9597  do {
9598  oldValue = *dst;
9599  newValue = oldValue & src;
9600  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
9601  (void)order;
9602  return oldValue;
9603  }
9604  #endif
9605  #if defined(C89ATOMIC_HAS_8)
9607  {
9608  c89atomic_uint8 oldValue;
9609  c89atomic_uint8 newValue;
9610  do {
9611  oldValue = *dst;
9612  newValue = (c89atomic_uint8)(oldValue ^ src);
9613  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
9614  (void)order;
9615  return oldValue;
9616  }
9617  #endif
9618  #if defined(C89ATOMIC_HAS_16)
9620  {
9621  c89atomic_uint16 oldValue;
9622  c89atomic_uint16 newValue;
9623  do {
9624  oldValue = *dst;
9625  newValue = (c89atomic_uint16)(oldValue ^ src);
9626  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
9627  (void)order;
9628  return oldValue;
9629  }
9630  #endif
9631  #if defined(C89ATOMIC_HAS_32)
9633  {
9634  c89atomic_uint32 oldValue;
9635  c89atomic_uint32 newValue;
9636  do {
9637  oldValue = *dst;
9638  newValue = oldValue ^ src;
9639  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
9640  (void)order;
9641  return oldValue;
9642  }
9643  #endif
9644  #if defined(C89ATOMIC_HAS_64)
9646  {
9647  c89atomic_uint64 oldValue;
9648  c89atomic_uint64 newValue;
9649  do {
9650  oldValue = *dst;
9651  newValue = oldValue ^ src;
9652  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
9653  (void)order;
9654  return oldValue;
9655  }
9656  #endif
9657  #if defined(C89ATOMIC_HAS_8)
9659  {
9660  c89atomic_uint8 oldValue;
9661  c89atomic_uint8 newValue;
9662  do {
9663  oldValue = *dst;
9664  newValue = (c89atomic_uint8)(oldValue | src);
9665  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
9666  (void)order;
9667  return oldValue;
9668  }
9669  #endif
9670  #if defined(C89ATOMIC_HAS_16)
9672  {
9673  c89atomic_uint16 oldValue;
9674  c89atomic_uint16 newValue;
9675  do {
9676  oldValue = *dst;
9677  newValue = (c89atomic_uint16)(oldValue | src);
9678  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
9679  (void)order;
9680  return oldValue;
9681  }
9682  #endif
9683  #if defined(C89ATOMIC_HAS_32)
9685  {
9686  c89atomic_uint32 oldValue;
9687  c89atomic_uint32 newValue;
9688  do {
9689  oldValue = *dst;
9690  newValue = oldValue | src;
9691  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
9692  (void)order;
9693  return oldValue;
9694  }
9695  #endif
9696  #if defined(C89ATOMIC_HAS_64)
9698  {
9699  c89atomic_uint64 oldValue;
9700  c89atomic_uint64 newValue;
9701  do {
9702  oldValue = *dst;
9703  newValue = oldValue | src;
9704  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
9705  (void)order;
9706  return oldValue;
9707  }
9708  #endif
9709  #if defined(C89ATOMIC_HAS_8)
9710  #define c89atomic_test_and_set_explicit_8( dst, order) c89atomic_exchange_explicit_8 (dst, 1, order)
9711  #endif
9712  #if defined(C89ATOMIC_HAS_16)
9713  #define c89atomic_test_and_set_explicit_16(dst, order) c89atomic_exchange_explicit_16(dst, 1, order)
9714  #endif
9715  #if defined(C89ATOMIC_HAS_32)
9716  #define c89atomic_test_and_set_explicit_32(dst, order) c89atomic_exchange_explicit_32(dst, 1, order)
9717  #endif
9718  #if defined(C89ATOMIC_HAS_64)
9719  #define c89atomic_test_and_set_explicit_64(dst, order) c89atomic_exchange_explicit_64(dst, 1, order)
9720  #endif
9721  #if defined(C89ATOMIC_HAS_8)
9722  #define c89atomic_clear_explicit_8( dst, order) c89atomic_store_explicit_8 (dst, 0, order)
9723  #endif
9724  #if defined(C89ATOMIC_HAS_16)
9725  #define c89atomic_clear_explicit_16(dst, order) c89atomic_store_explicit_16(dst, 0, order)
9726  #endif
9727  #if defined(C89ATOMIC_HAS_32)
9728  #define c89atomic_clear_explicit_32(dst, order) c89atomic_store_explicit_32(dst, 0, order)
9729  #endif
9730  #if defined(C89ATOMIC_HAS_64)
9731  #define c89atomic_clear_explicit_64(dst, order) c89atomic_store_explicit_64(dst, 0, order)
9732  #endif
9733  #if defined(C89ATOMIC_HAS_8)
9735  #define c89atomic_flag_test_and_set_explicit(ptr, order) (c89atomic_bool)c89atomic_test_and_set_explicit_8(ptr, order)
9736  #define c89atomic_flag_clear_explicit(ptr, order) c89atomic_clear_explicit_8(ptr, order)
9737  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_8(ptr, order)
9738  #else
9740  #define c89atomic_flag_test_and_set_explicit(ptr, order) (c89atomic_bool)c89atomic_test_and_set_explicit_32(ptr, order)
9741  #define c89atomic_flag_clear_explicit(ptr, order) c89atomic_clear_explicit_32(ptr, order)
9742  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_32(ptr, order)
9743  #endif
9744 #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
9745  #define C89ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE
9746  #define C89ATOMIC_HAS_NATIVE_IS_LOCK_FREE
9747  #define c89atomic_memory_order_relaxed __ATOMIC_RELAXED
9748  #define c89atomic_memory_order_consume __ATOMIC_CONSUME
9749  #define c89atomic_memory_order_acquire __ATOMIC_ACQUIRE
9750  #define c89atomic_memory_order_release __ATOMIC_RELEASE
9751  #define c89atomic_memory_order_acq_rel __ATOMIC_ACQ_REL
9752  #define c89atomic_memory_order_seq_cst __ATOMIC_SEQ_CST
9753  #define c89atomic_compiler_fence() __asm__ __volatile__("":::"memory")
9754  #define c89atomic_thread_fence(order) __atomic_thread_fence(order)
9755  #define c89atomic_signal_fence(order) __atomic_signal_fence(order)
9756  #define c89atomic_is_lock_free_8(ptr) __atomic_is_lock_free(1, ptr)
9757  #define c89atomic_is_lock_free_16(ptr) __atomic_is_lock_free(2, ptr)
9758  #define c89atomic_is_lock_free_32(ptr) __atomic_is_lock_free(4, ptr)
9759  #define c89atomic_is_lock_free_64(ptr) __atomic_is_lock_free(8, ptr)
9760  #define c89atomic_test_and_set_explicit_8( dst, order) __atomic_exchange_n(dst, 1, order)
9761  #define c89atomic_test_and_set_explicit_16(dst, order) __atomic_exchange_n(dst, 1, order)
9762  #define c89atomic_test_and_set_explicit_32(dst, order) __atomic_exchange_n(dst, 1, order)
9763  #define c89atomic_test_and_set_explicit_64(dst, order) __atomic_exchange_n(dst, 1, order)
9764  #define c89atomic_clear_explicit_8( dst, order) __atomic_store_n(dst, 0, order)
9765  #define c89atomic_clear_explicit_16(dst, order) __atomic_store_n(dst, 0, order)
9766  #define c89atomic_clear_explicit_32(dst, order) __atomic_store_n(dst, 0, order)
9767  #define c89atomic_clear_explicit_64(dst, order) __atomic_store_n(dst, 0, order)
9768  #define c89atomic_store_explicit_8( dst, src, order) __atomic_store_n(dst, src, order)
9769  #define c89atomic_store_explicit_16(dst, src, order) __atomic_store_n(dst, src, order)
9770  #define c89atomic_store_explicit_32(dst, src, order) __atomic_store_n(dst, src, order)
9771  #define c89atomic_store_explicit_64(dst, src, order) __atomic_store_n(dst, src, order)
9772  #define c89atomic_load_explicit_8( dst, order) __atomic_load_n(dst, order)
9773  #define c89atomic_load_explicit_16(dst, order) __atomic_load_n(dst, order)
9774  #define c89atomic_load_explicit_32(dst, order) __atomic_load_n(dst, order)
9775  #define c89atomic_load_explicit_64(dst, order) __atomic_load_n(dst, order)
9776  #define c89atomic_exchange_explicit_8( dst, src, order) __atomic_exchange_n(dst, src, order)
9777  #define c89atomic_exchange_explicit_16(dst, src, order) __atomic_exchange_n(dst, src, order)
9778  #define c89atomic_exchange_explicit_32(dst, src, order) __atomic_exchange_n(dst, src, order)
9779  #define c89atomic_exchange_explicit_64(dst, src, order) __atomic_exchange_n(dst, src, order)
9780  #define c89atomic_compare_exchange_strong_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
9781  #define c89atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
9782  #define c89atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
9783  #define c89atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
9784  #define c89atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
9785  #define c89atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
9786  #define c89atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
9787  #define c89atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
9788  #define c89atomic_fetch_add_explicit_8( dst, src, order) __atomic_fetch_add(dst, src, order)
9789  #define c89atomic_fetch_add_explicit_16(dst, src, order) __atomic_fetch_add(dst, src, order)
9790  #define c89atomic_fetch_add_explicit_32(dst, src, order) __atomic_fetch_add(dst, src, order)
9791  #define c89atomic_fetch_add_explicit_64(dst, src, order) __atomic_fetch_add(dst, src, order)
9792  #define c89atomic_fetch_sub_explicit_8( dst, src, order) __atomic_fetch_sub(dst, src, order)
9793  #define c89atomic_fetch_sub_explicit_16(dst, src, order) __atomic_fetch_sub(dst, src, order)
9794  #define c89atomic_fetch_sub_explicit_32(dst, src, order) __atomic_fetch_sub(dst, src, order)
9795  #define c89atomic_fetch_sub_explicit_64(dst, src, order) __atomic_fetch_sub(dst, src, order)
9796  #define c89atomic_fetch_or_explicit_8( dst, src, order) __atomic_fetch_or(dst, src, order)
9797  #define c89atomic_fetch_or_explicit_16(dst, src, order) __atomic_fetch_or(dst, src, order)
9798  #define c89atomic_fetch_or_explicit_32(dst, src, order) __atomic_fetch_or(dst, src, order)
9799  #define c89atomic_fetch_or_explicit_64(dst, src, order) __atomic_fetch_or(dst, src, order)
9800  #define c89atomic_fetch_xor_explicit_8( dst, src, order) __atomic_fetch_xor(dst, src, order)
9801  #define c89atomic_fetch_xor_explicit_16(dst, src, order) __atomic_fetch_xor(dst, src, order)
9802  #define c89atomic_fetch_xor_explicit_32(dst, src, order) __atomic_fetch_xor(dst, src, order)
9803  #define c89atomic_fetch_xor_explicit_64(dst, src, order) __atomic_fetch_xor(dst, src, order)
9804  #define c89atomic_fetch_and_explicit_8( dst, src, order) __atomic_fetch_and(dst, src, order)
9805  #define c89atomic_fetch_and_explicit_16(dst, src, order) __atomic_fetch_and(dst, src, order)
9806  #define c89atomic_fetch_and_explicit_32(dst, src, order) __atomic_fetch_and(dst, src, order)
9807  #define c89atomic_fetch_and_explicit_64(dst, src, order) __atomic_fetch_and(dst, src, order)
9808  #define c89atomic_compare_and_swap_8 (dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9809  #define c89atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9810  #define c89atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9811  #define c89atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9813  #define c89atomic_flag_test_and_set_explicit(dst, order) (c89atomic_bool)__atomic_test_and_set(dst, order)
9814  #define c89atomic_flag_clear_explicit(dst, order) __atomic_clear(dst, order)
9815  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_8(ptr, order)
9816 #else
9817  #define c89atomic_memory_order_relaxed 1
9818  #define c89atomic_memory_order_consume 2
9819  #define c89atomic_memory_order_acquire 3
9820  #define c89atomic_memory_order_release 4
9821  #define c89atomic_memory_order_acq_rel 5
9822  #define c89atomic_memory_order_seq_cst 6
9823  #define c89atomic_compiler_fence() __asm__ __volatile__("":::"memory")
9824  #if defined(__GNUC__)
9825  #define c89atomic_thread_fence(order) __sync_synchronize(), (void)order
9827  {
9828  if (order > c89atomic_memory_order_acquire) {
9829  __sync_synchronize();
9830  }
9831  return __sync_lock_test_and_set(dst, src);
9832  }
9834  {
9835  c89atomic_uint16 oldValue;
9836  do {
9837  oldValue = *dst;
9838  } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
9839  (void)order;
9840  return oldValue;
9841  }
9843  {
9844  c89atomic_uint32 oldValue;
9845  do {
9846  oldValue = *dst;
9847  } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
9848  (void)order;
9849  return oldValue;
9850  }
9852  {
9853  c89atomic_uint64 oldValue;
9854  do {
9855  oldValue = *dst;
9856  } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
9857  (void)order;
9858  return oldValue;
9859  }
9861  {
9862  (void)order;
9863  return __sync_fetch_and_add(dst, src);
9864  }
9866  {
9867  (void)order;
9868  return __sync_fetch_and_add(dst, src);
9869  }
9871  {
9872  (void)order;
9873  return __sync_fetch_and_add(dst, src);
9874  }
9876  {
9877  (void)order;
9878  return __sync_fetch_and_add(dst, src);
9879  }
9881  {
9882  (void)order;
9883  return __sync_fetch_and_sub(dst, src);
9884  }
9886  {
9887  (void)order;
9888  return __sync_fetch_and_sub(dst, src);
9889  }
9891  {
9892  (void)order;
9893  return __sync_fetch_and_sub(dst, src);
9894  }
9896  {
9897  (void)order;
9898  return __sync_fetch_and_sub(dst, src);
9899  }
9901  {
9902  (void)order;
9903  return __sync_fetch_and_or(dst, src);
9904  }
9906  {
9907  (void)order;
9908  return __sync_fetch_and_or(dst, src);
9909  }
9911  {
9912  (void)order;
9913  return __sync_fetch_and_or(dst, src);
9914  }
9916  {
9917  (void)order;
9918  return __sync_fetch_and_or(dst, src);
9919  }
9921  {
9922  (void)order;
9923  return __sync_fetch_and_xor(dst, src);
9924  }
9926  {
9927  (void)order;
9928  return __sync_fetch_and_xor(dst, src);
9929  }
9931  {
9932  (void)order;
9933  return __sync_fetch_and_xor(dst, src);
9934  }
9936  {
9937  (void)order;
9938  return __sync_fetch_and_xor(dst, src);
9939  }
9941  {
9942  (void)order;
9943  return __sync_fetch_and_and(dst, src);
9944  }
9946  {
9947  (void)order;
9948  return __sync_fetch_and_and(dst, src);
9949  }
9951  {
9952  (void)order;
9953  return __sync_fetch_and_and(dst, src);
9954  }
9956  {
9957  (void)order;
9958  return __sync_fetch_and_and(dst, src);
9959  }
9960  #define c89atomic_compare_and_swap_8( dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9961  #define c89atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9962  #define c89atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9963  #define c89atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
9964  #else
9965  #if defined(C89ATOMIC_X86)
9966  #define c89atomic_thread_fence(order) __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory", "cc")
9967  #elif defined(C89ATOMIC_X64)
9968  #define c89atomic_thread_fence(order) __asm__ __volatile__("lock; addq $0, (%%rsp)" ::: "memory", "cc")
9969  #else
9970  #error Unsupported architecture. Please submit a feature request.
9971  #endif
9973  {
9974  c89atomic_uint8 result;
9975  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
9976  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
9977  #else
9978  #error Unsupported architecture. Please submit a feature request.
9979  #endif
9980  return result;
9981  }
9983  {
9984  c89atomic_uint16 result;
9985  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
9986  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
9987  #else
9988  #error Unsupported architecture. Please submit a feature request.
9989  #endif
9990  return result;
9991  }
9993  {
9994  c89atomic_uint32 result;
9995  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
9996  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
9997  #else
9998  #error Unsupported architecture. Please submit a feature request.
9999  #endif
10000  return result;
10001  }
10003  {
10004  volatile c89atomic_uint64 result;
10005  #if defined(C89ATOMIC_X86)
10006  c89atomic_uint32 resultEAX;
10007  c89atomic_uint32 resultEDX;
10008  __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");
10009  result = ((c89atomic_uint64)resultEDX << 32) | resultEAX;
10010  #elif defined(C89ATOMIC_X64)
10011  __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
10012  #else
10013  #error Unsupported architecture. Please submit a feature request.
10014  #endif
10015  return result;
10016  }
10018  {
10019  c89atomic_uint8 result = 0;
10020  (void)order;
10021  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10022  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
10023  #else
10024  #error Unsupported architecture. Please submit a feature request.
10025  #endif
10026  return result;
10027  }
10029  {
10030  c89atomic_uint16 result = 0;
10031  (void)order;
10032  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10033  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
10034  #else
10035  #error Unsupported architecture. Please submit a feature request.
10036  #endif
10037  return result;
10038  }
10040  {
10041  c89atomic_uint32 result;
10042  (void)order;
10043  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10044  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
10045  #else
10046  #error Unsupported architecture. Please submit a feature request.
10047  #endif
10048  return result;
10049  }
10051  {
10052  c89atomic_uint64 result;
10053  (void)order;
10054  #if defined(C89ATOMIC_X86)
10055  do {
10056  result = *dst;
10057  } while (c89atomic_compare_and_swap_64(dst, result, src) != result);
10058  #elif defined(C89ATOMIC_X64)
10059  __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
10060  #else
10061  #error Unsupported architecture. Please submit a feature request.
10062  #endif
10063  return result;
10064  }
10066  {
10067  c89atomic_uint8 result;
10068  (void)order;
10069  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10070  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
10071  #else
10072  #error Unsupported architecture. Please submit a feature request.
10073  #endif
10074  return result;
10075  }
10077  {
10078  c89atomic_uint16 result;
10079  (void)order;
10080  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10081  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
10082  #else
10083  #error Unsupported architecture. Please submit a feature request.
10084  #endif
10085  return result;
10086  }
10088  {
10089  c89atomic_uint32 result;
10090  (void)order;
10091  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10092  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
10093  #else
10094  #error Unsupported architecture. Please submit a feature request.
10095  #endif
10096  return result;
10097  }
10099  {
10100  #if defined(C89ATOMIC_X86)
10101  c89atomic_uint64 oldValue;
10102  c89atomic_uint64 newValue;
10103  (void)order;
10104  do {
10105  oldValue = *dst;
10106  newValue = oldValue + src;
10107  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
10108  return oldValue;
10109  #elif defined(C89ATOMIC_X64)
10110  c89atomic_uint64 result;
10111  (void)order;
10112  __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
10113  return result;
10114  #endif
10115  }
10117  {
10118  c89atomic_uint8 oldValue;
10119  c89atomic_uint8 newValue;
10120  do {
10121  oldValue = *dst;
10122  newValue = (c89atomic_uint8)(oldValue - src);
10123  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
10124  (void)order;
10125  return oldValue;
10126  }
10128  {
10129  c89atomic_uint16 oldValue;
10130  c89atomic_uint16 newValue;
10131  do {
10132  oldValue = *dst;
10133  newValue = (c89atomic_uint16)(oldValue - src);
10134  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
10135  (void)order;
10136  return oldValue;
10137  }
10139  {
10140  c89atomic_uint32 oldValue;
10141  c89atomic_uint32 newValue;
10142  do {
10143  oldValue = *dst;
10144  newValue = oldValue - src;
10145  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
10146  (void)order;
10147  return oldValue;
10148  }
10150  {
10151  c89atomic_uint64 oldValue;
10152  c89atomic_uint64 newValue;
10153  do {
10154  oldValue = *dst;
10155  newValue = oldValue - src;
10156  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
10157  (void)order;
10158  return oldValue;
10159  }
10161  {
10162  c89atomic_uint8 oldValue;
10163  c89atomic_uint8 newValue;
10164  do {
10165  oldValue = *dst;
10166  newValue = (c89atomic_uint8)(oldValue & src);
10167  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
10168  (void)order;
10169  return oldValue;
10170  }
10172  {
10173  c89atomic_uint16 oldValue;
10174  c89atomic_uint16 newValue;
10175  do {
10176  oldValue = *dst;
10177  newValue = (c89atomic_uint16)(oldValue & src);
10178  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
10179  (void)order;
10180  return oldValue;
10181  }
10183  {
10184  c89atomic_uint32 oldValue;
10185  c89atomic_uint32 newValue;
10186  do {
10187  oldValue = *dst;
10188  newValue = oldValue & src;
10189  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
10190  (void)order;
10191  return oldValue;
10192  }
10194  {
10195  c89atomic_uint64 oldValue;
10196  c89atomic_uint64 newValue;
10197  do {
10198  oldValue = *dst;
10199  newValue = oldValue & src;
10200  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
10201  (void)order;
10202  return oldValue;
10203  }
10205  {
10206  c89atomic_uint8 oldValue;
10207  c89atomic_uint8 newValue;
10208  do {
10209  oldValue = *dst;
10210  newValue = (c89atomic_uint8)(oldValue ^ src);
10211  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
10212  (void)order;
10213  return oldValue;
10214  }
10216  {
10217  c89atomic_uint16 oldValue;
10218  c89atomic_uint16 newValue;
10219  do {
10220  oldValue = *dst;
10221  newValue = (c89atomic_uint16)(oldValue ^ src);
10222  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
10223  (void)order;
10224  return oldValue;
10225  }
10227  {
10228  c89atomic_uint32 oldValue;
10229  c89atomic_uint32 newValue;
10230  do {
10231  oldValue = *dst;
10232  newValue = oldValue ^ src;
10233  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
10234  (void)order;
10235  return oldValue;
10236  }
10238  {
10239  c89atomic_uint64 oldValue;
10240  c89atomic_uint64 newValue;
10241  do {
10242  oldValue = *dst;
10243  newValue = oldValue ^ src;
10244  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
10245  (void)order;
10246  return oldValue;
10247  }
10249  {
10250  c89atomic_uint8 oldValue;
10251  c89atomic_uint8 newValue;
10252  do {
10253  oldValue = *dst;
10254  newValue = (c89atomic_uint8)(oldValue | src);
10255  } while (c89atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
10256  (void)order;
10257  return oldValue;
10258  }
10260  {
10261  c89atomic_uint16 oldValue;
10262  c89atomic_uint16 newValue;
10263  do {
10264  oldValue = *dst;
10265  newValue = (c89atomic_uint16)(oldValue | src);
10266  } while (c89atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
10267  (void)order;
10268  return oldValue;
10269  }
10271  {
10272  c89atomic_uint32 oldValue;
10273  c89atomic_uint32 newValue;
10274  do {
10275  oldValue = *dst;
10276  newValue = oldValue | src;
10277  } while (c89atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
10278  (void)order;
10279  return oldValue;
10280  }
10282  {
10283  c89atomic_uint64 oldValue;
10284  c89atomic_uint64 newValue;
10285  do {
10286  oldValue = *dst;
10287  newValue = oldValue | src;
10288  } while (c89atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
10289  (void)order;
10290  return oldValue;
10291  }
10292  #endif
10293  #define c89atomic_signal_fence(order) c89atomic_thread_fence(order)
10295  {
10296  (void)order;
10297  return c89atomic_compare_and_swap_8((c89atomic_uint8*)ptr, 0, 0);
10298  }
10300  {
10301  (void)order;
10302  return c89atomic_compare_and_swap_16((c89atomic_uint16*)ptr, 0, 0);
10303  }
10305  {
10306  (void)order;
10307  return c89atomic_compare_and_swap_32((c89atomic_uint32*)ptr, 0, 0);
10308  }
10310  {
10311  (void)order;
10312  return c89atomic_compare_and_swap_64((c89atomic_uint64*)ptr, 0, 0);
10313  }
10314  #define c89atomic_store_explicit_8( dst, src, order) (void)c89atomic_exchange_explicit_8 (dst, src, order)
10315  #define c89atomic_store_explicit_16(dst, src, order) (void)c89atomic_exchange_explicit_16(dst, src, order)
10316  #define c89atomic_store_explicit_32(dst, src, order) (void)c89atomic_exchange_explicit_32(dst, src, order)
10317  #define c89atomic_store_explicit_64(dst, src, order) (void)c89atomic_exchange_explicit_64(dst, src, order)
10318  #define c89atomic_test_and_set_explicit_8( dst, order) c89atomic_exchange_explicit_8 (dst, 1, order)
10319  #define c89atomic_test_and_set_explicit_16(dst, order) c89atomic_exchange_explicit_16(dst, 1, order)
10320  #define c89atomic_test_and_set_explicit_32(dst, order) c89atomic_exchange_explicit_32(dst, 1, order)
10321  #define c89atomic_test_and_set_explicit_64(dst, order) c89atomic_exchange_explicit_64(dst, 1, order)
10322  #define c89atomic_clear_explicit_8( dst, order) c89atomic_store_explicit_8 (dst, 0, order)
10323  #define c89atomic_clear_explicit_16(dst, order) c89atomic_store_explicit_16(dst, 0, order)
10324  #define c89atomic_clear_explicit_32(dst, order) c89atomic_store_explicit_32(dst, 0, order)
10325  #define c89atomic_clear_explicit_64(dst, order) c89atomic_store_explicit_64(dst, 0, order)
10327  #define c89atomic_flag_test_and_set_explicit(ptr, order) (c89atomic_bool)c89atomic_test_and_set_explicit_8(ptr, order)
10328  #define c89atomic_flag_clear_explicit(ptr, order) c89atomic_clear_explicit_8(ptr, order)
10329  #define c89atoimc_flag_load_explicit(ptr, order) c89atomic_load_explicit_8(ptr, order)
10330 #endif
10331 #if !defined(C89ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE)
10332  #if defined(C89ATOMIC_HAS_8)
10334  {
10335  c89atomic_uint8 expectedValue;
10336  c89atomic_uint8 result;
10337  (void)successOrder;
10338  (void)failureOrder;
10339  expectedValue = c89atomic_load_explicit_8(expected, c89atomic_memory_order_seq_cst);
10340  result = c89atomic_compare_and_swap_8(dst, expectedValue, desired);
10341  if (result == expectedValue) {
10342  return 1;
10343  } else {
10344  c89atomic_store_explicit_8(expected, result, failureOrder);
10345  return 0;
10346  }
10347  }
10348  #endif
10349  #if defined(C89ATOMIC_HAS_16)
10351  {
10352  c89atomic_uint16 expectedValue;
10353  c89atomic_uint16 result;
10354  (void)successOrder;
10355  (void)failureOrder;
10357  result = c89atomic_compare_and_swap_16(dst, expectedValue, desired);
10358  if (result == expectedValue) {
10359  return 1;
10360  } else {
10361  c89atomic_store_explicit_16(expected, result, failureOrder);
10362  return 0;
10363  }
10364  }
10365  #endif
10366  #if defined(C89ATOMIC_HAS_32)
10368  {
10369  c89atomic_uint32 expectedValue;
10370  c89atomic_uint32 result;
10371  (void)successOrder;
10372  (void)failureOrder;
10374  result = c89atomic_compare_and_swap_32(dst, expectedValue, desired);
10375  if (result == expectedValue) {
10376  return 1;
10377  } else {
10378  c89atomic_store_explicit_32(expected, result, failureOrder);
10379  return 0;
10380  }
10381  }
10382  #endif
10383  #if defined(C89ATOMIC_HAS_64)
10385  {
10386  c89atomic_uint64 expectedValue;
10387  c89atomic_uint64 result;
10388  (void)successOrder;
10389  (void)failureOrder;
10391  result = c89atomic_compare_and_swap_64(dst, expectedValue, desired);
10392  if (result == expectedValue) {
10393  return 1;
10394  } else {
10395  c89atomic_store_explicit_64(expected, result, failureOrder);
10396  return 0;
10397  }
10398  }
10399  #endif
10400  #define c89atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_8 (dst, expected, desired, successOrder, failureOrder)
10401  #define c89atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder)
10402  #define c89atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder)
10403  #define c89atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) c89atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder)
10404 #endif
10405 #if !defined(C89ATOMIC_HAS_NATIVE_IS_LOCK_FREE)
10406  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_8(volatile void* ptr)
10407  {
10408  (void)ptr;
10409  return 1;
10410  }
10411  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_16(volatile void* ptr)
10412  {
10413  (void)ptr;
10414  return 1;
10415  }
10416  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_32(volatile void* ptr)
10417  {
10418  (void)ptr;
10419  return 1;
10420  }
10421  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_64(volatile void* ptr)
10422  {
10423  (void)ptr;
10424  #if defined(C89ATOMIC_64BIT)
10425  return 1;
10426  #else
10427  #if defined(C89ATOMIC_X86) || defined(C89ATOMIC_X64)
10428  return 1;
10429  #else
10430  return 0;
10431  #endif
10432  #endif
10433  }
10434 #endif
10435 #if defined(C89ATOMIC_64BIT)
10436  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_ptr(volatile void** ptr)
10437  {
10438  return c89atomic_is_lock_free_64((volatile c89atomic_uint64*)ptr);
10439  }
10440  static C89ATOMIC_INLINE void* c89atomic_load_explicit_ptr(volatile void** ptr, c89atomic_memory_order order)
10441  {
10442  return (void*)c89atomic_load_explicit_64((volatile c89atomic_uint64*)ptr, order);
10443  }
10444  static C89ATOMIC_INLINE void c89atomic_store_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
10445  {
10446  c89atomic_store_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64)src, order);
10447  }
10448  static C89ATOMIC_INLINE void* c89atomic_exchange_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
10449  {
10450  return (void*)c89atomic_exchange_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64)src, order);
10451  }
10452  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)
10453  {
10454  return c89atomic_compare_exchange_strong_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64*)expected, (c89atomic_uint64)desired, successOrder, failureOrder);
10455  }
10456  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)
10457  {
10458  return c89atomic_compare_exchange_weak_explicit_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64*)expected, (c89atomic_uint64)desired, successOrder, failureOrder);
10459  }
10460  static C89ATOMIC_INLINE void* c89atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired)
10461  {
10462  return (void*)c89atomic_compare_and_swap_64((volatile c89atomic_uint64*)dst, (c89atomic_uint64)expected, (c89atomic_uint64)desired);
10463  }
10464 #elif defined(C89ATOMIC_32BIT)
10465  static C89ATOMIC_INLINE c89atomic_bool c89atomic_is_lock_free_ptr(volatile void** ptr)
10466  {
10467  return c89atomic_is_lock_free_32((volatile c89atomic_uint32*)ptr);
10468  }
10469  static C89ATOMIC_INLINE void* c89atomic_load_explicit_ptr(volatile void** ptr, c89atomic_memory_order order)
10470  {
10471  return (void*)c89atomic_load_explicit_32((volatile c89atomic_uint32*)ptr, order);
10472  }
10473  static C89ATOMIC_INLINE void c89atomic_store_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
10474  {
10475  c89atomic_store_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32)src, order);
10476  }
10477  static C89ATOMIC_INLINE void* c89atomic_exchange_explicit_ptr(volatile void** dst, void* src, c89atomic_memory_order order)
10478  {
10479  return (void*)c89atomic_exchange_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32)src, order);
10480  }
10481  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)
10482  {
10483  return c89atomic_compare_exchange_strong_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32*)expected, (c89atomic_uint32)desired, successOrder, failureOrder);
10484  }
10485  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)
10486  {
10487  return c89atomic_compare_exchange_weak_explicit_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32*)expected, (c89atomic_uint32)desired, successOrder, failureOrder);
10488  }
10489  static C89ATOMIC_INLINE void* c89atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired)
10490  {
10491  return (void*)c89atomic_compare_and_swap_32((volatile c89atomic_uint32*)dst, (c89atomic_uint32)expected, (c89atomic_uint32)desired);
10492  }
10493 #else
10494  #error Unsupported architecture.
10495 #endif
10496 #define c89atomic_flag_test_and_set(ptr) c89atomic_flag_test_and_set_explicit(ptr, c89atomic_memory_order_seq_cst)
10497 #define c89atomic_flag_clear(ptr) c89atomic_flag_clear_explicit(ptr, c89atomic_memory_order_seq_cst)
10498 #define c89atomic_store_ptr(dst, src) c89atomic_store_explicit_ptr((volatile void**)dst, (void*)src, c89atomic_memory_order_seq_cst)
10499 #define c89atomic_load_ptr(ptr) c89atomic_load_explicit_ptr((volatile void**)ptr, c89atomic_memory_order_seq_cst)
10500 #define c89atomic_exchange_ptr(dst, src) c89atomic_exchange_explicit_ptr((volatile void**)dst, (void*)src, c89atomic_memory_order_seq_cst)
10501 #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)
10502 #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)
10503 #define c89atomic_test_and_set_8( ptr) c89atomic_test_and_set_explicit_8( ptr, c89atomic_memory_order_seq_cst)
10504 #define c89atomic_test_and_set_16(ptr) c89atomic_test_and_set_explicit_16(ptr, c89atomic_memory_order_seq_cst)
10505 #define c89atomic_test_and_set_32(ptr) c89atomic_test_and_set_explicit_32(ptr, c89atomic_memory_order_seq_cst)
10506 #define c89atomic_test_and_set_64(ptr) c89atomic_test_and_set_explicit_64(ptr, c89atomic_memory_order_seq_cst)
10507 #define c89atomic_clear_8( ptr) c89atomic_clear_explicit_8( ptr, c89atomic_memory_order_seq_cst)
10508 #define c89atomic_clear_16(ptr) c89atomic_clear_explicit_16(ptr, c89atomic_memory_order_seq_cst)
10509 #define c89atomic_clear_32(ptr) c89atomic_clear_explicit_32(ptr, c89atomic_memory_order_seq_cst)
10510 #define c89atomic_clear_64(ptr) c89atomic_clear_explicit_64(ptr, c89atomic_memory_order_seq_cst)
10511 #define c89atomic_store_8( dst, src) c89atomic_store_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
10512 #define c89atomic_store_16(dst, src) c89atomic_store_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10513 #define c89atomic_store_32(dst, src) c89atomic_store_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10514 #define c89atomic_store_64(dst, src) c89atomic_store_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10515 #define c89atomic_load_8( ptr) c89atomic_load_explicit_8( ptr, c89atomic_memory_order_seq_cst)
10516 #define c89atomic_load_16(ptr) c89atomic_load_explicit_16(ptr, c89atomic_memory_order_seq_cst)
10517 #define c89atomic_load_32(ptr) c89atomic_load_explicit_32(ptr, c89atomic_memory_order_seq_cst)
10518 #define c89atomic_load_64(ptr) c89atomic_load_explicit_64(ptr, c89atomic_memory_order_seq_cst)
10519 #define c89atomic_exchange_8( dst, src) c89atomic_exchange_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
10520 #define c89atomic_exchange_16(dst, src) c89atomic_exchange_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10521 #define c89atomic_exchange_32(dst, src) c89atomic_exchange_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10522 #define c89atomic_exchange_64(dst, src) c89atomic_exchange_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10523 #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)
10524 #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)
10525 #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)
10526 #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)
10527 #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)
10528 #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)
10529 #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)
10530 #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)
10531 #define c89atomic_fetch_add_8( dst, src) c89atomic_fetch_add_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
10532 #define c89atomic_fetch_add_16(dst, src) c89atomic_fetch_add_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10533 #define c89atomic_fetch_add_32(dst, src) c89atomic_fetch_add_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10534 #define c89atomic_fetch_add_64(dst, src) c89atomic_fetch_add_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10535 #define c89atomic_fetch_sub_8( dst, src) c89atomic_fetch_sub_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
10536 #define c89atomic_fetch_sub_16(dst, src) c89atomic_fetch_sub_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10537 #define c89atomic_fetch_sub_32(dst, src) c89atomic_fetch_sub_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10538 #define c89atomic_fetch_sub_64(dst, src) c89atomic_fetch_sub_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10539 #define c89atomic_fetch_or_8( dst, src) c89atomic_fetch_or_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
10540 #define c89atomic_fetch_or_16(dst, src) c89atomic_fetch_or_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10541 #define c89atomic_fetch_or_32(dst, src) c89atomic_fetch_or_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10542 #define c89atomic_fetch_or_64(dst, src) c89atomic_fetch_or_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10543 #define c89atomic_fetch_xor_8( dst, src) c89atomic_fetch_xor_explicit_8( dst, src, c89atomic_memory_order_seq_cst)
10544 #define c89atomic_fetch_xor_16(dst, src) c89atomic_fetch_xor_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10545 #define c89atomic_fetch_xor_32(dst, src) c89atomic_fetch_xor_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10546 #define c89atomic_fetch_xor_64(dst, src) c89atomic_fetch_xor_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10547 #define c89atomic_fetch_and_8( dst, src) c89atomic_fetch_and_explicit_8 (dst, src, c89atomic_memory_order_seq_cst)
10548 #define c89atomic_fetch_and_16(dst, src) c89atomic_fetch_and_explicit_16(dst, src, c89atomic_memory_order_seq_cst)
10549 #define c89atomic_fetch_and_32(dst, src) c89atomic_fetch_and_explicit_32(dst, src, c89atomic_memory_order_seq_cst)
10550 #define c89atomic_fetch_and_64(dst, src) c89atomic_fetch_and_explicit_64(dst, src, c89atomic_memory_order_seq_cst)
10551 #define c89atomic_test_and_set_explicit_i8( ptr, order) (c89atomic_int8 )c89atomic_test_and_set_explicit_8( (c89atomic_uint8* )ptr, order)
10552 #define c89atomic_test_and_set_explicit_i16(ptr, order) (c89atomic_int16)c89atomic_test_and_set_explicit_16((c89atomic_uint16*)ptr, order)
10553 #define c89atomic_test_and_set_explicit_i32(ptr, order) (c89atomic_int32)c89atomic_test_and_set_explicit_32((c89atomic_uint32*)ptr, order)
10554 #define c89atomic_test_and_set_explicit_i64(ptr, order) (c89atomic_int64)c89atomic_test_and_set_explicit_64((c89atomic_uint64*)ptr, order)
10555 #define c89atomic_clear_explicit_i8( ptr, order) c89atomic_clear_explicit_8( (c89atomic_uint8* )ptr, order)
10556 #define c89atomic_clear_explicit_i16(ptr, order) c89atomic_clear_explicit_16((c89atomic_uint16*)ptr, order)
10557 #define c89atomic_clear_explicit_i32(ptr, order) c89atomic_clear_explicit_32((c89atomic_uint32*)ptr, order)
10558 #define c89atomic_clear_explicit_i64(ptr, order) c89atomic_clear_explicit_64((c89atomic_uint64*)ptr, order)
10559 #define c89atomic_store_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_store_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10560 #define c89atomic_store_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_store_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10561 #define c89atomic_store_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_store_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10562 #define c89atomic_store_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_store_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10563 #define c89atomic_load_explicit_i8( ptr, order) (c89atomic_int8 )c89atomic_load_explicit_8( (c89atomic_uint8* )ptr, order)
10564 #define c89atomic_load_explicit_i16(ptr, order) (c89atomic_int16)c89atomic_load_explicit_16((c89atomic_uint16*)ptr, order)
10565 #define c89atomic_load_explicit_i32(ptr, order) (c89atomic_int32)c89atomic_load_explicit_32((c89atomic_uint32*)ptr, order)
10566 #define c89atomic_load_explicit_i64(ptr, order) (c89atomic_int64)c89atomic_load_explicit_64((c89atomic_uint64*)ptr, order)
10567 #define c89atomic_exchange_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_exchange_explicit_8 ((c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10568 #define c89atomic_exchange_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_exchange_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10569 #define c89atomic_exchange_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_exchange_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10570 #define c89atomic_exchange_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_exchange_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10571 #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)
10572 #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)
10573 #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)
10574 #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)
10575 #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)
10576 #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)
10577 #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)
10578 #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)
10579 #define c89atomic_fetch_add_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_add_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10580 #define c89atomic_fetch_add_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_add_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10581 #define c89atomic_fetch_add_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_add_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10582 #define c89atomic_fetch_add_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_add_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10583 #define c89atomic_fetch_sub_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_sub_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10584 #define c89atomic_fetch_sub_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_sub_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10585 #define c89atomic_fetch_sub_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_sub_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10586 #define c89atomic_fetch_sub_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_sub_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10587 #define c89atomic_fetch_or_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_or_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10588 #define c89atomic_fetch_or_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_or_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10589 #define c89atomic_fetch_or_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_or_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10590 #define c89atomic_fetch_or_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_or_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10591 #define c89atomic_fetch_xor_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_xor_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10592 #define c89atomic_fetch_xor_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_xor_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10593 #define c89atomic_fetch_xor_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_xor_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10594 #define c89atomic_fetch_xor_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_xor_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10595 #define c89atomic_fetch_and_explicit_i8( dst, src, order) (c89atomic_int8 )c89atomic_fetch_and_explicit_8( (c89atomic_uint8* )dst, (c89atomic_uint8 )src, order)
10596 #define c89atomic_fetch_and_explicit_i16(dst, src, order) (c89atomic_int16)c89atomic_fetch_and_explicit_16((c89atomic_uint16*)dst, (c89atomic_uint16)src, order)
10597 #define c89atomic_fetch_and_explicit_i32(dst, src, order) (c89atomic_int32)c89atomic_fetch_and_explicit_32((c89atomic_uint32*)dst, (c89atomic_uint32)src, order)
10598 #define c89atomic_fetch_and_explicit_i64(dst, src, order) (c89atomic_int64)c89atomic_fetch_and_explicit_64((c89atomic_uint64*)dst, (c89atomic_uint64)src, order)
10599 #define c89atomic_test_and_set_i8( ptr) c89atomic_test_and_set_explicit_i8( ptr, c89atomic_memory_order_seq_cst)
10600 #define c89atomic_test_and_set_i16(ptr) c89atomic_test_and_set_explicit_i16(ptr, c89atomic_memory_order_seq_cst)
10601 #define c89atomic_test_and_set_i32(ptr) c89atomic_test_and_set_explicit_i32(ptr, c89atomic_memory_order_seq_cst)
10602 #define c89atomic_test_and_set_i64(ptr) c89atomic_test_and_set_explicit_i64(ptr, c89atomic_memory_order_seq_cst)
10603 #define c89atomic_clear_i8( ptr) c89atomic_clear_explicit_i8( ptr, c89atomic_memory_order_seq_cst)
10604 #define c89atomic_clear_i16(ptr) c89atomic_clear_explicit_i16(ptr, c89atomic_memory_order_seq_cst)
10605 #define c89atomic_clear_i32(ptr) c89atomic_clear_explicit_i32(ptr, c89atomic_memory_order_seq_cst)
10606 #define c89atomic_clear_i64(ptr) c89atomic_clear_explicit_i64(ptr, c89atomic_memory_order_seq_cst)
10607 #define c89atomic_store_i8( dst, src) c89atomic_store_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10608 #define c89atomic_store_i16(dst, src) c89atomic_store_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10609 #define c89atomic_store_i32(dst, src) c89atomic_store_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10610 #define c89atomic_store_i64(dst, src) c89atomic_store_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10611 #define c89atomic_load_i8( ptr) c89atomic_load_explicit_i8( ptr, c89atomic_memory_order_seq_cst)
10612 #define c89atomic_load_i16(ptr) c89atomic_load_explicit_i16(ptr, c89atomic_memory_order_seq_cst)
10613 #define c89atomic_load_i32(ptr) c89atomic_load_explicit_i32(ptr, c89atomic_memory_order_seq_cst)
10614 #define c89atomic_load_i64(ptr) c89atomic_load_explicit_i64(ptr, c89atomic_memory_order_seq_cst)
10615 #define c89atomic_exchange_i8( dst, src) c89atomic_exchange_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10616 #define c89atomic_exchange_i16(dst, src) c89atomic_exchange_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10617 #define c89atomic_exchange_i32(dst, src) c89atomic_exchange_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10618 #define c89atomic_exchange_i64(dst, src) c89atomic_exchange_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10619 #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)
10620 #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)
10621 #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)
10622 #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)
10623 #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)
10624 #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)
10625 #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)
10626 #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)
10627 #define c89atomic_fetch_add_i8( dst, src) c89atomic_fetch_add_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10628 #define c89atomic_fetch_add_i16(dst, src) c89atomic_fetch_add_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10629 #define c89atomic_fetch_add_i32(dst, src) c89atomic_fetch_add_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10630 #define c89atomic_fetch_add_i64(dst, src) c89atomic_fetch_add_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10631 #define c89atomic_fetch_sub_i8( dst, src) c89atomic_fetch_sub_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10632 #define c89atomic_fetch_sub_i16(dst, src) c89atomic_fetch_sub_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10633 #define c89atomic_fetch_sub_i32(dst, src) c89atomic_fetch_sub_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10634 #define c89atomic_fetch_sub_i64(dst, src) c89atomic_fetch_sub_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10635 #define c89atomic_fetch_or_i8( dst, src) c89atomic_fetch_or_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10636 #define c89atomic_fetch_or_i16(dst, src) c89atomic_fetch_or_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10637 #define c89atomic_fetch_or_i32(dst, src) c89atomic_fetch_or_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10638 #define c89atomic_fetch_or_i64(dst, src) c89atomic_fetch_or_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10639 #define c89atomic_fetch_xor_i8( dst, src) c89atomic_fetch_xor_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10640 #define c89atomic_fetch_xor_i16(dst, src) c89atomic_fetch_xor_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10641 #define c89atomic_fetch_xor_i32(dst, src) c89atomic_fetch_xor_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10642 #define c89atomic_fetch_xor_i64(dst, src) c89atomic_fetch_xor_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10643 #define c89atomic_fetch_and_i8( dst, src) c89atomic_fetch_and_explicit_i8( dst, src, c89atomic_memory_order_seq_cst)
10644 #define c89atomic_fetch_and_i16(dst, src) c89atomic_fetch_and_explicit_i16(dst, src, c89atomic_memory_order_seq_cst)
10645 #define c89atomic_fetch_and_i32(dst, src) c89atomic_fetch_and_explicit_i32(dst, src, c89atomic_memory_order_seq_cst)
10646 #define c89atomic_fetch_and_i64(dst, src) c89atomic_fetch_and_explicit_i64(dst, src, c89atomic_memory_order_seq_cst)
10647 typedef union
10648 {
10649  c89atomic_uint32 i;
10650  float f;
10651 } c89atomic_if32;
10652 typedef union
10653 {
10654  c89atomic_uint64 i;
10655  double f;
10656 } c89atomic_if64;
10657 #define c89atomic_clear_explicit_f32(ptr, order) c89atomic_clear_explicit_32((c89atomic_uint32*)ptr, order)
10658 #define c89atomic_clear_explicit_f64(ptr, order) c89atomic_clear_explicit_64((c89atomic_uint64*)ptr, order)
10659 static C89ATOMIC_INLINE void c89atomic_store_explicit_f32(volatile float* dst, float src, c89atomic_memory_order order)
10660 {
10661  c89atomic_if32 x;
10662  x.f = src;
10663  c89atomic_store_explicit_32((volatile c89atomic_uint32*)dst, x.i, order);
10664 }
10665 static C89ATOMIC_INLINE void c89atomic_store_explicit_f64(volatile double* dst, double src, c89atomic_memory_order order)
10666 {
10667  c89atomic_if64 x;
10668  x.f = src;
10669  c89atomic_store_explicit_64((volatile c89atomic_uint64*)dst, x.i, order);
10670 }
10671 static C89ATOMIC_INLINE float c89atomic_load_explicit_f32(volatile float* ptr, c89atomic_memory_order order)
10672 {
10673  c89atomic_if32 r;
10674  r.i = c89atomic_load_explicit_32((volatile c89atomic_uint32*)ptr, order);
10675  return r.f;
10676 }
10677 static C89ATOMIC_INLINE double c89atomic_load_explicit_f64(volatile double* ptr, c89atomic_memory_order order)
10678 {
10679  c89atomic_if64 r;
10680  r.i = c89atomic_load_explicit_64((volatile c89atomic_uint64*)ptr, order);
10681  return r.f;
10682 }
10683 static C89ATOMIC_INLINE float c89atomic_exchange_explicit_f32(volatile float* dst, float src, c89atomic_memory_order order)
10684 {
10685  c89atomic_if32 r;
10686  c89atomic_if32 x;
10687  x.f = src;
10688  r.i = c89atomic_exchange_explicit_32((volatile c89atomic_uint32*)dst, x.i, order);
10689  return r.f;
10690 }
10691 static C89ATOMIC_INLINE double c89atomic_exchange_explicit_f64(volatile double* dst, double src, c89atomic_memory_order order)
10692 {
10693  c89atomic_if64 r;
10694  c89atomic_if64 x;
10695  x.f = src;
10696  r.i = c89atomic_exchange_explicit_64((volatile c89atomic_uint64*)dst, x.i, order);
10697  return r.f;
10698 }
10699 #define c89atomic_clear_f32(ptr) (float )c89atomic_clear_explicit_f32(ptr, c89atomic_memory_order_seq_cst)
10700 #define c89atomic_clear_f64(ptr) (double)c89atomic_clear_explicit_f64(ptr, c89atomic_memory_order_seq_cst)
10701 #define c89atomic_store_f32(dst, src) c89atomic_store_explicit_f32(dst, src, c89atomic_memory_order_seq_cst)
10702 #define c89atomic_store_f64(dst, src) c89atomic_store_explicit_f64(dst, src, c89atomic_memory_order_seq_cst)
10703 #define c89atomic_load_f32(ptr) (float )c89atomic_load_explicit_f32(ptr, c89atomic_memory_order_seq_cst)
10704 #define c89atomic_load_f64(ptr) (double)c89atomic_load_explicit_f64(ptr, c89atomic_memory_order_seq_cst)
10705 #define c89atomic_exchange_f32(dst, src) (float )c89atomic_exchange_explicit_f32(dst, src, c89atomic_memory_order_seq_cst)
10706 #define c89atomic_exchange_f64(dst, src) (double)c89atomic_exchange_explicit_f64(dst, src, c89atomic_memory_order_seq_cst)
10708 static C89ATOMIC_INLINE void c89atomic_spinlock_lock(volatile c89atomic_spinlock* pSpinlock)
10709 {
10710  for (;;) {
10712  break;
10713  }
10715  }
10716  }
10717 }
10718 static C89ATOMIC_INLINE void c89atomic_spinlock_unlock(volatile c89atomic_spinlock* pSpinlock)
10719 {
10721 }
10722 #if defined(__cplusplus)
10723 }
10724 #endif
10725 #endif
10726 /* c89atomic.h end */
10727 
10728 
10729 
10731 {
10732  /* For robustness we're going to use a resampler object to calculate this since that already has a way of calculating this. */
10733  ma_result result;
10734  ma_uint64 frameCountOut;
10736  ma_resampler resampler;
10737 
10738  if (sampleRateOut == sampleRateIn) {
10739  return frameCountIn;
10740  }
10741 
10742  config = ma_resampler_config_init(ma_format_s16, 1, sampleRateIn, sampleRateOut, ma_resample_algorithm_linear);
10743  result = ma_resampler_init(&config, &resampler);
10744  if (result != MA_SUCCESS) {
10745  return 0;
10746  }
10747 
10748  frameCountOut = ma_resampler_get_expected_output_frame_count(&resampler, frameCountIn);
10749 
10750  ma_resampler_uninit(&resampler);
10751  return frameCountOut;
10752 }
10753 
10754 #ifndef MA_DATA_CONVERTER_STACK_BUFFER_SIZE
10755 #define MA_DATA_CONVERTER_STACK_BUFFER_SIZE 4096
10756 #endif
10757 
10758 
10759 
10760 #if defined(MA_WIN32)
10761 static ma_result ma_result_from_GetLastError(DWORD error)
10762 {
10763  switch (error)
10764  {
10765  case ERROR_SUCCESS: return MA_SUCCESS;
10766  case ERROR_PATH_NOT_FOUND: return MA_DOES_NOT_EXIST;
10767  case ERROR_TOO_MANY_OPEN_FILES: return MA_TOO_MANY_OPEN_FILES;
10768  case ERROR_NOT_ENOUGH_MEMORY: return MA_OUT_OF_MEMORY;
10769  case ERROR_DISK_FULL: return MA_NO_SPACE;
10770  case ERROR_HANDLE_EOF: return MA_AT_END;
10771  case ERROR_NEGATIVE_SEEK: return MA_BAD_SEEK;
10772  case ERROR_INVALID_PARAMETER: return MA_INVALID_ARGS;
10773  case ERROR_ACCESS_DENIED: return MA_ACCESS_DENIED;
10774  case ERROR_SEM_TIMEOUT: return MA_TIMEOUT;
10775  case ERROR_FILE_NOT_FOUND: return MA_DOES_NOT_EXIST;
10776  default: break;
10777  }
10778 
10779  return MA_ERROR;
10780 }
10781 #endif /* MA_WIN32 */
10782 
10783 
10784 /*******************************************************************************
10785 
10786 Threading
10787 
10788 *******************************************************************************/
10789 #ifndef MA_NO_THREADING
10790 #ifdef MA_WIN32
10791  #define MA_THREADCALL WINAPI
10792  typedef unsigned long ma_thread_result;
10793 #else
10794  #define MA_THREADCALL
10795  typedef void* ma_thread_result;
10796 #endif
10797 typedef ma_thread_result (MA_THREADCALL * ma_thread_entry_proc)(void* pData);
10798 
10799 static MA_INLINE ma_result ma_spinlock_lock_ex(volatile ma_spinlock* pSpinlock, ma_bool32 yield)
10800 {
10801  if (pSpinlock == NULL) {
10802  return MA_INVALID_ARGS;
10803  }
10804 
10805  for (;;) {
10807  break;
10808  }
10809 
10811  if (yield) {
10812  ma_yield();
10813  }
10814  }
10815  }
10816 
10817  return MA_SUCCESS;
10818 }
10819 
10820 MA_API ma_result ma_spinlock_lock(volatile ma_spinlock* pSpinlock)
10821 {
10822  return ma_spinlock_lock_ex(pSpinlock, MA_TRUE);
10823 }
10824 
10826 {
10827  return ma_spinlock_lock_ex(pSpinlock, MA_FALSE);
10828 }
10829 
10830 MA_API ma_result ma_spinlock_unlock(volatile ma_spinlock* pSpinlock)
10831 {
10832  if (pSpinlock == NULL) {
10833  return MA_INVALID_ARGS;
10834  }
10835 
10837  return MA_SUCCESS;
10838 }
10839 
10840 #ifdef MA_WIN32
10841 static int ma_thread_priority_to_win32(ma_thread_priority priority)
10842 {
10843  switch (priority) {
10844  case ma_thread_priority_idle: return THREAD_PRIORITY_IDLE;
10845  case ma_thread_priority_lowest: return THREAD_PRIORITY_LOWEST;
10846  case ma_thread_priority_low: return THREAD_PRIORITY_BELOW_NORMAL;
10847  case ma_thread_priority_normal: return THREAD_PRIORITY_NORMAL;
10848  case ma_thread_priority_high: return THREAD_PRIORITY_ABOVE_NORMAL;
10849  case ma_thread_priority_highest: return THREAD_PRIORITY_HIGHEST;
10850  case ma_thread_priority_realtime: return THREAD_PRIORITY_TIME_CRITICAL;
10851  default: return THREAD_PRIORITY_NORMAL;
10852  }
10853 }
10854 
10855 static ma_result ma_thread_create__win32(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
10856 {
10857  *pThread = CreateThread(NULL, stackSize, entryProc, pData, 0, NULL);
10858  if (*pThread == NULL) {
10859  return ma_result_from_GetLastError(GetLastError());
10860  }
10861 
10862  SetThreadPriority((HANDLE)*pThread, ma_thread_priority_to_win32(priority));
10863 
10864  return MA_SUCCESS;
10865 }
10866 
10867 static void ma_thread_wait__win32(ma_thread* pThread)
10868 {
10869  WaitForSingleObject((HANDLE)*pThread, INFINITE);
10870  CloseHandle((HANDLE)*pThread);
10871 }
10872 
10873 
10874 static ma_result ma_mutex_init__win32(ma_mutex* pMutex)
10875 {
10876  *pMutex = CreateEventW(NULL, FALSE, TRUE, NULL);
10877  if (*pMutex == NULL) {
10878  return ma_result_from_GetLastError(GetLastError());
10879  }
10880 
10881  return MA_SUCCESS;
10882 }
10883 
10884 static void ma_mutex_uninit__win32(ma_mutex* pMutex)
10885 {
10886  CloseHandle((HANDLE)*pMutex);
10887 }
10888 
10889 static void ma_mutex_lock__win32(ma_mutex* pMutex)
10890 {
10891  WaitForSingleObject((HANDLE)*pMutex, INFINITE);
10892 }
10893 
10894 static void ma_mutex_unlock__win32(ma_mutex* pMutex)
10895 {
10896  SetEvent((HANDLE)*pMutex);
10897 }
10898 
10899 
10900 static ma_result ma_event_init__win32(ma_event* pEvent)
10901 {
10902  *pEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
10903  if (*pEvent == NULL) {
10904  return ma_result_from_GetLastError(GetLastError());
10905  }
10906 
10907  return MA_SUCCESS;
10908 }
10909 
10910 static void ma_event_uninit__win32(ma_event* pEvent)
10911 {
10912  CloseHandle((HANDLE)*pEvent);
10913 }
10914 
10915 static ma_result ma_event_wait__win32(ma_event* pEvent)
10916 {
10917  DWORD result = WaitForSingleObject((HANDLE)*pEvent, INFINITE);
10918  if (result == WAIT_OBJECT_0) {
10919  return MA_SUCCESS;
10920  }
10921 
10922  if (result == WAIT_TIMEOUT) {
10923  return MA_TIMEOUT;
10924  }
10925 
10926  return ma_result_from_GetLastError(GetLastError());
10927 }
10928 
10929 static ma_result ma_event_signal__win32(ma_event* pEvent)
10930 {
10931  BOOL result = SetEvent((HANDLE)*pEvent);
10932  if (result == 0) {
10933  return ma_result_from_GetLastError(GetLastError());
10934  }
10935 
10936  return MA_SUCCESS;
10937 }
10938 
10939 
10940 static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemaphore)
10941 {
10942  *pSemaphore = CreateSemaphoreW(NULL, (LONG)initialValue, LONG_MAX, NULL);
10943  if (*pSemaphore == NULL) {
10944  return ma_result_from_GetLastError(GetLastError());
10945  }
10946 
10947  return MA_SUCCESS;
10948 }
10949 
10950 static void ma_semaphore_uninit__win32(ma_semaphore* pSemaphore)
10951 {
10952  CloseHandle((HANDLE)*pSemaphore);
10953 }
10954 
10955 static ma_result ma_semaphore_wait__win32(ma_semaphore* pSemaphore)
10956 {
10957  DWORD result = WaitForSingleObject((HANDLE)*pSemaphore, INFINITE);
10958  if (result == WAIT_OBJECT_0) {
10959  return MA_SUCCESS;
10960  }
10961 
10962  if (result == WAIT_TIMEOUT) {
10963  return MA_TIMEOUT;
10964  }
10965 
10966  return ma_result_from_GetLastError(GetLastError());
10967 }
10968 
10969 static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore)
10970 {
10971  BOOL result = ReleaseSemaphore((HANDLE)*pSemaphore, 1, NULL);
10972  if (result == 0) {
10973  return ma_result_from_GetLastError(GetLastError());
10974  }
10975 
10976  return MA_SUCCESS;
10977 }
10978 #endif
10979 
10980 
10981 #ifdef MA_POSIX
10982 static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
10983 {
10984  int result;
10985  pthread_attr_t* pAttr = NULL;
10986 
10987 #if !defined(__EMSCRIPTEN__)
10988  /* Try setting the thread priority. It's not critical if anything fails here. */
10989  pthread_attr_t attr;
10990  if (pthread_attr_init(&attr) == 0) {
10991  int scheduler = -1;
10992  if (priority == ma_thread_priority_idle) {
10993 #ifdef SCHED_IDLE
10994  if (pthread_attr_setschedpolicy(&attr, SCHED_IDLE) == 0) {
10995  scheduler = SCHED_IDLE;
10996  }
10997 #endif
10998  } else if (priority == ma_thread_priority_realtime) {
10999 #ifdef SCHED_FIFO
11000  if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0) {
11001  scheduler = SCHED_FIFO;
11002  }
11003 #endif
11004 #ifdef MA_LINUX
11005  } else {
11006  scheduler = sched_getscheduler(0);
11007 #endif
11008  }
11009 
11010  if (stackSize > 0) {
11011  pthread_attr_setstacksize(&attr, stackSize);
11012  }
11013 
11014  if (scheduler != -1) {
11015  int priorityMin = sched_get_priority_min(scheduler);
11016  int priorityMax = sched_get_priority_max(scheduler);
11017  int priorityStep = (priorityMax - priorityMin) / 7; /* 7 = number of priorities supported by miniaudio. */
11018 
11019  struct sched_param sched;
11020  if (pthread_attr_getschedparam(&attr, &sched) == 0) {
11021  if (priority == ma_thread_priority_idle) {
11022  sched.sched_priority = priorityMin;
11023  } else if (priority == ma_thread_priority_realtime) {
11024  sched.sched_priority = priorityMax;
11025  } else {
11026  sched.sched_priority += ((int)priority + 5) * priorityStep; /* +5 because the lowest priority is -5. */
11027  if (sched.sched_priority < priorityMin) {
11028  sched.sched_priority = priorityMin;
11029  }
11030  if (sched.sched_priority > priorityMax) {
11031  sched.sched_priority = priorityMax;
11032  }
11033  }
11034 
11035  if (pthread_attr_setschedparam(&attr, &sched) == 0) {
11036  pAttr = &attr;
11037  }
11038  }
11039  }
11040  }
11041 #else
11042  /* It's the emscripten build. We'll have a few unused parameters. */
11043  (void)priority;
11044  (void)stackSize;
11045 #endif
11046 
11047  result = pthread_create(pThread, pAttr, entryProc, pData);
11048 
11049  /* The thread attributes object is no longer required. */
11050  if (pAttr != NULL) {
11051  pthread_attr_destroy(pAttr);
11052  }
11053 
11054  if (result != 0) {
11055  return ma_result_from_errno(result);
11056  }
11057 
11058  return MA_SUCCESS;
11059 }
11060 
11061 static void ma_thread_wait__posix(ma_thread* pThread)
11062 {
11063  pthread_join(*pThread, NULL);
11064  pthread_detach(*pThread);
11065 }
11066 
11067 
11068 static ma_result ma_mutex_init__posix(ma_mutex* pMutex)
11069 {
11070  int result = pthread_mutex_init((pthread_mutex_t*)pMutex, NULL);
11071  if (result != 0) {
11072  return ma_result_from_errno(result);
11073  }
11074 
11075  return MA_SUCCESS;
11076 }
11077 
11078 static void ma_mutex_uninit__posix(ma_mutex* pMutex)
11079 {
11080  pthread_mutex_destroy((pthread_mutex_t*)pMutex);
11081 }
11082 
11083 static void ma_mutex_lock__posix(ma_mutex* pMutex)
11084 {
11085  pthread_mutex_lock((pthread_mutex_t*)pMutex);
11086 }
11087 
11088 static void ma_mutex_unlock__posix(ma_mutex* pMutex)
11089 {
11090  pthread_mutex_unlock((pthread_mutex_t*)pMutex);
11091 }
11092 
11093 
11094 static ma_result ma_event_init__posix(ma_event* pEvent)
11095 {
11096  int result;
11097 
11098  result = pthread_mutex_init(&pEvent->lock, NULL);
11099  if (result != 0) {
11100  return ma_result_from_errno(result);
11101  }
11102 
11103  result = pthread_cond_init(&pEvent->cond, NULL);
11104  if (result != 0) {
11105  pthread_mutex_destroy(&pEvent->lock);
11106  return ma_result_from_errno(result);
11107  }
11108 
11109  pEvent->value = 0;
11110  return MA_SUCCESS;
11111 }
11112 
11113 static void ma_event_uninit__posix(ma_event* pEvent)
11114 {
11115  pthread_cond_destroy(&pEvent->cond);
11116  pthread_mutex_destroy(&pEvent->lock);
11117 }
11118 
11119 static ma_result ma_event_wait__posix(ma_event* pEvent)
11120 {
11121  pthread_mutex_lock(&pEvent->lock);
11122  {
11123  while (pEvent->value == 0) {
11124  pthread_cond_wait(&pEvent->cond, &pEvent->lock);
11125  }
11126  pEvent->value = 0; /* Auto-reset. */
11127  }
11128  pthread_mutex_unlock(&pEvent->lock);
11129 
11130  return MA_SUCCESS;
11131 }
11132 
11134 {
11135  pthread_mutex_lock(&pEvent->lock);
11136  {
11137  pEvent->value = 1;
11138  pthread_cond_signal(&pEvent->cond);
11139  }
11140  pthread_mutex_unlock(&pEvent->lock);
11141 
11142  return MA_SUCCESS;
11143 }
11144 
11145 
11146 static ma_result ma_semaphore_init__posix(int initialValue, ma_semaphore* pSemaphore)
11147 {
11148  int result;
11149 
11150  if (pSemaphore == NULL) {
11151  return MA_INVALID_ARGS;
11152  }
11153 
11154  pSemaphore->value = initialValue;
11155 
11156  result = pthread_mutex_init(&pSemaphore->lock, NULL);
11157  if (result != 0) {
11158  return ma_result_from_errno(result); /* Failed to create mutex. */
11159  }
11160 
11161  result = pthread_cond_init(&pSemaphore->cond, NULL);
11162  if (result != 0) {
11163  pthread_mutex_destroy(&pSemaphore->lock);
11164  return ma_result_from_errno(result); /* Failed to create condition variable. */
11165  }
11166 
11167  return MA_SUCCESS;
11168 }
11169 
11170 static void ma_semaphore_uninit__posix(ma_semaphore* pSemaphore)
11171 {
11172  if (pSemaphore == NULL) {
11173  return;
11174  }
11175 
11176  pthread_cond_destroy(&pSemaphore->cond);
11177  pthread_mutex_destroy(&pSemaphore->lock);
11178 }
11179 
11181 {
11182  if (pSemaphore == NULL) {
11183  return MA_INVALID_ARGS;
11184  }
11185 
11186  pthread_mutex_lock(&pSemaphore->lock);
11187  {
11188  /* We need to wait on a condition variable before escaping. We can't return from this function until the semaphore has been signaled. */
11189  while (pSemaphore->value == 0) {
11190  pthread_cond_wait(&pSemaphore->cond, &pSemaphore->lock);
11191  }
11192 
11193  pSemaphore->value -= 1;
11194  }
11195  pthread_mutex_unlock(&pSemaphore->lock);
11196 
11197  return MA_SUCCESS;
11198 }
11199 
11201 {
11202  if (pSemaphore == NULL) {
11203  return MA_INVALID_ARGS;
11204  }
11205 
11206  pthread_mutex_lock(&pSemaphore->lock);
11207  {
11208  pSemaphore->value += 1;
11209  pthread_cond_signal(&pSemaphore->cond);
11210  }
11211  pthread_mutex_unlock(&pSemaphore->lock);
11212 
11213  return MA_SUCCESS;
11214 }
11215 #endif
11216 
11217 typedef struct
11218 {
11219  ma_thread_entry_proc entryProc;
11220  void* pData;
11221  ma_allocation_callbacks allocationCallbacks;
11223 
11225 {
11226  ma_thread_proxy_data* pProxyData = (ma_thread_proxy_data*)pData;
11227  ma_thread_entry_proc entryProc;
11228  void* pEntryProcData;
11229  ma_thread_result result;
11230 
11231  #if defined(MA_ON_THREAD_ENTRY)
11232  MA_ON_THREAD_ENTRY
11233  #endif
11234 
11235  entryProc = pProxyData->entryProc;
11236  pEntryProcData = pProxyData->pData;
11237 
11238  /* Free the proxy data before getting into the real thread entry proc. */
11239  ma_free(pProxyData, &pProxyData->allocationCallbacks);
11240 
11241  result = entryProc(pEntryProcData);
11242 
11243  #if defined(MA_ON_THREAD_EXIT)
11244  MA_ON_THREAD_EXIT
11245  #endif
11246 
11247  return result;
11248 }
11249 
11250 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)
11251 {
11252  ma_result result;
11253  ma_thread_proxy_data* pProxyData;
11254 
11255  if (pThread == NULL || entryProc == NULL) {
11256  return MA_FALSE;
11257  }
11258 
11259  pProxyData = (ma_thread_proxy_data*)ma_malloc(sizeof(*pProxyData), pAllocationCallbacks); /* Will be freed by the proxy entry proc. */
11260  if (pProxyData == NULL) {
11261  return MA_OUT_OF_MEMORY;
11262  }
11263 
11264  pProxyData->entryProc = entryProc;
11265  pProxyData->pData = pData;
11266  ma_allocation_callbacks_init_copy(&pProxyData->allocationCallbacks, pAllocationCallbacks);
11267 
11268 #ifdef MA_WIN32
11269  result = ma_thread_create__win32(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
11270 #endif
11271 #ifdef MA_POSIX
11272  result = ma_thread_create__posix(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
11273 #endif
11274 
11275  if (result != MA_SUCCESS) {
11276  ma_free(pProxyData, pAllocationCallbacks);
11277  return result;
11278  }
11279 
11280  return MA_SUCCESS;
11281 }
11282 
11283 static void ma_thread_wait(ma_thread* pThread)
11284 {
11285  if (pThread == NULL) {
11286  return;
11287  }
11288 
11289 #ifdef MA_WIN32
11290  ma_thread_wait__win32(pThread);
11291 #endif
11292 #ifdef MA_POSIX
11293  ma_thread_wait__posix(pThread);
11294 #endif
11295 }
11296 
11297 
11299 {
11300  if (pMutex == NULL) {
11301  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11302  return MA_INVALID_ARGS;
11303  }
11304 
11305 #ifdef MA_WIN32
11306  return ma_mutex_init__win32(pMutex);
11307 #endif
11308 #ifdef MA_POSIX
11309  return ma_mutex_init__posix(pMutex);
11310 #endif
11311 }
11312 
11313 MA_API void ma_mutex_uninit(ma_mutex* pMutex)
11314 {
11315  if (pMutex == NULL) {
11316  return;
11317  }
11318 
11319 #ifdef MA_WIN32
11320  ma_mutex_uninit__win32(pMutex);
11321 #endif
11322 #ifdef MA_POSIX
11323  ma_mutex_uninit__posix(pMutex);
11324 #endif
11325 }
11326 
11327 MA_API void ma_mutex_lock(ma_mutex* pMutex)
11328 {
11329  if (pMutex == NULL) {
11330  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11331  return;
11332  }
11333 
11334 #ifdef MA_WIN32
11335  ma_mutex_lock__win32(pMutex);
11336 #endif
11337 #ifdef MA_POSIX
11338  ma_mutex_lock__posix(pMutex);
11339 #endif
11340 }
11341 
11342 MA_API void ma_mutex_unlock(ma_mutex* pMutex)
11343 {
11344  if (pMutex == NULL) {
11345  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11346  return;
11347 }
11348 
11349 #ifdef MA_WIN32
11350  ma_mutex_unlock__win32(pMutex);
11351 #endif
11352 #ifdef MA_POSIX
11353  ma_mutex_unlock__posix(pMutex);
11354 #endif
11355 }
11356 
11357 
11359 {
11360  if (pEvent == NULL) {
11361  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11362  return MA_INVALID_ARGS;
11363  }
11364 
11365 #ifdef MA_WIN32
11366  return ma_event_init__win32(pEvent);
11367 #endif
11368 #ifdef MA_POSIX
11369  return ma_event_init__posix(pEvent);
11370 #endif
11371 }
11372 
11373 #if 0
11374 static ma_result ma_event_alloc_and_init(ma_event** ppEvent, ma_allocation_callbacks* pAllocationCallbacks)
11375 {
11376  ma_result result;
11377  ma_event* pEvent;
11378 
11379  if (ppEvent == NULL) {
11380  return MA_INVALID_ARGS;
11381  }
11382 
11383  *ppEvent = NULL;
11384 
11385  pEvent = ma_malloc(sizeof(*pEvent), pAllocationCallbacks/*, MA_ALLOCATION_TYPE_EVENT*/);
11386  if (pEvent == NULL) {
11387  return MA_OUT_OF_MEMORY;
11388  }
11389 
11390  result = ma_event_init(pEvent);
11391  if (result != MA_SUCCESS) {
11392  ma_free(pEvent, pAllocationCallbacks/*, MA_ALLOCATION_TYPE_EVENT*/);
11393  return result;
11394  }
11395 
11396  *ppEvent = pEvent;
11397  return result;
11398 }
11399 #endif
11400 
11401 MA_API void ma_event_uninit(ma_event* pEvent)
11402 {
11403  if (pEvent == NULL) {
11404  return;
11405  }
11406 
11407 #ifdef MA_WIN32
11408  ma_event_uninit__win32(pEvent);
11409 #endif
11410 #ifdef MA_POSIX
11411  ma_event_uninit__posix(pEvent);
11412 #endif
11413 }
11414 
11415 #if 0
11416 static void ma_event_uninit_and_free(ma_event* pEvent, ma_allocation_callbacks* pAllocationCallbacks)
11417 {
11418  if (pEvent == NULL) {
11419  return;
11420  }
11421 
11422  ma_event_uninit(pEvent);
11423  ma_free(pEvent, pAllocationCallbacks/*, MA_ALLOCATION_TYPE_EVENT*/);
11424 }
11425 #endif
11426 
11428 {
11429  if (pEvent == NULL) {
11430  MA_ASSERT(MA_FALSE); /* Fire an assert to the caller is aware of this bug. */
11431  return MA_INVALID_ARGS;
11432  }
11433 
11434 #ifdef MA_WIN32
11435  return ma_event_wait__win32(pEvent);
11436 #endif
11437 #ifdef MA_POSIX
11438  return ma_event_wait__posix(pEvent);
11439 #endif
11440 }
11441 
11443 {
11444  if (pEvent == NULL) {
11445  MA_ASSERT(MA_FALSE); /* Fire an assert to the caller is aware of this bug. */
11446  return MA_INVALID_ARGS;
11447  }
11448 
11449 #ifdef MA_WIN32
11450  return ma_event_signal__win32(pEvent);
11451 #endif
11452 #ifdef MA_POSIX
11453  return ma_event_signal__posix(pEvent);
11454 #endif
11455 }
11456 
11457 
11458 MA_API ma_result ma_semaphore_init(int initialValue, ma_semaphore* pSemaphore)
11459 {
11460  if (pSemaphore == NULL) {
11461  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11462  return MA_INVALID_ARGS;
11463  }
11464 
11465 #ifdef MA_WIN32
11466  return ma_semaphore_init__win32(initialValue, pSemaphore);
11467 #endif
11468 #ifdef MA_POSIX
11469  return ma_semaphore_init__posix(initialValue, pSemaphore);
11470 #endif
11471 }
11472 
11473 MA_API void ma_semaphore_uninit(ma_semaphore* pSemaphore)
11474 {
11475  if (pSemaphore == NULL) {
11476  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11477  return;
11478  }
11479 
11480 #ifdef MA_WIN32
11481  ma_semaphore_uninit__win32(pSemaphore);
11482 #endif
11483 #ifdef MA_POSIX
11484  ma_semaphore_uninit__posix(pSemaphore);
11485 #endif
11486 }
11487 
11489 {
11490  if (pSemaphore == NULL) {
11491  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11492  return MA_INVALID_ARGS;
11493  }
11494 
11495 #ifdef MA_WIN32
11496  return ma_semaphore_wait__win32(pSemaphore);
11497 #endif
11498 #ifdef MA_POSIX
11499  return ma_semaphore_wait__posix(pSemaphore);
11500 #endif
11501 }
11502 
11504 {
11505  if (pSemaphore == NULL) {
11506  MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
11507  return MA_INVALID_ARGS;
11508  }
11509 
11510 #ifdef MA_WIN32
11511  return ma_semaphore_release__win32(pSemaphore);
11512 #endif
11513 #ifdef MA_POSIX
11514  return ma_semaphore_release__posix(pSemaphore);
11515 #endif
11516 }
11517 #else
11518 /* 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. */
11519 #ifndef MA_NO_DEVICE_IO
11520 #error "MA_NO_THREADING cannot be used without MA_NO_DEVICE_IO";
11521 #endif
11522 #endif /* MA_NO_THREADING */
11523 
11524 
11525 
11526 /************************************************************************************************************************************************************
11527 *************************************************************************************************************************************************************
11528 
11529 DEVICE I/O
11530 ==========
11531 
11532 *************************************************************************************************************************************************************
11533 ************************************************************************************************************************************************************/
11534 #ifndef MA_NO_DEVICE_IO
11535 #ifdef MA_WIN32
11536  #include <objbase.h>
11537  #include <mmreg.h>
11538  #include <mmsystem.h>
11539 #endif
11540 
11541 #if defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
11542  #include <mach/mach_time.h> /* For mach_absolute_time() */
11543 #endif
11544 
11545 #ifdef MA_POSIX
11546  #include <sys/types.h>
11547  #include <unistd.h>
11548  #include <dlfcn.h>
11549 #endif
11550 
11551 /*
11552 Unfortunately using runtime linking for pthreads causes problems. This has occurred for me when testing on FreeBSD. When
11553 using runtime linking, deadlocks can occur (for me it happens when loading data from fread()). It turns out that doing
11554 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
11555 disable runtime linking by default. To enable runtime linking, #define this before the implementation of this file. I am
11556 not officially supporting this, but I'm leaving it here in case it's useful for somebody, somewhere.
11557 */
11558 /*#define MA_USE_RUNTIME_LINKING_FOR_PTHREAD*/
11559 
11560 /* Disable run-time linking on certain backends. */
11561 #ifndef MA_NO_RUNTIME_LINKING
11562  #if defined(MA_EMSCRIPTEN)
11563  #define MA_NO_RUNTIME_LINKING
11564  #endif
11565 #endif
11566 
11567 
11568 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)
11569 {
11570  if (pDeviceInfo == NULL) {
11571  return;
11572  }
11573 
11574  if (pDeviceInfo->nativeDataFormatCount < ma_countof(pDeviceInfo->nativeDataFormats)) {
11575  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
11576  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
11577  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
11578  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = flags;
11579  pDeviceInfo->nativeDataFormatCount += 1;
11580  }
11581 }
11582 
11583 
11584 MA_API const char* ma_get_backend_name(ma_backend backend)
11585 {
11586  switch (backend)
11587  {
11588  case ma_backend_wasapi: return "WASAPI";
11589  case ma_backend_dsound: return "DirectSound";
11590  case ma_backend_winmm: return "WinMM";
11591  case ma_backend_coreaudio: return "Core Audio";
11592  case ma_backend_sndio: return "sndio";
11593  case ma_backend_audio4: return "audio(4)";
11594  case ma_backend_oss: return "OSS";
11595  case ma_backend_pulseaudio: return "PulseAudio";
11596  case ma_backend_alsa: return "ALSA";
11597  case ma_backend_jack: return "JACK";
11598  case ma_backend_aaudio: return "AAudio";
11599  case ma_backend_opensl: return "OpenSL|ES";
11600  case ma_backend_webaudio: return "Web Audio";
11601  case ma_backend_custom: return "Custom";
11602  case ma_backend_null: return "Null";
11603  default: return "Unknown";
11604  }
11605 }
11606 
11608 {
11609  /*
11610  This looks a little bit gross, but we want all backends to be included in the switch to avoid warnings on some compilers
11611  about some enums not being handled by the switch statement.
11612  */
11613  switch (backend)
11614  {
11615  case ma_backend_wasapi:
11616  #if defined(MA_HAS_WASAPI)
11617  return MA_TRUE;
11618  #else
11619  return MA_FALSE;
11620  #endif
11621  case ma_backend_dsound:
11622  #if defined(MA_HAS_DSOUND)
11623  return MA_TRUE;
11624  #else
11625  return MA_FALSE;
11626  #endif
11627  case ma_backend_winmm:
11628  #if defined(MA_HAS_WINMM)
11629  return MA_TRUE;
11630  #else
11631  return MA_FALSE;
11632  #endif
11633  case ma_backend_coreaudio:
11634  #if defined(MA_HAS_COREAUDIO)
11635  return MA_TRUE;
11636  #else
11637  return MA_FALSE;
11638  #endif
11639  case ma_backend_sndio:
11640  #if defined(MA_HAS_SNDIO)
11641  return MA_TRUE;
11642  #else
11643  return MA_FALSE;
11644  #endif
11645  case ma_backend_audio4:
11646  #if defined(MA_HAS_AUDIO4)
11647  return MA_TRUE;
11648  #else
11649  return MA_FALSE;
11650  #endif
11651  case ma_backend_oss:
11652  #if defined(MA_HAS_OSS)
11653  return MA_TRUE;
11654  #else
11655  return MA_FALSE;
11656  #endif
11657  case ma_backend_pulseaudio:
11658  #if defined(MA_HAS_PULSEAUDIO)
11659  return MA_TRUE;
11660  #else
11661  return MA_FALSE;
11662  #endif
11663  case ma_backend_alsa:
11664  #if defined(MA_HAS_ALSA)
11665  return MA_TRUE;
11666  #else
11667  return MA_FALSE;
11668  #endif
11669  case ma_backend_jack:
11670  #if defined(MA_HAS_JACK)
11671  return MA_TRUE;
11672  #else
11673  return MA_FALSE;
11674  #endif
11675  case ma_backend_aaudio:
11676  #if defined(MA_HAS_AAUDIO)
11677  return MA_TRUE;
11678  #else
11679  return MA_FALSE;
11680  #endif
11681  case ma_backend_opensl:
11682  #if defined(MA_HAS_OPENSL)
11683  return MA_TRUE;
11684  #else
11685  return MA_FALSE;
11686  #endif
11687  case ma_backend_webaudio:
11688  #if defined(MA_HAS_WEBAUDIO)
11689  return MA_TRUE;
11690  #else
11691  return MA_FALSE;
11692  #endif
11693  case ma_backend_custom:
11694  #if defined(MA_HAS_CUSTOM)
11695  return MA_TRUE;
11696  #else
11697  return MA_FALSE;
11698  #endif
11699  case ma_backend_null:
11700  #if defined(MA_HAS_NULL)
11701  return MA_TRUE;
11702  #else
11703  return MA_FALSE;
11704  #endif
11705 
11706  default: return MA_FALSE;
11707  }
11708 }
11709 
11710 MA_API ma_result ma_get_enabled_backends(ma_backend* pBackends, size_t backendCap, size_t* pBackendCount)
11711 {
11712  size_t backendCount;
11713  size_t iBackend;
11714  ma_result result = MA_SUCCESS;
11715 
11716  if (pBackendCount == NULL) {
11717  return MA_INVALID_ARGS;
11718  }
11719 
11720  backendCount = 0;
11721 
11722  for (iBackend = 0; iBackend <= ma_backend_null; iBackend += 1) {
11723  ma_backend backend = (ma_backend)iBackend;
11724 
11725  if (ma_is_backend_enabled(backend)) {
11726  /* The backend is enabled. Try adding it to the list. If there's no room, MA_NO_SPACE needs to be returned. */
11727  if (backendCount == backendCap) {
11728  result = MA_NO_SPACE;
11729  break;
11730  } else {
11731  pBackends[backendCount] = backend;
11732  backendCount += 1;
11733  }
11734  }
11735  }
11736 
11737  if (pBackendCount != NULL) {
11738  *pBackendCount = backendCount;
11739  }
11740 
11741  return result;
11742 }
11743 
11745 {
11746  switch (backend)
11747  {
11748  case ma_backend_wasapi: return MA_TRUE;
11749  case ma_backend_dsound: return MA_FALSE;
11750  case ma_backend_winmm: return MA_FALSE;
11751  case ma_backend_coreaudio: return MA_FALSE;
11752  case ma_backend_sndio: return MA_FALSE;
11753  case ma_backend_audio4: return MA_FALSE;
11754  case ma_backend_oss: return MA_FALSE;
11755  case ma_backend_pulseaudio: return MA_FALSE;
11756  case ma_backend_alsa: return MA_FALSE;
11757  case ma_backend_jack: return MA_FALSE;
11758  case ma_backend_aaudio: return MA_FALSE;
11759  case ma_backend_opensl: return MA_FALSE;
11760  case ma_backend_webaudio: return MA_FALSE;
11761  case ma_backend_custom: return MA_FALSE; /* <-- Will depend on the implementation of the backend. */
11762  case ma_backend_null: return MA_FALSE;
11763  default: return MA_FALSE;
11764  }
11765 }
11766 
11767 
11768 
11769 #ifdef MA_WIN32
11770 /* WASAPI error codes. */
11771 #define MA_AUDCLNT_E_NOT_INITIALIZED ((HRESULT)0x88890001)
11772 #define MA_AUDCLNT_E_ALREADY_INITIALIZED ((HRESULT)0x88890002)
11773 #define MA_AUDCLNT_E_WRONG_ENDPOINT_TYPE ((HRESULT)0x88890003)
11774 #define MA_AUDCLNT_E_DEVICE_INVALIDATED ((HRESULT)0x88890004)
11775 #define MA_AUDCLNT_E_NOT_STOPPED ((HRESULT)0x88890005)
11776 #define MA_AUDCLNT_E_BUFFER_TOO_LARGE ((HRESULT)0x88890006)
11777 #define MA_AUDCLNT_E_OUT_OF_ORDER ((HRESULT)0x88890007)
11778 #define MA_AUDCLNT_E_UNSUPPORTED_FORMAT ((HRESULT)0x88890008)
11779 #define MA_AUDCLNT_E_INVALID_SIZE ((HRESULT)0x88890009)
11780 #define MA_AUDCLNT_E_DEVICE_IN_USE ((HRESULT)0x8889000A)
11781 #define MA_AUDCLNT_E_BUFFER_OPERATION_PENDING ((HRESULT)0x8889000B)
11782 #define MA_AUDCLNT_E_THREAD_NOT_REGISTERED ((HRESULT)0x8889000C)
11783 #define MA_AUDCLNT_E_NO_SINGLE_PROCESS ((HRESULT)0x8889000D)
11784 #define MA_AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED ((HRESULT)0x8889000E)
11785 #define MA_AUDCLNT_E_ENDPOINT_CREATE_FAILED ((HRESULT)0x8889000F)
11786 #define MA_AUDCLNT_E_SERVICE_NOT_RUNNING ((HRESULT)0x88890010)
11787 #define MA_AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ((HRESULT)0x88890011)
11788 #define MA_AUDCLNT_E_EXCLUSIVE_MODE_ONLY ((HRESULT)0x88890012)
11789 #define MA_AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL ((HRESULT)0x88890013)
11790 #define MA_AUDCLNT_E_EVENTHANDLE_NOT_SET ((HRESULT)0x88890014)
11791 #define MA_AUDCLNT_E_INCORRECT_BUFFER_SIZE ((HRESULT)0x88890015)
11792 #define MA_AUDCLNT_E_BUFFER_SIZE_ERROR ((HRESULT)0x88890016)
11793 #define MA_AUDCLNT_E_CPUUSAGE_EXCEEDED ((HRESULT)0x88890017)
11794 #define MA_AUDCLNT_E_BUFFER_ERROR ((HRESULT)0x88890018)
11795 #define MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED ((HRESULT)0x88890019)
11796 #define MA_AUDCLNT_E_INVALID_DEVICE_PERIOD ((HRESULT)0x88890020)
11797 #define MA_AUDCLNT_E_INVALID_STREAM_FLAG ((HRESULT)0x88890021)
11798 #define MA_AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE ((HRESULT)0x88890022)
11799 #define MA_AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES ((HRESULT)0x88890023)
11800 #define MA_AUDCLNT_E_OFFLOAD_MODE_ONLY ((HRESULT)0x88890024)
11801 #define MA_AUDCLNT_E_NONOFFLOAD_MODE_ONLY ((HRESULT)0x88890025)
11802 #define MA_AUDCLNT_E_RESOURCES_INVALIDATED ((HRESULT)0x88890026)
11803 #define MA_AUDCLNT_E_RAW_MODE_UNSUPPORTED ((HRESULT)0x88890027)
11804 #define MA_AUDCLNT_E_ENGINE_PERIODICITY_LOCKED ((HRESULT)0x88890028)
11805 #define MA_AUDCLNT_E_ENGINE_FORMAT_LOCKED ((HRESULT)0x88890029)
11806 #define MA_AUDCLNT_E_HEADTRACKING_ENABLED ((HRESULT)0x88890030)
11807 #define MA_AUDCLNT_E_HEADTRACKING_UNSUPPORTED ((HRESULT)0x88890040)
11808 #define MA_AUDCLNT_S_BUFFER_EMPTY ((HRESULT)0x08890001)
11809 #define MA_AUDCLNT_S_THREAD_ALREADY_REGISTERED ((HRESULT)0x08890002)
11810 #define MA_AUDCLNT_S_POSITION_STALLED ((HRESULT)0x08890003)
11811 
11812 #define MA_DS_OK ((HRESULT)0)
11813 #define MA_DS_NO_VIRTUALIZATION ((HRESULT)0x0878000A)
11814 #define MA_DSERR_ALLOCATED ((HRESULT)0x8878000A)
11815 #define MA_DSERR_CONTROLUNAVAIL ((HRESULT)0x8878001E)
11816 #define MA_DSERR_INVALIDPARAM ((HRESULT)0x80070057) /*E_INVALIDARG*/
11817 #define MA_DSERR_INVALIDCALL ((HRESULT)0x88780032)
11818 #define MA_DSERR_GENERIC ((HRESULT)0x80004005) /*E_FAIL*/
11819 #define MA_DSERR_PRIOLEVELNEEDED ((HRESULT)0x88780046)
11820 #define MA_DSERR_OUTOFMEMORY ((HRESULT)0x8007000E) /*E_OUTOFMEMORY*/
11821 #define MA_DSERR_BADFORMAT ((HRESULT)0x88780064)
11822 #define MA_DSERR_UNSUPPORTED ((HRESULT)0x80004001) /*E_NOTIMPL*/
11823 #define MA_DSERR_NODRIVER ((HRESULT)0x88780078)
11824 #define MA_DSERR_ALREADYINITIALIZED ((HRESULT)0x88780082)
11825 #define MA_DSERR_NOAGGREGATION ((HRESULT)0x80040110) /*CLASS_E_NOAGGREGATION*/
11826 #define MA_DSERR_BUFFERLOST ((HRESULT)0x88780096)
11827 #define MA_DSERR_OTHERAPPHASPRIO ((HRESULT)0x887800A0)
11828 #define MA_DSERR_UNINITIALIZED ((HRESULT)0x887800AA)
11829 #define MA_DSERR_NOINTERFACE ((HRESULT)0x80004002) /*E_NOINTERFACE*/
11830 #define MA_DSERR_ACCESSDENIED ((HRESULT)0x80070005) /*E_ACCESSDENIED*/
11831 #define MA_DSERR_BUFFERTOOSMALL ((HRESULT)0x887800B4)
11832 #define MA_DSERR_DS8_REQUIRED ((HRESULT)0x887800BE)
11833 #define MA_DSERR_SENDLOOP ((HRESULT)0x887800C8)
11834 #define MA_DSERR_BADSENDBUFFERGUID ((HRESULT)0x887800D2)
11835 #define MA_DSERR_OBJECTNOTFOUND ((HRESULT)0x88781161)
11836 #define MA_DSERR_FXUNAVAILABLE ((HRESULT)0x887800DC)
11837 
11838 static ma_result ma_result_from_HRESULT(HRESULT hr)
11839 {
11840  switch (hr)
11841  {
11842  case NOERROR: return MA_SUCCESS;
11843  /*case S_OK: return MA_SUCCESS;*/
11844 
11845  case E_POINTER: return MA_INVALID_ARGS;
11846  case E_UNEXPECTED: return MA_ERROR;
11847  case E_NOTIMPL: return MA_NOT_IMPLEMENTED;
11848  case E_OUTOFMEMORY: return MA_OUT_OF_MEMORY;
11849  case E_INVALIDARG: return MA_INVALID_ARGS;
11850  case E_NOINTERFACE: return MA_API_NOT_FOUND;
11851  case E_HANDLE: return MA_INVALID_ARGS;
11852  case E_ABORT: return MA_ERROR;
11853  case E_FAIL: return MA_ERROR;
11854  case E_ACCESSDENIED: return MA_ACCESS_DENIED;
11855 
11856  /* WASAPI */
11857  case MA_AUDCLNT_E_NOT_INITIALIZED: return MA_DEVICE_NOT_INITIALIZED;
11858  case MA_AUDCLNT_E_ALREADY_INITIALIZED: return MA_DEVICE_ALREADY_INITIALIZED;
11859  case MA_AUDCLNT_E_WRONG_ENDPOINT_TYPE: return MA_INVALID_ARGS;
11860  case MA_AUDCLNT_E_DEVICE_INVALIDATED: return MA_UNAVAILABLE;
11861  case MA_AUDCLNT_E_NOT_STOPPED: return MA_DEVICE_NOT_STOPPED;
11862  case MA_AUDCLNT_E_BUFFER_TOO_LARGE: return MA_TOO_BIG;
11863  case MA_AUDCLNT_E_OUT_OF_ORDER: return MA_INVALID_OPERATION;
11864  case MA_AUDCLNT_E_UNSUPPORTED_FORMAT: return MA_FORMAT_NOT_SUPPORTED;
11865  case MA_AUDCLNT_E_INVALID_SIZE: return MA_INVALID_ARGS;
11866  case MA_AUDCLNT_E_DEVICE_IN_USE: return MA_BUSY;
11867  case MA_AUDCLNT_E_BUFFER_OPERATION_PENDING: return MA_INVALID_OPERATION;
11868  case MA_AUDCLNT_E_THREAD_NOT_REGISTERED: return MA_DOES_NOT_EXIST;
11869  case MA_AUDCLNT_E_NO_SINGLE_PROCESS: return MA_INVALID_OPERATION;
11870  case MA_AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: return MA_SHARE_MODE_NOT_SUPPORTED;
11871  case MA_AUDCLNT_E_ENDPOINT_CREATE_FAILED: return MA_FAILED_TO_OPEN_BACKEND_DEVICE;
11872  case MA_AUDCLNT_E_SERVICE_NOT_RUNNING: return MA_NOT_CONNECTED;
11873  case MA_AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: return MA_INVALID_ARGS;
11874  case MA_AUDCLNT_E_EXCLUSIVE_MODE_ONLY: return MA_SHARE_MODE_NOT_SUPPORTED;
11875  case MA_AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: return MA_INVALID_ARGS;
11876  case MA_AUDCLNT_E_EVENTHANDLE_NOT_SET: return MA_INVALID_ARGS;
11877  case MA_AUDCLNT_E_INCORRECT_BUFFER_SIZE: return MA_INVALID_ARGS;
11878  case MA_AUDCLNT_E_BUFFER_SIZE_ERROR: return MA_INVALID_ARGS;
11879  case MA_AUDCLNT_E_CPUUSAGE_EXCEEDED: return MA_ERROR;
11880  case MA_AUDCLNT_E_BUFFER_ERROR: return MA_ERROR;
11881  case MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED: return MA_INVALID_ARGS;
11882  case MA_AUDCLNT_E_INVALID_DEVICE_PERIOD: return MA_INVALID_ARGS;
11883  case MA_AUDCLNT_E_INVALID_STREAM_FLAG: return MA_INVALID_ARGS;
11884  case MA_AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE: return MA_INVALID_OPERATION;
11885  case MA_AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES: return MA_OUT_OF_MEMORY;
11886  case MA_AUDCLNT_E_OFFLOAD_MODE_ONLY: return MA_INVALID_OPERATION;
11887  case MA_AUDCLNT_E_NONOFFLOAD_MODE_ONLY: return MA_INVALID_OPERATION;
11888  case MA_AUDCLNT_E_RESOURCES_INVALIDATED: return MA_INVALID_DATA;
11889  case MA_AUDCLNT_E_RAW_MODE_UNSUPPORTED: return MA_INVALID_OPERATION;
11890  case MA_AUDCLNT_E_ENGINE_PERIODICITY_LOCKED: return MA_INVALID_OPERATION;
11891  case MA_AUDCLNT_E_ENGINE_FORMAT_LOCKED: return MA_INVALID_OPERATION;
11892  case MA_AUDCLNT_E_HEADTRACKING_ENABLED: return MA_INVALID_OPERATION;
11893  case MA_AUDCLNT_E_HEADTRACKING_UNSUPPORTED: return MA_INVALID_OPERATION;
11894  case MA_AUDCLNT_S_BUFFER_EMPTY: return MA_NO_SPACE;
11895  case MA_AUDCLNT_S_THREAD_ALREADY_REGISTERED: return MA_ALREADY_EXISTS;
11896  case MA_AUDCLNT_S_POSITION_STALLED: return MA_ERROR;
11897 
11898  /* DirectSound */
11899  /*case MA_DS_OK: return MA_SUCCESS;*/ /* S_OK */
11900  case MA_DS_NO_VIRTUALIZATION: return MA_SUCCESS;
11901  case MA_DSERR_ALLOCATED: return MA_ALREADY_IN_USE;
11902  case MA_DSERR_CONTROLUNAVAIL: return MA_INVALID_OPERATION;
11903  /*case MA_DSERR_INVALIDPARAM: return MA_INVALID_ARGS;*/ /* E_INVALIDARG */
11904  case MA_DSERR_INVALIDCALL: return MA_INVALID_OPERATION;
11905  /*case MA_DSERR_GENERIC: return MA_ERROR;*/ /* E_FAIL */
11906  case MA_DSERR_PRIOLEVELNEEDED: return MA_INVALID_OPERATION;
11907  /*case MA_DSERR_OUTOFMEMORY: return MA_OUT_OF_MEMORY;*/ /* E_OUTOFMEMORY */
11908  case MA_DSERR_BADFORMAT: return MA_FORMAT_NOT_SUPPORTED;
11909  /*case MA_DSERR_UNSUPPORTED: return MA_NOT_IMPLEMENTED;*/ /* E_NOTIMPL */
11910  case MA_DSERR_NODRIVER: return MA_FAILED_TO_INIT_BACKEND;
11911  case MA_DSERR_ALREADYINITIALIZED: return MA_DEVICE_ALREADY_INITIALIZED;
11912  case MA_DSERR_NOAGGREGATION: return MA_ERROR;
11913  case MA_DSERR_BUFFERLOST: return MA_UNAVAILABLE;
11914  case MA_DSERR_OTHERAPPHASPRIO: return MA_ACCESS_DENIED;
11915  case MA_DSERR_UNINITIALIZED: return MA_DEVICE_NOT_INITIALIZED;
11916  /*case MA_DSERR_NOINTERFACE: return MA_API_NOT_FOUND;*/ /* E_NOINTERFACE */
11917  /*case MA_DSERR_ACCESSDENIED: return MA_ACCESS_DENIED;*/ /* E_ACCESSDENIED */
11918  case MA_DSERR_BUFFERTOOSMALL: return MA_NO_SPACE;
11919  case MA_DSERR_DS8_REQUIRED: return MA_INVALID_OPERATION;
11920  case MA_DSERR_SENDLOOP: return MA_DEADLOCK;
11921  case MA_DSERR_BADSENDBUFFERGUID: return MA_INVALID_ARGS;
11922  case MA_DSERR_OBJECTNOTFOUND: return MA_NO_DEVICE;
11923  case MA_DSERR_FXUNAVAILABLE: return MA_UNAVAILABLE;
11924 
11925  default: return MA_ERROR;
11926  }
11927 }
11928 
11929 typedef HRESULT (WINAPI * MA_PFN_CoInitializeEx)(LPVOID pvReserved, DWORD dwCoInit);
11930 typedef void (WINAPI * MA_PFN_CoUninitialize)(void);
11931 typedef HRESULT (WINAPI * MA_PFN_CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);
11932 typedef void (WINAPI * MA_PFN_CoTaskMemFree)(LPVOID pv);
11933 typedef HRESULT (WINAPI * MA_PFN_PropVariantClear)(PROPVARIANT *pvar);
11934 typedef int (WINAPI * MA_PFN_StringFromGUID2)(const GUID* const rguid, LPOLESTR lpsz, int cchMax);
11935 
11936 typedef HWND (WINAPI * MA_PFN_GetForegroundWindow)(void);
11937 typedef HWND (WINAPI * MA_PFN_GetDesktopWindow)(void);
11938 
11939 /* Microsoft documents these APIs as returning LSTATUS, but the Win32 API shipping with some compilers do not define it. It's just a LONG. */
11940 typedef LONG (WINAPI * MA_PFN_RegOpenKeyExA)(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
11941 typedef LONG (WINAPI * MA_PFN_RegCloseKey)(HKEY hKey);
11942 typedef LONG (WINAPI * MA_PFN_RegQueryValueExA)(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
11943 #endif
11944 
11945 
11946 #define MA_DEFAULT_PLAYBACK_DEVICE_NAME "Default Playback Device"
11947 #define MA_DEFAULT_CAPTURE_DEVICE_NAME "Default Capture Device"
11948 
11949 
11950 /* Posts a log message. */
11951 static void ma_post_log_message(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message)
11952 {
11953  if (pContext == NULL) {
11954  if (pDevice != NULL) {
11955  pContext = pDevice->pContext;
11956  }
11957  }
11958 
11959  if (pContext == NULL) {
11960  return;
11961  }
11962 
11963  ma_log_post(ma_context_get_log(pContext), logLevel, message); /* <-- This will deal with MA_DEBUG_OUTPUT. */
11964 
11965  /* Legacy. */
11966 #if defined(MA_LOG_LEVEL)
11967  if (logLevel <= MA_LOG_LEVEL) {
11968  ma_log_proc onLog;
11969 
11970  onLog = pContext->logCallback;
11971  if (onLog) {
11972  onLog(pContext, pDevice, logLevel, message);
11973  }
11974  }
11975 #endif
11976 }
11977 
11978 /* Posts an log message. Throw a breakpoint in here if you're needing to debug. The return value is always "resultCode". */
11979 static ma_result ma_context_post_error(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message, ma_result resultCode)
11980 {
11981  ma_post_log_message(pContext, pDevice, logLevel, message);
11982  return resultCode;
11983 }
11984 
11985 static ma_result ma_post_error(ma_device* pDevice, ma_uint32 logLevel, const char* message, ma_result resultCode)
11986 {
11987  return ma_context_post_error(ma_device_get_context(pDevice), pDevice, logLevel, message, resultCode);
11988 }
11989 
11990 
11991 
11992 
11993 /*******************************************************************************
11994 
11995 Timing
11996 
11997 *******************************************************************************/
11998 #ifdef MA_WIN32
11999  static LARGE_INTEGER g_ma_TimerFrequency; /* <-- Initialized to zero since it's static. */
12000  static void ma_timer_init(ma_timer* pTimer)
12001  {
12002  LARGE_INTEGER counter;
12003 
12004  if (g_ma_TimerFrequency.QuadPart == 0) {
12005  QueryPerformanceFrequency(&g_ma_TimerFrequency);
12006  }
12007 
12008  QueryPerformanceCounter(&counter);
12009  pTimer->counter = counter.QuadPart;
12010  }
12011 
12012  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
12013  {
12014  LARGE_INTEGER counter;
12015  if (!QueryPerformanceCounter(&counter)) {
12016  return 0;
12017  }
12018 
12019  return (double)(counter.QuadPart - pTimer->counter) / g_ma_TimerFrequency.QuadPart;
12020  }
12021 #elif defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
12022  static ma_uint64 g_ma_TimerFrequency = 0;
12023  static void ma_timer_init(ma_timer* pTimer)
12024  {
12025  mach_timebase_info_data_t baseTime;
12026  mach_timebase_info(&baseTime);
12027  g_ma_TimerFrequency = (baseTime.denom * 1e9) / baseTime.numer;
12028 
12029  pTimer->counter = mach_absolute_time();
12030  }
12031 
12032  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
12033  {
12034  ma_uint64 newTimeCounter = mach_absolute_time();
12035  ma_uint64 oldTimeCounter = pTimer->counter;
12036 
12037  return (newTimeCounter - oldTimeCounter) / g_ma_TimerFrequency;
12038  }
12039 #elif defined(MA_EMSCRIPTEN)
12040  static MA_INLINE void ma_timer_init(ma_timer* pTimer)
12041  {
12042  pTimer->counterD = emscripten_get_now();
12043  }
12044 
12045  static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer)
12046  {
12047  return (emscripten_get_now() - pTimer->counterD) / 1000; /* Emscripten is in milliseconds. */
12048  }
12049 #else
12050  #if _POSIX_C_SOURCE >= 199309L
12051  #if defined(CLOCK_MONOTONIC)
12052  #define MA_CLOCK_ID CLOCK_MONOTONIC
12053  #else
12054  #define MA_CLOCK_ID CLOCK_REALTIME
12055  #endif
12056 
12057  static void ma_timer_init(ma_timer* pTimer)
12058  {
12059  struct timespec newTime;
12060  clock_gettime(MA_CLOCK_ID, &newTime);
12061 
12062  pTimer->counter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
12063  }
12064 
12065  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
12066  {
12067  ma_uint64 newTimeCounter;
12068  ma_uint64 oldTimeCounter;
12069 
12070  struct timespec newTime;
12071  clock_gettime(MA_CLOCK_ID, &newTime);
12072 
12073  newTimeCounter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
12074  oldTimeCounter = pTimer->counter;
12075 
12076  return (newTimeCounter - oldTimeCounter) / 1000000000.0;
12077  }
12078  #else
12079  static void ma_timer_init(ma_timer* pTimer)
12080  {
12081  struct timeval newTime;
12082  gettimeofday(&newTime, NULL);
12083 
12084  pTimer->counter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
12085  }
12086 
12087  static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
12088  {
12089  ma_uint64 newTimeCounter;
12090  ma_uint64 oldTimeCounter;
12091 
12092  struct timeval newTime;
12093  gettimeofday(&newTime, NULL);
12094 
12095  newTimeCounter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
12096  oldTimeCounter = pTimer->counter;
12097 
12098  return (newTimeCounter - oldTimeCounter) / 1000000.0;
12099  }
12100  #endif
12101 #endif
12102 
12103 
12104 /*******************************************************************************
12105 
12106 Dynamic Linking
12107 
12108 *******************************************************************************/
12109 MA_API ma_handle ma_dlopen(ma_context* pContext, const char* filename)
12110 {
12111  ma_handle handle;
12112 
12113  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename);
12114 
12115 #ifdef _WIN32
12116 #ifdef MA_WIN32_DESKTOP
12117  handle = (ma_handle)LoadLibraryA(filename);
12118 #else
12119  /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
12120  WCHAR filenameW[4096];
12121  if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) {
12122  handle = NULL;
12123  } else {
12124  handle = (ma_handle)LoadPackagedLibrary(filenameW, 0);
12125  }
12126 #endif
12127 #else
12128  handle = (ma_handle)dlopen(filename, RTLD_NOW);
12129 #endif
12130 
12131  /*
12132  I'm not considering failure to load a library an error nor a warning because seamlessly falling through to a lower-priority
12133  backend is a deliberate design choice. Instead I'm logging it as an informational message.
12134  */
12135  if (handle == NULL) {
12136  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_INFO, "Failed to load library: %s\n", filename);
12137  }
12138 
12139  (void)pContext; /* It's possible for pContext to be unused. */
12140  return handle;
12141 }
12142 
12143 MA_API void ma_dlclose(ma_context* pContext, ma_handle handle)
12144 {
12145 #ifdef _WIN32
12146  FreeLibrary((HMODULE)handle);
12147 #else
12148  dlclose((void*)handle);
12149 #endif
12150 
12151  (void)pContext;
12152 }
12153 
12154 MA_API ma_proc ma_dlsym(ma_context* pContext, ma_handle handle, const char* symbol)
12155 {
12156  ma_proc proc;
12157 
12158  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Loading symbol: %s\n", symbol);
12159 
12160 #ifdef _WIN32
12161  proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol);
12162 #else
12163 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
12164  #pragma GCC diagnostic push
12165  #pragma GCC diagnostic ignored "-Wpedantic"
12166 #endif
12167  proc = (ma_proc)dlsym((void*)handle, symbol);
12168 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
12169  #pragma GCC diagnostic pop
12170 #endif
12171 #endif
12172 
12173  if (proc == NULL) {
12174  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Failed to load symbol: %s\n", symbol);
12175  }
12176 
12177  (void)pContext; /* It's possible for pContext to be unused. */
12178  return proc;
12179 }
12180 
12181 
12182 #if 0
12183 static ma_uint32 ma_get_closest_standard_sample_rate(ma_uint32 sampleRateIn)
12184 {
12185  ma_uint32 closestRate = 0;
12186  ma_uint32 closestDiff = 0xFFFFFFFF;
12187  size_t iStandardRate;
12188 
12189  for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
12190  ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
12191  ma_uint32 diff;
12192 
12193  if (sampleRateIn > standardRate) {
12194  diff = sampleRateIn - standardRate;
12195  } else {
12196  diff = standardRate - sampleRateIn;
12197  }
12198 
12199  if (diff == 0) {
12200  return standardRate; /* The input sample rate is a standard rate. */
12201  }
12202 
12203  if (closestDiff > diff) {
12204  closestDiff = diff;
12205  closestRate = standardRate;
12206  }
12207  }
12208 
12209  return closestRate;
12210 }
12211 #endif
12212 
12213 
12214 static void ma_device__on_data(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
12215 {
12216  float masterVolumeFactor;
12217 
12218  ma_device_get_master_volume(pDevice, &masterVolumeFactor); /* Use ma_device_get_master_volume() to ensure the volume is loaded atomically. */
12219 
12220  if (pDevice->onData) {
12221  if (!pDevice->noPreZeroedOutputBuffer && pFramesOut != NULL) {
12222  ma_silence_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels);
12223  }
12224 
12225  /* 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. */
12226  if (pFramesIn != NULL && masterVolumeFactor < 1) {
12228  ma_uint32 bpfCapture = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
12229  ma_uint32 bpfPlayback = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
12230  ma_uint32 totalFramesProcessed = 0;
12231  while (totalFramesProcessed < frameCount) {
12232  ma_uint32 framesToProcessThisIteration = frameCount - totalFramesProcessed;
12233  if (framesToProcessThisIteration > sizeof(tempFramesIn)/bpfCapture) {
12234  framesToProcessThisIteration = sizeof(tempFramesIn)/bpfCapture;
12235  }
12236 
12237  ma_copy_and_apply_volume_factor_pcm_frames(tempFramesIn, ma_offset_ptr(pFramesIn, totalFramesProcessed*bpfCapture), framesToProcessThisIteration, pDevice->capture.format, pDevice->capture.channels, masterVolumeFactor);
12238 
12239  pDevice->onData(pDevice, ma_offset_ptr(pFramesOut, totalFramesProcessed*bpfPlayback), tempFramesIn, framesToProcessThisIteration);
12240 
12241  totalFramesProcessed += framesToProcessThisIteration;
12242  }
12243  } else {
12244  pDevice->onData(pDevice, pFramesOut, pFramesIn, frameCount);
12245  }
12246 
12247  /* Volume control and clipping for playback devices. */
12248  if (pFramesOut != NULL) {
12249  if (masterVolumeFactor < 1) {
12250  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. */
12251  ma_apply_volume_factor_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels, masterVolumeFactor);
12252  }
12253  }
12254 
12255  if (!pDevice->noClip && pDevice->playback.format == ma_format_f32) {
12256  ma_clip_pcm_frames_f32((float*)pFramesOut, frameCount, pDevice->playback.channels);
12257  }
12258  }
12259  }
12260 }
12261 
12262 
12263 
12264 /* A helper function for reading sample data from the client. */
12265 static void ma_device__read_frames_from_client(ma_device* pDevice, ma_uint32 frameCount, void* pFramesOut)
12266 {
12267  MA_ASSERT(pDevice != NULL);
12268  MA_ASSERT(frameCount > 0);
12269  MA_ASSERT(pFramesOut != NULL);
12270 
12271  if (pDevice->playback.converter.isPassthrough) {
12272  ma_device__on_data(pDevice, pFramesOut, NULL, frameCount);
12273  } else {
12274  ma_result result;
12275  ma_uint64 totalFramesReadOut;
12276  ma_uint64 totalFramesReadIn;
12277  void* pRunningFramesOut;
12278 
12279  totalFramesReadOut = 0;
12280  totalFramesReadIn = 0;
12281  pRunningFramesOut = pFramesOut;
12282 
12283  while (totalFramesReadOut < frameCount) {
12284  ma_uint8 pIntermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In client format. */
12285  ma_uint64 intermediaryBufferCap = sizeof(pIntermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
12286  ma_uint64 framesToReadThisIterationIn;
12287  ma_uint64 framesReadThisIterationIn;
12288  ma_uint64 framesToReadThisIterationOut;
12289  ma_uint64 framesReadThisIterationOut;
12290  ma_uint64 requiredInputFrameCount;
12291 
12292  framesToReadThisIterationOut = (frameCount - totalFramesReadOut);
12293  framesToReadThisIterationIn = framesToReadThisIterationOut;
12294  if (framesToReadThisIterationIn > intermediaryBufferCap) {
12295  framesToReadThisIterationIn = intermediaryBufferCap;
12296  }
12297 
12298  requiredInputFrameCount = ma_data_converter_get_required_input_frame_count(&pDevice->playback.converter, framesToReadThisIterationOut);
12299  if (framesToReadThisIterationIn > requiredInputFrameCount) {
12300  framesToReadThisIterationIn = requiredInputFrameCount;
12301  }
12302 
12303  if (framesToReadThisIterationIn > 0) {
12304  ma_device__on_data(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn);
12305  totalFramesReadIn += framesToReadThisIterationIn;
12306  }
12307 
12308  /*
12309  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
12310  input frames, we still want to try processing frames because there may some output frames generated from cached input data.
12311  */
12312  framesReadThisIterationIn = framesToReadThisIterationIn;
12313  framesReadThisIterationOut = framesToReadThisIterationOut;
12314  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
12315  if (result != MA_SUCCESS) {
12316  break;
12317  }
12318 
12319  totalFramesReadOut += framesReadThisIterationOut;
12320  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
12321 
12322  if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
12323  break; /* We're done. */
12324  }
12325  }
12326  }
12327 }
12328 
12329 /* A helper for sending sample data to the client. */
12330 static void ma_device__send_frames_to_client(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat)
12331 {
12332  MA_ASSERT(pDevice != NULL);
12333  MA_ASSERT(frameCountInDeviceFormat > 0);
12334  MA_ASSERT(pFramesInDeviceFormat != NULL);
12335 
12336  if (pDevice->capture.converter.isPassthrough) {
12337  ma_device__on_data(pDevice, NULL, pFramesInDeviceFormat, frameCountInDeviceFormat);
12338  } else {
12339  ma_result result;
12340  ma_uint8 pFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12341  ma_uint64 framesInClientFormatCap = sizeof(pFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
12342  ma_uint64 totalDeviceFramesProcessed = 0;
12343  ma_uint64 totalClientFramesProcessed = 0;
12344  const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat;
12345 
12346  /* We just keep going until we've exhaused all of our input frames and cannot generate any more output frames. */
12347  for (;;) {
12348  ma_uint64 deviceFramesProcessedThisIteration;
12349  ma_uint64 clientFramesProcessedThisIteration;
12350 
12351  deviceFramesProcessedThisIteration = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
12352  clientFramesProcessedThisIteration = framesInClientFormatCap;
12353 
12354  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningFramesInDeviceFormat, &deviceFramesProcessedThisIteration, pFramesInClientFormat, &clientFramesProcessedThisIteration);
12355  if (result != MA_SUCCESS) {
12356  break;
12357  }
12358 
12359  if (clientFramesProcessedThisIteration > 0) {
12360  ma_device__on_data(pDevice, NULL, pFramesInClientFormat, (ma_uint32)clientFramesProcessedThisIteration); /* Safe cast. */
12361  }
12362 
12363  pRunningFramesInDeviceFormat = ma_offset_ptr(pRunningFramesInDeviceFormat, deviceFramesProcessedThisIteration * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
12364  totalDeviceFramesProcessed += deviceFramesProcessedThisIteration;
12365  totalClientFramesProcessed += clientFramesProcessedThisIteration;
12366 
12367  if (deviceFramesProcessedThisIteration == 0 && clientFramesProcessedThisIteration == 0) {
12368  break; /* We're done. */
12369  }
12370  }
12371  }
12372 }
12373 
12374 static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat, ma_pcm_rb* pRB)
12375 {
12376  ma_result result;
12377  ma_uint32 totalDeviceFramesProcessed = 0;
12378  const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat;
12379 
12380  MA_ASSERT(pDevice != NULL);
12381  MA_ASSERT(frameCountInDeviceFormat > 0);
12382  MA_ASSERT(pFramesInDeviceFormat != NULL);
12383  MA_ASSERT(pRB != NULL);
12384 
12385  /* Write to the ring buffer. The ring buffer is in the client format which means we need to convert. */
12386  for (;;) {
12387  ma_uint32 framesToProcessInDeviceFormat = (frameCountInDeviceFormat - totalDeviceFramesProcessed);
12388  ma_uint32 framesToProcessInClientFormat = MA_DATA_CONVERTER_STACK_BUFFER_SIZE / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
12389  ma_uint64 framesProcessedInDeviceFormat;
12390  ma_uint64 framesProcessedInClientFormat;
12391  void* pFramesInClientFormat;
12392 
12393  result = ma_pcm_rb_acquire_write(pRB, &framesToProcessInClientFormat, &pFramesInClientFormat);
12394  if (result != MA_SUCCESS) {
12395  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "Failed to acquire capture PCM frames from ring buffer.", result);
12396  break;
12397  }
12398 
12399  if (framesToProcessInClientFormat == 0) {
12401  break; /* Overrun. Not enough room in the ring buffer for input frame. Excess frames are dropped. */
12402  }
12403  }
12404 
12405  /* Convert. */
12406  framesProcessedInDeviceFormat = framesToProcessInDeviceFormat;
12407  framesProcessedInClientFormat = framesToProcessInClientFormat;
12408  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningFramesInDeviceFormat, &framesProcessedInDeviceFormat, pFramesInClientFormat, &framesProcessedInClientFormat);
12409  if (result != MA_SUCCESS) {
12410  break;
12411  }
12412 
12413  result = ma_pcm_rb_commit_write(pRB, (ma_uint32)framesProcessedInClientFormat, pFramesInClientFormat); /* Safe cast. */
12414  if (result != MA_SUCCESS) {
12415  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "Failed to commit capture PCM frames to ring buffer.", result);
12416  break;
12417  }
12418 
12419  pRunningFramesInDeviceFormat = ma_offset_ptr(pRunningFramesInDeviceFormat, framesProcessedInDeviceFormat * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
12420  totalDeviceFramesProcessed += (ma_uint32)framesProcessedInDeviceFormat; /* Safe cast. */
12421 
12422  /* We're done when we're unable to process any client nor device frames. */
12423  if (framesProcessedInClientFormat == 0 && framesProcessedInDeviceFormat == 0) {
12424  break; /* Done. */
12425  }
12426  }
12427 
12428  return MA_SUCCESS;
12429 }
12430 
12431 static ma_result ma_device__handle_duplex_callback_playback(ma_device* pDevice, ma_uint32 frameCount, void* pFramesInInternalFormat, ma_pcm_rb* pRB)
12432 {
12433  ma_result result;
12434  ma_uint8 playbackFramesInExternalFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12435  ma_uint8 silentInputFrames[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12436  ma_uint32 totalFramesToReadFromClient;
12437  ma_uint32 totalFramesReadFromClient;
12438  ma_uint32 totalFramesReadOut = 0;
12439 
12440  MA_ASSERT(pDevice != NULL);
12441  MA_ASSERT(frameCount > 0);
12442  MA_ASSERT(pFramesInInternalFormat != NULL);
12443  MA_ASSERT(pRB != NULL);
12444 
12445  /*
12446  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
12447  the whole frameCount frames we just use silence instead for the input data.
12448  */
12449  MA_ZERO_MEMORY(silentInputFrames, sizeof(silentInputFrames));
12450 
12451  /* We need to calculate how many output frames are required to be read from the client to completely fill frameCount internal frames. */
12452  totalFramesToReadFromClient = (ma_uint32)ma_data_converter_get_required_input_frame_count(&pDevice->playback.converter, frameCount);
12453  totalFramesReadFromClient = 0;
12454  while (totalFramesReadFromClient < totalFramesToReadFromClient && ma_device_is_started(pDevice)) {
12455  ma_uint32 framesRemainingFromClient;
12456  ma_uint32 framesToProcessFromClient;
12457  ma_uint32 inputFrameCount;
12458  void* pInputFrames;
12459 
12460  framesRemainingFromClient = (totalFramesToReadFromClient - totalFramesReadFromClient);
12461  framesToProcessFromClient = sizeof(playbackFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
12462  if (framesToProcessFromClient > framesRemainingFromClient) {
12463  framesToProcessFromClient = framesRemainingFromClient;
12464  }
12465 
12466  /* We need to grab captured samples before firing the callback. If there's not enough input samples we just pass silence. */
12467  inputFrameCount = framesToProcessFromClient;
12468  result = ma_pcm_rb_acquire_read(pRB, &inputFrameCount, &pInputFrames);
12469  if (result == MA_SUCCESS) {
12470  if (inputFrameCount > 0) {
12471  /* Use actual input frames. */
12472  ma_device__on_data(pDevice, playbackFramesInExternalFormat, pInputFrames, inputFrameCount);
12473  } else {
12474  if (ma_pcm_rb_pointer_distance(pRB) == 0) {
12475  break; /* Underrun. */
12476  }
12477  }
12478 
12479  /* We're done with the captured samples. */
12480  result = ma_pcm_rb_commit_read(pRB, inputFrameCount, pInputFrames);
12481  if (result != MA_SUCCESS) {
12482  break; /* Don't know what to do here... Just abandon ship. */
12483  }
12484  } else {
12485  /* Use silent input frames. */
12486  inputFrameCount = ma_min(
12487  sizeof(playbackFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels),
12488  sizeof(silentInputFrames) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels)
12489  );
12490 
12491  ma_device__on_data(pDevice, playbackFramesInExternalFormat, silentInputFrames, inputFrameCount);
12492  }
12493 
12494  /* We have samples in external format so now we need to convert to internal format and output to the device. */
12495  {
12496  ma_uint64 framesConvertedIn = inputFrameCount;
12497  ma_uint64 framesConvertedOut = (frameCount - totalFramesReadOut);
12498  ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackFramesInExternalFormat, &framesConvertedIn, pFramesInInternalFormat, &framesConvertedOut);
12499 
12500  totalFramesReadFromClient += (ma_uint32)framesConvertedIn; /* Safe cast. */
12501  totalFramesReadOut += (ma_uint32)framesConvertedOut; /* Safe cast. */
12502  pFramesInInternalFormat = ma_offset_ptr(pFramesInInternalFormat, framesConvertedOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
12503  }
12504  }
12505 
12506  return MA_SUCCESS;
12507 }
12508 
12509 /* A helper for changing the state of the device. */
12510 static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_uint32 newState)
12511 {
12512  c89atomic_exchange_32(&pDevice->state, newState);
12513 }
12514 
12515 
12516 #ifdef MA_WIN32
12517  GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
12518  GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
12519  /*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
12520  /*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
12521 #endif
12522 
12523 
12524 
12525 MA_API ma_uint32 ma_get_format_priority_index(ma_format format) /* Lower = better. */
12526 {
12527  ma_uint32 i;
12528  for (i = 0; i < ma_countof(g_maFormatPriorities); ++i) {
12529  if (g_maFormatPriorities[i] == format) {
12530  return i;
12531  }
12532  }
12533 
12534  /* Getting here means the format could not be found or is equal to ma_format_unknown. */
12535  return (ma_uint32)-1;
12536 }
12537 
12538 static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType);
12539 
12540 
12541 static ma_bool32 ma_device_descriptor_is_valid(const ma_device_descriptor* pDeviceDescriptor)
12542 {
12543  if (pDeviceDescriptor == NULL) {
12544  return MA_FALSE;
12545  }
12546 
12547  if (pDeviceDescriptor->format == ma_format_unknown) {
12548  return MA_FALSE;
12549  }
12550 
12551  if (pDeviceDescriptor->channels < MA_MIN_CHANNELS || pDeviceDescriptor->channels > MA_MAX_CHANNELS) {
12552  return MA_FALSE;
12553  }
12554 
12555  if (pDeviceDescriptor->sampleRate == 0) {
12556  return MA_FALSE;
12557  }
12558 
12559  return MA_TRUE;
12560 }
12561 
12562 
12564 {
12565  ma_result result = MA_SUCCESS;
12566  ma_bool32 exitLoop = MA_FALSE;
12567  ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12568  ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12569  ma_uint32 capturedDeviceDataCapInFrames = 0;
12570  ma_uint32 playbackDeviceDataCapInFrames = 0;
12571 
12572  MA_ASSERT(pDevice != NULL);
12573 
12574  /* Just some quick validation on the device type and the available callbacks. */
12575  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
12576  if (pDevice->pContext->callbacks.onDeviceRead == NULL) {
12577  return MA_NOT_IMPLEMENTED;
12578  }
12579 
12580  capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
12581  }
12582 
12583  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
12584  if (pDevice->pContext->callbacks.onDeviceWrite == NULL) {
12585  return MA_NOT_IMPLEMENTED;
12586  }
12587 
12588  playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
12589  }
12590 
12591  /* NOTE: The device was started outside of this function, in the worker thread. */
12592 
12593  while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
12594  switch (pDevice->type) {
12595  case ma_device_type_duplex:
12596  {
12597  /* The process is: onDeviceRead() -> convert -> callback -> convert -> onDeviceWrite() */
12598  ma_uint32 totalCapturedDeviceFramesProcessed = 0;
12599  ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
12600 
12601  while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
12602  ma_uint32 capturedDeviceFramesRemaining;
12603  ma_uint32 capturedDeviceFramesProcessed;
12604  ma_uint32 capturedDeviceFramesToProcess;
12605  ma_uint32 capturedDeviceFramesToTryProcessing = capturedDevicePeriodSizeInFrames - totalCapturedDeviceFramesProcessed;
12606  if (capturedDeviceFramesToTryProcessing > capturedDeviceDataCapInFrames) {
12607  capturedDeviceFramesToTryProcessing = capturedDeviceDataCapInFrames;
12608  }
12609 
12610  result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, capturedDeviceFramesToTryProcessing, &capturedDeviceFramesToProcess);
12611  if (result != MA_SUCCESS) {
12612  exitLoop = MA_TRUE;
12613  break;
12614  }
12615 
12616  capturedDeviceFramesRemaining = capturedDeviceFramesToProcess;
12617  capturedDeviceFramesProcessed = 0;
12618 
12619  /* At this point we have our captured data in device format and we now need to convert it to client format. */
12620  for (;;) {
12621  ma_uint8 capturedClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12622  ma_uint8 playbackClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
12623  ma_uint32 capturedClientDataCapInFrames = sizeof(capturedClientData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
12624  ma_uint32 playbackClientDataCapInFrames = sizeof(playbackClientData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
12625  ma_uint64 capturedClientFramesToProcessThisIteration = ma_min(capturedClientDataCapInFrames, playbackClientDataCapInFrames);
12626  ma_uint64 capturedDeviceFramesToProcessThisIteration = capturedDeviceFramesRemaining;
12627  ma_uint8* pRunningCapturedDeviceFrames = ma_offset_ptr(capturedDeviceData, capturedDeviceFramesProcessed * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
12628 
12629  /* Convert capture data from device format to client format. */
12630  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningCapturedDeviceFrames, &capturedDeviceFramesToProcessThisIteration, capturedClientData, &capturedClientFramesToProcessThisIteration);
12631  if (result != MA_SUCCESS) {
12632  break;
12633  }
12634 
12635  /*
12636  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
12637  which should never be the case when it's of the size MA_DATA_CONVERTER_STACK_BUFFER_SIZE.
12638  */
12639  if (capturedClientFramesToProcessThisIteration == 0) {
12640  break;
12641  }
12642 
12643  ma_device__on_data(pDevice, playbackClientData, capturedClientData, (ma_uint32)capturedClientFramesToProcessThisIteration); /* Safe cast .*/
12644 
12645  capturedDeviceFramesProcessed += (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
12646  capturedDeviceFramesRemaining -= (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
12647 
12648  /* At this point the playbackClientData buffer should be holding data that needs to be written to the device. */
12649  for (;;) {
12650  ma_uint64 convertedClientFrameCount = capturedClientFramesToProcessThisIteration;
12651  ma_uint64 convertedDeviceFrameCount = playbackDeviceDataCapInFrames;
12652  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackClientData, &convertedClientFrameCount, playbackDeviceData, &convertedDeviceFrameCount);
12653  if (result != MA_SUCCESS) {
12654  break;
12655  }
12656 
12657  result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, (ma_uint32)convertedDeviceFrameCount, NULL); /* Safe cast. */
12658  if (result != MA_SUCCESS) {
12659  exitLoop = MA_TRUE;
12660  break;
12661  }
12662 
12663  capturedClientFramesToProcessThisIteration -= (ma_uint32)convertedClientFrameCount; /* Safe cast. */
12664  if (capturedClientFramesToProcessThisIteration == 0) {
12665  break;
12666  }
12667  }
12668 
12669  /* In case an error happened from ma_device_write__null()... */
12670  if (result != MA_SUCCESS) {
12671  exitLoop = MA_TRUE;
12672  break;
12673  }
12674  }
12675 
12676  totalCapturedDeviceFramesProcessed += capturedDeviceFramesProcessed;
12677  }
12678  } break;
12679 
12682  {
12683  ma_uint32 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
12684  ma_uint32 framesReadThisPeriod = 0;
12685  while (framesReadThisPeriod < periodSizeInFrames) {
12686  ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
12687  ma_uint32 framesProcessed;
12688  ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
12689  if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
12690  framesToReadThisIteration = capturedDeviceDataCapInFrames;
12691  }
12692 
12693  result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
12694  if (result != MA_SUCCESS) {
12695  exitLoop = MA_TRUE;
12696  break;
12697  }
12698 
12699  ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
12700 
12701  framesReadThisPeriod += framesProcessed;
12702  }
12703  } break;
12704 
12706  {
12707  /* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
12708  ma_uint32 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
12709  ma_uint32 framesWrittenThisPeriod = 0;
12710  while (framesWrittenThisPeriod < periodSizeInFrames) {
12711  ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
12712  ma_uint32 framesProcessed;
12713  ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
12714  if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
12715  framesToWriteThisIteration = playbackDeviceDataCapInFrames;
12716  }
12717 
12718  ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
12719 
12720  result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
12721  if (result != MA_SUCCESS) {
12722  exitLoop = MA_TRUE;
12723  break;
12724  }
12725 
12726  framesWrittenThisPeriod += framesProcessed;
12727  }
12728  } break;
12729 
12730  /* Should never get here. */
12731  default: break;
12732  }
12733  }
12734 
12735  return result;
12736 }
12737 
12738 
12739 
12740 /*******************************************************************************
12741 
12742 Null Backend
12743 
12744 *******************************************************************************/
12745 #ifdef MA_HAS_NULL
12746 
12747 #define MA_DEVICE_OP_NONE__NULL 0
12748 #define MA_DEVICE_OP_START__NULL 1
12749 #define MA_DEVICE_OP_SUSPEND__NULL 2
12750 #define MA_DEVICE_OP_KILL__NULL 3
12751 
12753 {
12754  ma_device* pDevice = (ma_device*)pData;
12755  MA_ASSERT(pDevice != NULL);
12756 
12757  for (;;) { /* Keep the thread alive until the device is uninitialized. */
12758  ma_uint32 operation;
12759 
12760  /* Wait for an operation to be requested. */
12761  ma_event_wait(&pDevice->null_device.operationEvent);
12762 
12763  /* At this point an event should have been triggered. */
12764  operation = pDevice->null_device.operation;
12765 
12766  /* Starting the device needs to put the thread into a loop. */
12767  if (operation == MA_DEVICE_OP_START__NULL) {
12768  /* Reset the timer just in case. */
12769  ma_timer_init(&pDevice->null_device.timer);
12770 
12771  /* Getting here means a suspend or kill operation has been requested. */
12772  pDevice->null_device.operationResult = MA_SUCCESS;
12773  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
12774  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
12775  continue;
12776  }
12777 
12778  /* Suspending the device means we need to stop the timer and just continue the loop. */
12779  if (operation == MA_DEVICE_OP_SUSPEND__NULL) {
12780  /* We need to add the current run time to the prior run time, then reset the timer. */
12781  pDevice->null_device.priorRunTime += ma_timer_get_time_in_seconds(&pDevice->null_device.timer);
12782  ma_timer_init(&pDevice->null_device.timer);
12783 
12784  /* We're done. */
12785  pDevice->null_device.operationResult = MA_SUCCESS;
12786  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
12787  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
12788  continue;
12789  }
12790 
12791  /* Killing the device means we need to get out of this loop so that this thread can terminate. */
12792  if (operation == MA_DEVICE_OP_KILL__NULL) {
12793  pDevice->null_device.operationResult = MA_SUCCESS;
12794  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
12795  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
12796  break;
12797  }
12798 
12799  /* Getting a signal on a "none" operation probably means an error. Return invalid operation. */
12800  if (operation == MA_DEVICE_OP_NONE__NULL) {
12801  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). */
12802  pDevice->null_device.operationResult = MA_INVALID_OPERATION;
12803  ma_event_signal(&pDevice->null_device.operationCompletionEvent);
12804  ma_semaphore_release(&pDevice->null_device.operationSemaphore);
12805  continue; /* Continue the loop. Don't terminate. */
12806  }
12807  }
12808 
12809  return (ma_thread_result)0;
12810 }
12811 
12812 static ma_result ma_device_do_operation__null(ma_device* pDevice, ma_uint32 operation)
12813 {
12814  ma_result result;
12815 
12816  /*
12817  TODO: Need to review this and consider just using mutual exclusion. I think the original motivation
12818  for this was to just post the event to a queue and return immediately, but that has since changed
12819  and now this function is synchronous. I think this can be simplified to just use a mutex.
12820  */
12821 
12822  /*
12823  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
12824  to support queing of operations.
12825  */
12826  result = ma_semaphore_wait(&pDevice->null_device.operationSemaphore);
12827  if (result != MA_SUCCESS) {
12828  return result; /* Failed to wait for the event. */
12829  }
12830 
12831  /*
12832  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
12833  signal an event to the worker thread to let it know that it can start work.
12834  */
12835  pDevice->null_device.operation = operation;
12836 
12837  /* Once the operation code has been set, the worker thread can start work. */
12838  if (ma_event_signal(&pDevice->null_device.operationEvent) != MA_SUCCESS) {
12839  return MA_ERROR;
12840  }
12841 
12842  /* We want everything to be synchronous so we're going to wait for the worker thread to complete it's operation. */
12843  if (ma_event_wait(&pDevice->null_device.operationCompletionEvent) != MA_SUCCESS) {
12844  return MA_ERROR;
12845  }
12846 
12847  return pDevice->null_device.operationResult;
12848 }
12849 
12851 {
12852  ma_uint32 internalSampleRate;
12853  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
12854  internalSampleRate = pDevice->capture.internalSampleRate;
12855  } else {
12856  internalSampleRate = pDevice->playback.internalSampleRate;
12857  }
12858 
12859  return (ma_uint64)((pDevice->null_device.priorRunTime + ma_timer_get_time_in_seconds(&pDevice->null_device.timer)) * internalSampleRate);
12860 }
12861 
12862 static ma_result ma_context_enumerate_devices__null(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
12863 {
12864  ma_bool32 cbResult = MA_TRUE;
12865 
12866  MA_ASSERT(pContext != NULL);
12867  MA_ASSERT(callback != NULL);
12868 
12869  /* Playback. */
12870  if (cbResult) {
12871  ma_device_info deviceInfo;
12872  MA_ZERO_OBJECT(&deviceInfo);
12873  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), "NULL Playback Device", (size_t)-1);
12874  deviceInfo.isDefault = MA_TRUE; /* Only one playback and capture device for the null backend, so might as well mark as default. */
12875  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
12876  }
12877 
12878  /* Capture. */
12879  if (cbResult) {
12880  ma_device_info deviceInfo;
12881  MA_ZERO_OBJECT(&deviceInfo);
12882  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), "NULL Capture Device", (size_t)-1);
12883  deviceInfo.isDefault = MA_TRUE; /* Only one playback and capture device for the null backend, so might as well mark as default. */
12884  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
12885  }
12886 
12887  (void)cbResult; /* Silence a static analysis warning. */
12888 
12889  return MA_SUCCESS;
12890 }
12891 
12892 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)
12893 {
12894  MA_ASSERT(pContext != NULL);
12895 
12896  if (pDeviceID != NULL && pDeviceID->nullbackend != 0) {
12897  return MA_NO_DEVICE; /* Don't know the device. */
12898  }
12899 
12900  /* Name / Description */
12901  if (deviceType == ma_device_type_playback) {
12902  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), "NULL Playback Device", (size_t)-1);
12903  } else {
12904  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), "NULL Capture Device", (size_t)-1);
12905  }
12906 
12907  pDeviceInfo->isDefault = MA_TRUE; /* Only one playback and capture device for the null backend, so might as well mark as default. */
12908 
12909  /* Support everything on the null backend. */
12910  pDeviceInfo->nativeDataFormats[0].format = ma_format_unknown;
12911  pDeviceInfo->nativeDataFormats[0].channels = 0;
12912  pDeviceInfo->nativeDataFormats[0].sampleRate = 0;
12913  pDeviceInfo->nativeDataFormats[0].flags = 0;
12914  pDeviceInfo->nativeDataFormatCount = 1;
12915 
12916  (void)pContext;
12917  return MA_SUCCESS;
12918 }
12919 
12920 
12922 {
12923  MA_ASSERT(pDevice != NULL);
12924 
12925  /* Keep it clean and wait for the device thread to finish before returning. */
12927 
12928  /* Wait for the thread to finish before continuing. */
12929  ma_thread_wait(&pDevice->null_device.deviceThread);
12930 
12931  /* At this point the loop in the device thread is as good as terminated so we can uninitialize our events. */
12932  ma_semaphore_uninit(&pDevice->null_device.operationSemaphore);
12933  ma_event_uninit(&pDevice->null_device.operationCompletionEvent);
12934  ma_event_uninit(&pDevice->null_device.operationEvent);
12935 
12936  return MA_SUCCESS;
12937 }
12938 
12939 static ma_result ma_device_init__null(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
12940 {
12941  ma_result result;
12942 
12943  MA_ASSERT(pDevice != NULL);
12944 
12945  MA_ZERO_OBJECT(&pDevice->null_device);
12946 
12947  if (pConfig->deviceType == ma_device_type_loopback) {
12949  }
12950 
12951  /* The null backend supports everything exactly as we specify it. */
12952  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
12953  pDescriptorCapture->format = (pDescriptorCapture->format != ma_format_unknown) ? pDescriptorCapture->format : MA_DEFAULT_FORMAT;
12954  pDescriptorCapture->channels = (pDescriptorCapture->channels != 0) ? pDescriptorCapture->channels : MA_DEFAULT_CHANNELS;
12955  pDescriptorCapture->sampleRate = (pDescriptorCapture->sampleRate != 0) ? pDescriptorCapture->sampleRate : MA_DEFAULT_SAMPLE_RATE;
12956 
12957  if (pDescriptorCapture->channelMap[0] == MA_CHANNEL_NONE) {
12958  ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
12959  }
12960 
12961  pDescriptorCapture->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorCapture, pDescriptorCapture->sampleRate, pConfig->performanceProfile);
12962  }
12963 
12964  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
12965  pDescriptorPlayback->format = (pDescriptorPlayback->format != ma_format_unknown) ? pDescriptorPlayback->format : MA_DEFAULT_FORMAT;
12966  pDescriptorPlayback->channels = (pDescriptorPlayback->channels != 0) ? pDescriptorPlayback->channels : MA_DEFAULT_CHANNELS;
12967  pDescriptorPlayback->sampleRate = (pDescriptorPlayback->sampleRate != 0) ? pDescriptorPlayback->sampleRate : MA_DEFAULT_SAMPLE_RATE;
12968 
12969  if (pDescriptorPlayback->channelMap[0] == MA_CHANNEL_NONE) {
12970  ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
12971  }
12972 
12973  pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
12974  }
12975 
12976  /*
12977  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
12978  first period is "written" to it, and then stopped in ma_device_stop__null().
12979  */
12980  result = ma_event_init(&pDevice->null_device.operationEvent);
12981  if (result != MA_SUCCESS) {
12982  return result;
12983  }
12984 
12985  result = ma_event_init(&pDevice->null_device.operationCompletionEvent);
12986  if (result != MA_SUCCESS) {
12987  return result;
12988  }
12989 
12990  result = ma_semaphore_init(1, &pDevice->null_device.operationSemaphore); /* <-- It's important that the initial value is set to 1. */
12991  if (result != MA_SUCCESS) {
12992  return result;
12993  }
12994 
12995  result = ma_thread_create(&pDevice->null_device.deviceThread, pDevice->pContext->threadPriority, 0, ma_device_thread__null, pDevice, &pDevice->pContext->allocationCallbacks);
12996  if (result != MA_SUCCESS) {
12997  return result;
12998  }
12999 
13000  return MA_SUCCESS;
13001 }
13002 
13003 static ma_result ma_device_start__null(ma_device* pDevice)
13004 {
13005  MA_ASSERT(pDevice != NULL);
13006 
13008 
13009  c89atomic_exchange_32(&pDevice->null_device.isStarted, MA_TRUE);
13010  return MA_SUCCESS;
13011 }
13012 
13013 static ma_result ma_device_stop__null(ma_device* pDevice)
13014 {
13015  MA_ASSERT(pDevice != NULL);
13016 
13018 
13019  c89atomic_exchange_32(&pDevice->null_device.isStarted, MA_FALSE);
13020  return MA_SUCCESS;
13021 }
13022 
13023 static ma_result ma_device_write__null(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
13024 {
13025  ma_result result = MA_SUCCESS;
13026  ma_uint32 totalPCMFramesProcessed;
13027  ma_bool32 wasStartedOnEntry;
13028 
13029  if (pFramesWritten != NULL) {
13030  *pFramesWritten = 0;
13031  }
13032 
13033  wasStartedOnEntry = c89atomic_load_32(&pDevice->null_device.isStarted);
13034 
13035  /* Keep going until everything has been read. */
13036  totalPCMFramesProcessed = 0;
13037  while (totalPCMFramesProcessed < frameCount) {
13038  ma_uint64 targetFrame;
13039 
13040  /* If there are any frames remaining in the current period, consume those first. */
13041  if (pDevice->null_device.currentPeriodFramesRemainingPlayback > 0) {
13042  ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
13043  ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingPlayback;
13044  if (framesToProcess > framesRemaining) {
13045  framesToProcess = framesRemaining;
13046  }
13047 
13048  /* We don't actually do anything with pPCMFrames, so just mark it as unused to prevent a warning. */
13049  (void)pPCMFrames;
13050 
13051  pDevice->null_device.currentPeriodFramesRemainingPlayback -= framesToProcess;
13052  totalPCMFramesProcessed += framesToProcess;
13053  }
13054 
13055  /* 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. */
13056  if (pDevice->null_device.currentPeriodFramesRemainingPlayback == 0) {
13057  pDevice->null_device.currentPeriodFramesRemainingPlayback = 0;
13058 
13059  if (!c89atomic_load_32(&pDevice->null_device.isStarted) && !wasStartedOnEntry) {
13060  result = ma_device_start__null(pDevice);
13061  if (result != MA_SUCCESS) {
13062  break;
13063  }
13064  }
13065  }
13066 
13067  /* If we've consumed the whole buffer we can return now. */
13068  MA_ASSERT(totalPCMFramesProcessed <= frameCount);
13069  if (totalPCMFramesProcessed == frameCount) {
13070  break;
13071  }
13072 
13073  /* Getting here means we've still got more frames to consume, we but need to wait for it to become available. */
13074  targetFrame = pDevice->null_device.lastProcessedFramePlayback;
13075  for (;;) {
13076  ma_uint64 currentFrame;
13077 
13078  /* Stop waiting if the device has been stopped. */
13079  if (!c89atomic_load_32(&pDevice->null_device.isStarted)) {
13080  break;
13081  }
13082 
13083  currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
13084  if (currentFrame >= targetFrame) {
13085  break;
13086  }
13087 
13088  /* Getting here means we haven't yet reached the target sample, so continue waiting. */
13089  ma_sleep(10);
13090  }
13091 
13092  pDevice->null_device.lastProcessedFramePlayback += pDevice->playback.internalPeriodSizeInFrames;
13093  pDevice->null_device.currentPeriodFramesRemainingPlayback = pDevice->playback.internalPeriodSizeInFrames;
13094  }
13095 
13096  if (pFramesWritten != NULL) {
13097  *pFramesWritten = totalPCMFramesProcessed;
13098  }
13099 
13100  return result;
13101 }
13102 
13103 static ma_result ma_device_read__null(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
13104 {
13105  ma_result result = MA_SUCCESS;
13106  ma_uint32 totalPCMFramesProcessed;
13107 
13108  if (pFramesRead != NULL) {
13109  *pFramesRead = 0;
13110  }
13111 
13112  /* Keep going until everything has been read. */
13113  totalPCMFramesProcessed = 0;
13114  while (totalPCMFramesProcessed < frameCount) {
13115  ma_uint64 targetFrame;
13116 
13117  /* If there are any frames remaining in the current period, consume those first. */
13118  if (pDevice->null_device.currentPeriodFramesRemainingCapture > 0) {
13120  ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
13121  ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingCapture;
13122  if (framesToProcess > framesRemaining) {
13123  framesToProcess = framesRemaining;
13124  }
13125 
13126  /* We need to ensure the output buffer is zeroed. */
13127  MA_ZERO_MEMORY(ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed*bpf), framesToProcess*bpf);
13128 
13129  pDevice->null_device.currentPeriodFramesRemainingCapture -= framesToProcess;
13130  totalPCMFramesProcessed += framesToProcess;
13131  }
13132 
13133  /* 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. */
13134  if (pDevice->null_device.currentPeriodFramesRemainingCapture == 0) {
13135  pDevice->null_device.currentPeriodFramesRemainingCapture = 0;
13136  }
13137 
13138  /* If we've consumed the whole buffer we can return now. */
13139  MA_ASSERT(totalPCMFramesProcessed <= frameCount);
13140  if (totalPCMFramesProcessed == frameCount) {
13141  break;
13142  }
13143 
13144  /* Getting here means we've still got more frames to consume, we but need to wait for it to become available. */
13145  targetFrame = pDevice->null_device.lastProcessedFrameCapture + pDevice->capture.internalPeriodSizeInFrames;
13146  for (;;) {
13147  ma_uint64 currentFrame;
13148 
13149  /* Stop waiting if the device has been stopped. */
13150  if (!c89atomic_load_32(&pDevice->null_device.isStarted)) {
13151  break;
13152  }
13153 
13154  currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
13155  if (currentFrame >= targetFrame) {
13156  break;
13157  }
13158 
13159  /* Getting here means we haven't yet reached the target sample, so continue waiting. */
13160  ma_sleep(10);
13161  }
13162 
13163  pDevice->null_device.lastProcessedFrameCapture += pDevice->capture.internalPeriodSizeInFrames;
13164  pDevice->null_device.currentPeriodFramesRemainingCapture = pDevice->capture.internalPeriodSizeInFrames;
13165  }
13166 
13167  if (pFramesRead != NULL) {
13168  *pFramesRead = totalPCMFramesProcessed;
13169  }
13170 
13171  return result;
13172 }
13173 
13175 {
13176  MA_ASSERT(pContext != NULL);
13177  MA_ASSERT(pContext->backend == ma_backend_null);
13178 
13179  (void)pContext;
13180  return MA_SUCCESS;
13181 }
13182 
13183 static ma_result ma_context_init__null(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
13184 {
13185  MA_ASSERT(pContext != NULL);
13186 
13187  (void)pConfig;
13188  (void)pContext;
13189 
13190  pCallbacks->onContextInit = ma_context_init__null;
13194  pCallbacks->onDeviceInit = ma_device_init__null;
13195  pCallbacks->onDeviceUninit = ma_device_uninit__null;
13196  pCallbacks->onDeviceStart = ma_device_start__null;
13197  pCallbacks->onDeviceStop = ma_device_stop__null;
13198  pCallbacks->onDeviceRead = ma_device_read__null;
13199  pCallbacks->onDeviceWrite = ma_device_write__null;
13200  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. */
13201 
13202  /* The null backend always works. */
13203  return MA_SUCCESS;
13204 }
13205 #endif
13206 
13207 
13208 
13209 /*******************************************************************************
13210 
13211 WIN32 COMMON
13212 
13213 *******************************************************************************/
13214 #if defined(MA_WIN32)
13215 #if defined(MA_WIN32_DESKTOP)
13216  #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit)
13217  #define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
13218  #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
13219  #define ma_CoTaskMemFree(pContext, pv) ((MA_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pv)
13220  #define ma_PropVariantClear(pContext, pvar) ((MA_PFN_PropVariantClear)pContext->win32.PropVariantClear)(pvar)
13221 #else
13222  #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) CoInitializeEx(pvReserved, dwCoInit)
13223  #define ma_CoUninitialize(pContext) CoUninitialize()
13224  #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv)
13225  #define ma_CoTaskMemFree(pContext, pv) CoTaskMemFree(pv)
13226  #define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar)
13227 #endif
13228 
13229 #if !defined(MAXULONG_PTR) && !defined(__WATCOMC__)
13230 typedef size_t DWORD_PTR;
13231 #endif
13232 
13233 #if !defined(WAVE_FORMAT_44M08)
13234 #define WAVE_FORMAT_44M08 0x00000100
13235 #define WAVE_FORMAT_44S08 0x00000200
13236 #define WAVE_FORMAT_44M16 0x00000400
13237 #define WAVE_FORMAT_44S16 0x00000800
13238 #define WAVE_FORMAT_48M08 0x00001000
13239 #define WAVE_FORMAT_48S08 0x00002000
13240 #define WAVE_FORMAT_48M16 0x00004000
13241 #define WAVE_FORMAT_48S16 0x00008000
13242 #define WAVE_FORMAT_96M08 0x00010000
13243 #define WAVE_FORMAT_96S08 0x00020000
13244 #define WAVE_FORMAT_96M16 0x00040000
13245 #define WAVE_FORMAT_96S16 0x00080000
13246 #endif
13247 
13248 #ifndef SPEAKER_FRONT_LEFT
13249 #define SPEAKER_FRONT_LEFT 0x1
13250 #define SPEAKER_FRONT_RIGHT 0x2
13251 #define SPEAKER_FRONT_CENTER 0x4
13252 #define SPEAKER_LOW_FREQUENCY 0x8
13253 #define SPEAKER_BACK_LEFT 0x10
13254 #define SPEAKER_BACK_RIGHT 0x20
13255 #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
13256 #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
13257 #define SPEAKER_BACK_CENTER 0x100
13258 #define SPEAKER_SIDE_LEFT 0x200
13259 #define SPEAKER_SIDE_RIGHT 0x400
13260 #define SPEAKER_TOP_CENTER 0x800
13261 #define SPEAKER_TOP_FRONT_LEFT 0x1000
13262 #define SPEAKER_TOP_FRONT_CENTER 0x2000
13263 #define SPEAKER_TOP_FRONT_RIGHT 0x4000
13264 #define SPEAKER_TOP_BACK_LEFT 0x8000
13265 #define SPEAKER_TOP_BACK_CENTER 0x10000
13266 #define SPEAKER_TOP_BACK_RIGHT 0x20000
13267 #endif
13268 
13269 /*
13270 The SDK that comes with old versions of MSVC (VC6, for example) does not appear to define WAVEFORMATEXTENSIBLE. We
13271 define our own implementation in this case.
13272 */
13273 #if (defined(_MSC_VER) && !defined(_WAVEFORMATEXTENSIBLE_)) || defined(__DMC__)
13274 typedef struct
13275 {
13276  WAVEFORMATEX Format;
13277  union
13278  {
13279  WORD wValidBitsPerSample;
13280  WORD wSamplesPerBlock;
13281  WORD wReserved;
13282  } Samples;
13283  DWORD dwChannelMask;
13284  GUID SubFormat;
13285 } WAVEFORMATEXTENSIBLE;
13286 #endif
13287 
13288 #ifndef WAVE_FORMAT_EXTENSIBLE
13289 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
13290 #endif
13291 
13292 #ifndef WAVE_FORMAT_IEEE_FLOAT
13293 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
13294 #endif
13295 
13296 /* Converts an individual Win32-style channel identifier (SPEAKER_FRONT_LEFT, etc.) to miniaudio. */
13297 static ma_uint8 ma_channel_id_to_ma__win32(DWORD id)
13298 {
13299  switch (id)
13300  {
13301  case SPEAKER_FRONT_LEFT: return MA_CHANNEL_FRONT_LEFT;
13302  case SPEAKER_FRONT_RIGHT: return MA_CHANNEL_FRONT_RIGHT;
13303  case SPEAKER_FRONT_CENTER: return MA_CHANNEL_FRONT_CENTER;
13304  case SPEAKER_LOW_FREQUENCY: return MA_CHANNEL_LFE;
13305  case SPEAKER_BACK_LEFT: return MA_CHANNEL_BACK_LEFT;
13306  case SPEAKER_BACK_RIGHT: return MA_CHANNEL_BACK_RIGHT;
13307  case SPEAKER_FRONT_LEFT_OF_CENTER: return MA_CHANNEL_FRONT_LEFT_CENTER;
13308  case SPEAKER_FRONT_RIGHT_OF_CENTER: return MA_CHANNEL_FRONT_RIGHT_CENTER;
13309  case SPEAKER_BACK_CENTER: return MA_CHANNEL_BACK_CENTER;
13310  case SPEAKER_SIDE_LEFT: return MA_CHANNEL_SIDE_LEFT;
13311  case SPEAKER_SIDE_RIGHT: return MA_CHANNEL_SIDE_RIGHT;
13312  case SPEAKER_TOP_CENTER: return MA_CHANNEL_TOP_CENTER;
13313  case SPEAKER_TOP_FRONT_LEFT: return MA_CHANNEL_TOP_FRONT_LEFT;
13314  case SPEAKER_TOP_FRONT_CENTER: return MA_CHANNEL_TOP_FRONT_CENTER;
13315  case SPEAKER_TOP_FRONT_RIGHT: return MA_CHANNEL_TOP_FRONT_RIGHT;
13316  case SPEAKER_TOP_BACK_LEFT: return MA_CHANNEL_TOP_BACK_LEFT;
13317  case SPEAKER_TOP_BACK_CENTER: return MA_CHANNEL_TOP_BACK_CENTER;
13318  case SPEAKER_TOP_BACK_RIGHT: return MA_CHANNEL_TOP_BACK_RIGHT;
13319  default: return 0;
13320  }
13321 }
13322 
13323 /* Converts an individual miniaudio channel identifier (MA_CHANNEL_FRONT_LEFT, etc.) to Win32-style. */
13324 static DWORD ma_channel_id_to_win32(DWORD id)
13325 {
13326  switch (id)
13327  {
13328  case MA_CHANNEL_MONO: return SPEAKER_FRONT_CENTER;
13329  case MA_CHANNEL_FRONT_LEFT: return SPEAKER_FRONT_LEFT;
13330  case MA_CHANNEL_FRONT_RIGHT: return SPEAKER_FRONT_RIGHT;
13331  case MA_CHANNEL_FRONT_CENTER: return SPEAKER_FRONT_CENTER;
13332  case MA_CHANNEL_LFE: return SPEAKER_LOW_FREQUENCY;
13333  case MA_CHANNEL_BACK_LEFT: return SPEAKER_BACK_LEFT;
13334  case MA_CHANNEL_BACK_RIGHT: return SPEAKER_BACK_RIGHT;
13335  case MA_CHANNEL_FRONT_LEFT_CENTER: return SPEAKER_FRONT_LEFT_OF_CENTER;
13336  case MA_CHANNEL_FRONT_RIGHT_CENTER: return SPEAKER_FRONT_RIGHT_OF_CENTER;
13337  case MA_CHANNEL_BACK_CENTER: return SPEAKER_BACK_CENTER;
13338  case MA_CHANNEL_SIDE_LEFT: return SPEAKER_SIDE_LEFT;
13339  case MA_CHANNEL_SIDE_RIGHT: return SPEAKER_SIDE_RIGHT;
13340  case MA_CHANNEL_TOP_CENTER: return SPEAKER_TOP_CENTER;
13341  case MA_CHANNEL_TOP_FRONT_LEFT: return SPEAKER_TOP_FRONT_LEFT;
13342  case MA_CHANNEL_TOP_FRONT_CENTER: return SPEAKER_TOP_FRONT_CENTER;
13343  case MA_CHANNEL_TOP_FRONT_RIGHT: return SPEAKER_TOP_FRONT_RIGHT;
13344  case MA_CHANNEL_TOP_BACK_LEFT: return SPEAKER_TOP_BACK_LEFT;
13345  case MA_CHANNEL_TOP_BACK_CENTER: return SPEAKER_TOP_BACK_CENTER;
13346  case MA_CHANNEL_TOP_BACK_RIGHT: return SPEAKER_TOP_BACK_RIGHT;
13347  default: return 0;
13348  }
13349 }
13350 
13351 /* Converts a channel mapping to a Win32-style channel mask. */
13352 static DWORD ma_channel_map_to_channel_mask__win32(const ma_channel* pChannelMap, ma_uint32 channels)
13353 {
13354  DWORD dwChannelMask = 0;
13355  ma_uint32 iChannel;
13356 
13357  for (iChannel = 0; iChannel < channels; ++iChannel) {
13358  dwChannelMask |= ma_channel_id_to_win32(pChannelMap[iChannel]);
13359  }
13360 
13361  return dwChannelMask;
13362 }
13363 
13364 /* Converts a Win32-style channel mask to a miniaudio channel map. */
13365 static void ma_channel_mask_to_channel_map__win32(DWORD dwChannelMask, ma_uint32 channels, ma_channel* pChannelMap)
13366 {
13367  if (channels == 1 && dwChannelMask == 0) {
13368  pChannelMap[0] = MA_CHANNEL_MONO;
13369  } else if (channels == 2 && dwChannelMask == 0) {
13370  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
13371  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
13372  } else {
13373  if (channels == 1 && (dwChannelMask & SPEAKER_FRONT_CENTER) != 0) {
13374  pChannelMap[0] = MA_CHANNEL_MONO;
13375  } else {
13376  /* Just iterate over each bit. */
13377  ma_uint32 iChannel = 0;
13378  ma_uint32 iBit;
13379 
13380  for (iBit = 0; iBit < 32 && iChannel < channels; ++iBit) {
13381  DWORD bitValue = (dwChannelMask & (1UL << iBit));
13382  if (bitValue != 0) {
13383  /* The bit is set. */
13384  pChannelMap[iChannel] = ma_channel_id_to_ma__win32(bitValue);
13385  iChannel += 1;
13386  }
13387  }
13388  }
13389  }
13390 }
13391 
13392 #ifdef __cplusplus
13393 static ma_bool32 ma_is_guid_equal(const void* a, const void* b)
13394 {
13395  return IsEqualGUID(*(const GUID*)a, *(const GUID*)b);
13396 }
13397 #else
13398 #define ma_is_guid_equal(a, b) IsEqualGUID((const GUID*)a, (const GUID*)b)
13399 #endif
13400 
13401 static MA_INLINE ma_bool32 ma_is_guid_null(const void* guid)
13402 {
13403  static GUID nullguid = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
13404  return ma_is_guid_equal(guid, &nullguid);
13405 }
13406 
13407 static ma_format ma_format_from_WAVEFORMATEX(const WAVEFORMATEX* pWF)
13408 {
13409  MA_ASSERT(pWF != NULL);
13410 
13411  if (pWF->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
13412  const WAVEFORMATEXTENSIBLE* pWFEX = (const WAVEFORMATEXTENSIBLE*)pWF;
13413  if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_PCM)) {
13414  if (pWFEX->Samples.wValidBitsPerSample == 32) {
13415  return ma_format_s32;
13416  }
13417  if (pWFEX->Samples.wValidBitsPerSample == 24) {
13418  if (pWFEX->Format.wBitsPerSample == 32) {
13419  /*return ma_format_s24_32;*/
13420  }
13421  if (pWFEX->Format.wBitsPerSample == 24) {
13422  return ma_format_s24;
13423  }
13424  }
13425  if (pWFEX->Samples.wValidBitsPerSample == 16) {
13426  return ma_format_s16;
13427  }
13428  if (pWFEX->Samples.wValidBitsPerSample == 8) {
13429  return ma_format_u8;
13430  }
13431  }
13432  if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
13433  if (pWFEX->Samples.wValidBitsPerSample == 32) {
13434  return ma_format_f32;
13435  }
13436  /*
13437  if (pWFEX->Samples.wValidBitsPerSample == 64) {
13438  return ma_format_f64;
13439  }
13440  */
13441  }
13442  } else {
13443  if (pWF->wFormatTag == WAVE_FORMAT_PCM) {
13444  if (pWF->wBitsPerSample == 32) {
13445  return ma_format_s32;
13446  }
13447  if (pWF->wBitsPerSample == 24) {
13448  return ma_format_s24;
13449  }
13450  if (pWF->wBitsPerSample == 16) {
13451  return ma_format_s16;
13452  }
13453  if (pWF->wBitsPerSample == 8) {
13454  return ma_format_u8;
13455  }
13456  }
13457  if (pWF->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
13458  if (pWF->wBitsPerSample == 32) {
13459  return ma_format_f32;
13460  }
13461  if (pWF->wBitsPerSample == 64) {
13462  /*return ma_format_f64;*/
13463  }
13464  }
13465  }
13466 
13467  return ma_format_unknown;
13468 }
13469 #endif
13470 
13471 
13472 /*******************************************************************************
13473 
13474 WASAPI Backend
13475 
13476 *******************************************************************************/
13477 #ifdef MA_HAS_WASAPI
13478 #if 0
13479 #if defined(_MSC_VER)
13480  #pragma warning(push)
13481  #pragma warning(disable:4091) /* 'typedef ': ignored on left of '' when no variable is declared */
13482 #endif
13483 #include <audioclient.h>
13484 #include <mmdeviceapi.h>
13485 #if defined(_MSC_VER)
13486  #pragma warning(pop)
13487 #endif
13488 #endif /* 0 */
13489 
13490 static ma_result ma_device_reroute__wasapi(ma_device* pDevice, ma_device_type deviceType);
13491 
13492 /* Some compilers don't define VerifyVersionInfoW. Need to write this ourselves. */
13493 #define MA_WIN32_WINNT_VISTA 0x0600
13494 #define MA_VER_MINORVERSION 0x01
13495 #define MA_VER_MAJORVERSION 0x02
13496 #define MA_VER_SERVICEPACKMAJOR 0x20
13497 #define MA_VER_GREATER_EQUAL 0x03
13498 
13499 typedef struct {
13500  DWORD dwOSVersionInfoSize;
13501  DWORD dwMajorVersion;
13502  DWORD dwMinorVersion;
13503  DWORD dwBuildNumber;
13504  DWORD dwPlatformId;
13505  WCHAR szCSDVersion[128];
13506  WORD wServicePackMajor;
13507  WORD wServicePackMinor;
13508  WORD wSuiteMask;
13509  BYTE wProductType;
13510  BYTE wReserved;
13511 } ma_OSVERSIONINFOEXW;
13512 
13513 typedef BOOL (WINAPI * ma_PFNVerifyVersionInfoW) (ma_OSVERSIONINFOEXW* lpVersionInfo, DWORD dwTypeMask, DWORDLONG dwlConditionMask);
13514 typedef ULONGLONG (WINAPI * ma_PFNVerSetConditionMask)(ULONGLONG dwlConditionMask, DWORD dwTypeBitMask, BYTE dwConditionMask);
13515 
13516 
13517 #ifndef PROPERTYKEY_DEFINED
13518 #define PROPERTYKEY_DEFINED
13519 #ifndef __WATCOMC__
13520 typedef struct
13521 {
13522  GUID fmtid;
13523  DWORD pid;
13524 } PROPERTYKEY;
13525 #endif
13526 #endif
13527 
13528 /* Some compilers don't define PropVariantInit(). We just do this ourselves since it's just a memset(). */
13529 static MA_INLINE void ma_PropVariantInit(PROPVARIANT* pProp)
13530 {
13531  MA_ZERO_OBJECT(pProp);
13532 }
13533 
13534 
13535 static const PROPERTYKEY MA_PKEY_Device_FriendlyName = {{0xA45C254E, 0xDF1C, 0x4EFD, {0x80, 0x20, 0x67, 0xD1, 0x46, 0xA8, 0x50, 0xE0}}, 14};
13536 static const PROPERTYKEY MA_PKEY_AudioEngine_DeviceFormat = {{0xF19F064D, 0x82C, 0x4E27, {0xBC, 0x73, 0x68, 0x82, 0xA1, 0xBB, 0x8E, 0x4C}}, 0};
13537 
13538 static const IID MA_IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; /* 00000000-0000-0000-C000-000000000046 */
13539 #ifndef MA_WIN32_DESKTOP
13540 static const IID MA_IID_IAgileObject = {0x94EA2B94, 0xE9CC, 0x49E0, {0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90}}; /* 94EA2B94-E9CC-49E0-C0FF-EE64CA8F5B90 */
13541 #endif
13542 
13543 static const IID MA_IID_IAudioClient = {0x1CB9AD4C, 0xDBFA, 0x4C32, {0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}}; /* 1CB9AD4C-DBFA-4C32-B178-C2F568A703B2 = __uuidof(IAudioClient) */
13544 static const IID MA_IID_IAudioClient2 = {0x726778CD, 0xF60A, 0x4EDA, {0x82, 0xDE, 0xE4, 0x76, 0x10, 0xCD, 0x78, 0xAA}}; /* 726778CD-F60A-4EDA-82DE-E47610CD78AA = __uuidof(IAudioClient2) */
13545 static const IID MA_IID_IAudioClient3 = {0x7ED4EE07, 0x8E67, 0x4CD4, {0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42}}; /* 7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42 = __uuidof(IAudioClient3) */
13546 static const IID MA_IID_IAudioRenderClient = {0xF294ACFC, 0x3146, 0x4483, {0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}}; /* F294ACFC-3146-4483-A7BF-ADDCA7C260E2 = __uuidof(IAudioRenderClient) */
13547 static const IID MA_IID_IAudioCaptureClient = {0xC8ADBD64, 0xE71E, 0x48A0, {0xA4, 0xDE, 0x18, 0x5C, 0x39, 0x5C, 0xD3, 0x17}}; /* C8ADBD64-E71E-48A0-A4DE-185C395CD317 = __uuidof(IAudioCaptureClient) */
13548 static const IID MA_IID_IMMNotificationClient = {0x7991EEC9, 0x7E89, 0x4D85, {0x83, 0x90, 0x6C, 0x70, 0x3C, 0xEC, 0x60, 0xC0}}; /* 7991EEC9-7E89-4D85-8390-6C703CEC60C0 = __uuidof(IMMNotificationClient) */
13549 #ifndef MA_WIN32_DESKTOP
13550 static const IID MA_IID_DEVINTERFACE_AUDIO_RENDER = {0xE6327CAD, 0xDCEC, 0x4949, {0xAE, 0x8A, 0x99, 0x1E, 0x97, 0x6A, 0x79, 0xD2}}; /* E6327CAD-DCEC-4949-AE8A-991E976A79D2 */
13551 static const IID MA_IID_DEVINTERFACE_AUDIO_CAPTURE = {0x2EEF81BE, 0x33FA, 0x4800, {0x96, 0x70, 0x1C, 0xD4, 0x74, 0x97, 0x2C, 0x3F}}; /* 2EEF81BE-33FA-4800-9670-1CD474972C3F */
13552 static const IID MA_IID_IActivateAudioInterfaceCompletionHandler = {0x41D949AB, 0x9862, 0x444A, {0x80, 0xF6, 0xC2, 0x61, 0x33, 0x4D, 0xA5, 0xEB}}; /* 41D949AB-9862-444A-80F6-C261334DA5EB */
13553 #endif
13554 
13555 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) */
13556 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) */
13557 #ifdef __cplusplus
13558 #define MA_CLSID_MMDeviceEnumerator MA_CLSID_MMDeviceEnumerator_Instance
13559 #define MA_IID_IMMDeviceEnumerator MA_IID_IMMDeviceEnumerator_Instance
13560 #else
13561 #define MA_CLSID_MMDeviceEnumerator &MA_CLSID_MMDeviceEnumerator_Instance
13562 #define MA_IID_IMMDeviceEnumerator &MA_IID_IMMDeviceEnumerator_Instance
13563 #endif
13564 
13565 typedef struct ma_IUnknown ma_IUnknown;
13566 #ifdef MA_WIN32_DESKTOP
13567 #define MA_MM_DEVICE_STATE_ACTIVE 1
13568 #define MA_MM_DEVICE_STATE_DISABLED 2
13569 #define MA_MM_DEVICE_STATE_NOTPRESENT 4
13570 #define MA_MM_DEVICE_STATE_UNPLUGGED 8
13571 
13572 typedef struct ma_IMMDeviceEnumerator ma_IMMDeviceEnumerator;
13573 typedef struct ma_IMMDeviceCollection ma_IMMDeviceCollection;
13574 typedef struct ma_IMMDevice ma_IMMDevice;
13575 #else
13576 typedef struct ma_IActivateAudioInterfaceCompletionHandler ma_IActivateAudioInterfaceCompletionHandler;
13577 typedef struct ma_IActivateAudioInterfaceAsyncOperation ma_IActivateAudioInterfaceAsyncOperation;
13578 #endif
13579 typedef struct ma_IPropertyStore ma_IPropertyStore;
13580 typedef struct ma_IAudioClient ma_IAudioClient;
13581 typedef struct ma_IAudioClient2 ma_IAudioClient2;
13582 typedef struct ma_IAudioClient3 ma_IAudioClient3;
13583 typedef struct ma_IAudioRenderClient ma_IAudioRenderClient;
13584 typedef struct ma_IAudioCaptureClient ma_IAudioCaptureClient;
13585 
13586 typedef ma_int64 MA_REFERENCE_TIME;
13587 
13588 #define MA_AUDCLNT_STREAMFLAGS_CROSSPROCESS 0x00010000
13589 #define MA_AUDCLNT_STREAMFLAGS_LOOPBACK 0x00020000
13590 #define MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK 0x00040000
13591 #define MA_AUDCLNT_STREAMFLAGS_NOPERSIST 0x00080000
13592 #define MA_AUDCLNT_STREAMFLAGS_RATEADJUST 0x00100000
13593 #define MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000
13594 #define MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
13595 #define MA_AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED 0x10000000
13596 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE 0x20000000
13597 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED 0x40000000
13598 
13599 /* Buffer flags. */
13600 #define MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY 1
13601 #define MA_AUDCLNT_BUFFERFLAGS_SILENT 2
13602 #define MA_AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR 4
13603 
13604 typedef enum
13605 {
13606  ma_eRender = 0,
13607  ma_eCapture = 1,
13608  ma_eAll = 2
13609 } ma_EDataFlow;
13610 
13611 typedef enum
13612 {
13613  ma_eConsole = 0,
13614  ma_eMultimedia = 1,
13615  ma_eCommunications = 2
13616 } ma_ERole;
13617 
13618 typedef enum
13619 {
13620  MA_AUDCLNT_SHAREMODE_SHARED,
13621  MA_AUDCLNT_SHAREMODE_EXCLUSIVE
13622 } MA_AUDCLNT_SHAREMODE;
13623 
13624 typedef enum
13625 {
13626  MA_AudioCategory_Other = 0 /* <-- miniaudio is only caring about Other. */
13627 } MA_AUDIO_STREAM_CATEGORY;
13628 
13629 typedef struct
13630 {
13631  ma_uint32 cbSize;
13632  BOOL bIsOffload;
13633  MA_AUDIO_STREAM_CATEGORY eCategory;
13634 } ma_AudioClientProperties;
13635 
13636 /* IUnknown */
13637 typedef struct
13638 {
13639  /* IUnknown */
13640  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IUnknown* pThis, const IID* const riid, void** ppObject);
13641  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IUnknown* pThis);
13642  ULONG (STDMETHODCALLTYPE * Release) (ma_IUnknown* pThis);
13643 } ma_IUnknownVtbl;
13644 struct ma_IUnknown
13645 {
13646  ma_IUnknownVtbl* lpVtbl;
13647 };
13648 static MA_INLINE HRESULT ma_IUnknown_QueryInterface(ma_IUnknown* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13649 static MA_INLINE ULONG ma_IUnknown_AddRef(ma_IUnknown* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13650 static MA_INLINE ULONG ma_IUnknown_Release(ma_IUnknown* pThis) { return pThis->lpVtbl->Release(pThis); }
13651 
13652 #ifdef MA_WIN32_DESKTOP
13653  /* IMMNotificationClient */
13654  typedef struct
13655  {
13656  /* IUnknown */
13657  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMNotificationClient* pThis, const IID* const riid, void** ppObject);
13658  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMNotificationClient* pThis);
13659  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMNotificationClient* pThis);
13660 
13661  /* IMMNotificationClient */
13662  HRESULT (STDMETHODCALLTYPE * OnDeviceStateChanged) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, DWORD dwNewState);
13663  HRESULT (STDMETHODCALLTYPE * OnDeviceAdded) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID);
13664  HRESULT (STDMETHODCALLTYPE * OnDeviceRemoved) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID);
13665  HRESULT (STDMETHODCALLTYPE * OnDefaultDeviceChanged)(ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID);
13666  HRESULT (STDMETHODCALLTYPE * OnPropertyValueChanged)(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, const PROPERTYKEY key);
13667  } ma_IMMNotificationClientVtbl;
13668 
13669  /* IMMDeviceEnumerator */
13670  typedef struct
13671  {
13672  /* IUnknown */
13673  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceEnumerator* pThis, const IID* const riid, void** ppObject);
13674  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceEnumerator* pThis);
13675  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceEnumerator* pThis);
13676 
13677  /* IMMDeviceEnumerator */
13678  HRESULT (STDMETHODCALLTYPE * EnumAudioEndpoints) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices);
13679  HRESULT (STDMETHODCALLTYPE * GetDefaultAudioEndpoint) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint);
13680  HRESULT (STDMETHODCALLTYPE * GetDevice) (ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice);
13681  HRESULT (STDMETHODCALLTYPE * RegisterEndpointNotificationCallback) (ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient);
13682  HRESULT (STDMETHODCALLTYPE * UnregisterEndpointNotificationCallback)(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient);
13683  } ma_IMMDeviceEnumeratorVtbl;
13684  struct ma_IMMDeviceEnumerator
13685  {
13686  ma_IMMDeviceEnumeratorVtbl* lpVtbl;
13687  };
13688  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_QueryInterface(ma_IMMDeviceEnumerator* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13689  static MA_INLINE ULONG ma_IMMDeviceEnumerator_AddRef(ma_IMMDeviceEnumerator* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13690  static MA_INLINE ULONG ma_IMMDeviceEnumerator_Release(ma_IMMDeviceEnumerator* pThis) { return pThis->lpVtbl->Release(pThis); }
13691  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); }
13692  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); }
13693  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_GetDevice(ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice) { return pThis->lpVtbl->GetDevice(pThis, pID, ppDevice); }
13694  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_RegisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient) { return pThis->lpVtbl->RegisterEndpointNotificationCallback(pThis, pClient); }
13695  static MA_INLINE HRESULT ma_IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient) { return pThis->lpVtbl->UnregisterEndpointNotificationCallback(pThis, pClient); }
13696 
13697 
13698  /* IMMDeviceCollection */
13699  typedef struct
13700  {
13701  /* IUnknown */
13702  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceCollection* pThis, const IID* const riid, void** ppObject);
13703  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceCollection* pThis);
13704  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceCollection* pThis);
13705 
13706  /* IMMDeviceCollection */
13707  HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IMMDeviceCollection* pThis, UINT* pDevices);
13708  HRESULT (STDMETHODCALLTYPE * Item) (ma_IMMDeviceCollection* pThis, UINT nDevice, ma_IMMDevice** ppDevice);
13709  } ma_IMMDeviceCollectionVtbl;
13710  struct ma_IMMDeviceCollection
13711  {
13712  ma_IMMDeviceCollectionVtbl* lpVtbl;
13713  };
13714  static MA_INLINE HRESULT ma_IMMDeviceCollection_QueryInterface(ma_IMMDeviceCollection* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13715  static MA_INLINE ULONG ma_IMMDeviceCollection_AddRef(ma_IMMDeviceCollection* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13716  static MA_INLINE ULONG ma_IMMDeviceCollection_Release(ma_IMMDeviceCollection* pThis) { return pThis->lpVtbl->Release(pThis); }
13717  static MA_INLINE HRESULT ma_IMMDeviceCollection_GetCount(ma_IMMDeviceCollection* pThis, UINT* pDevices) { return pThis->lpVtbl->GetCount(pThis, pDevices); }
13718  static MA_INLINE HRESULT ma_IMMDeviceCollection_Item(ma_IMMDeviceCollection* pThis, UINT nDevice, ma_IMMDevice** ppDevice) { return pThis->lpVtbl->Item(pThis, nDevice, ppDevice); }
13719 
13720 
13721  /* IMMDevice */
13722  typedef struct
13723  {
13724  /* IUnknown */
13725  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDevice* pThis, const IID* const riid, void** ppObject);
13726  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDevice* pThis);
13727  ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDevice* pThis);
13728 
13729  /* IMMDevice */
13730  HRESULT (STDMETHODCALLTYPE * Activate) (ma_IMMDevice* pThis, const IID* const iid, DWORD dwClsCtx, PROPVARIANT* pActivationParams, void** ppInterface);
13731  HRESULT (STDMETHODCALLTYPE * OpenPropertyStore)(ma_IMMDevice* pThis, DWORD stgmAccess, ma_IPropertyStore** ppProperties);
13732  HRESULT (STDMETHODCALLTYPE * GetId) (ma_IMMDevice* pThis, LPWSTR *pID);
13733  HRESULT (STDMETHODCALLTYPE * GetState) (ma_IMMDevice* pThis, DWORD *pState);
13734  } ma_IMMDeviceVtbl;
13735  struct ma_IMMDevice
13736  {
13737  ma_IMMDeviceVtbl* lpVtbl;
13738  };
13739  static MA_INLINE HRESULT ma_IMMDevice_QueryInterface(ma_IMMDevice* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13740  static MA_INLINE ULONG ma_IMMDevice_AddRef(ma_IMMDevice* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13741  static MA_INLINE ULONG ma_IMMDevice_Release(ma_IMMDevice* pThis) { return pThis->lpVtbl->Release(pThis); }
13742  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); }
13743  static MA_INLINE HRESULT ma_IMMDevice_OpenPropertyStore(ma_IMMDevice* pThis, DWORD stgmAccess, ma_IPropertyStore** ppProperties) { return pThis->lpVtbl->OpenPropertyStore(pThis, stgmAccess, ppProperties); }
13744  static MA_INLINE HRESULT ma_IMMDevice_GetId(ma_IMMDevice* pThis, LPWSTR *pID) { return pThis->lpVtbl->GetId(pThis, pID); }
13745  static MA_INLINE HRESULT ma_IMMDevice_GetState(ma_IMMDevice* pThis, DWORD *pState) { return pThis->lpVtbl->GetState(pThis, pState); }
13746 #else
13747  /* IActivateAudioInterfaceAsyncOperation */
13748  typedef struct
13749  {
13750  /* IUnknown */
13751  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IActivateAudioInterfaceAsyncOperation* pThis, const IID* const riid, void** ppObject);
13752  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
13753  ULONG (STDMETHODCALLTYPE * Release) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
13754 
13755  /* IActivateAudioInterfaceAsyncOperation */
13756  HRESULT (STDMETHODCALLTYPE * GetActivateResult)(ma_IActivateAudioInterfaceAsyncOperation* pThis, HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface);
13757  } ma_IActivateAudioInterfaceAsyncOperationVtbl;
13758  struct ma_IActivateAudioInterfaceAsyncOperation
13759  {
13760  ma_IActivateAudioInterfaceAsyncOperationVtbl* lpVtbl;
13761  };
13762  static MA_INLINE HRESULT ma_IActivateAudioInterfaceAsyncOperation_QueryInterface(ma_IActivateAudioInterfaceAsyncOperation* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13763  static MA_INLINE ULONG ma_IActivateAudioInterfaceAsyncOperation_AddRef(ma_IActivateAudioInterfaceAsyncOperation* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13764  static MA_INLINE ULONG ma_IActivateAudioInterfaceAsyncOperation_Release(ma_IActivateAudioInterfaceAsyncOperation* pThis) { return pThis->lpVtbl->Release(pThis); }
13765  static MA_INLINE HRESULT ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(ma_IActivateAudioInterfaceAsyncOperation* pThis, HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface) { return pThis->lpVtbl->GetActivateResult(pThis, pActivateResult, ppActivatedInterface); }
13766 #endif
13767 
13768 /* IPropertyStore */
13769 typedef struct
13770 {
13771  /* IUnknown */
13772  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IPropertyStore* pThis, const IID* const riid, void** ppObject);
13773  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IPropertyStore* pThis);
13774  ULONG (STDMETHODCALLTYPE * Release) (ma_IPropertyStore* pThis);
13775 
13776  /* IPropertyStore */
13777  HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IPropertyStore* pThis, DWORD* pPropCount);
13778  HRESULT (STDMETHODCALLTYPE * GetAt) (ma_IPropertyStore* pThis, DWORD propIndex, PROPERTYKEY* pPropKey);
13779  HRESULT (STDMETHODCALLTYPE * GetValue)(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, PROPVARIANT* pPropVar);
13780  HRESULT (STDMETHODCALLTYPE * SetValue)(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, const PROPVARIANT* const pPropVar);
13781  HRESULT (STDMETHODCALLTYPE * Commit) (ma_IPropertyStore* pThis);
13782 } ma_IPropertyStoreVtbl;
13783 struct ma_IPropertyStore
13784 {
13785  ma_IPropertyStoreVtbl* lpVtbl;
13786 };
13787 static MA_INLINE HRESULT ma_IPropertyStore_QueryInterface(ma_IPropertyStore* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13788 static MA_INLINE ULONG ma_IPropertyStore_AddRef(ma_IPropertyStore* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13789 static MA_INLINE ULONG ma_IPropertyStore_Release(ma_IPropertyStore* pThis) { return pThis->lpVtbl->Release(pThis); }
13790 static MA_INLINE HRESULT ma_IPropertyStore_GetCount(ma_IPropertyStore* pThis, DWORD* pPropCount) { return pThis->lpVtbl->GetCount(pThis, pPropCount); }
13791 static MA_INLINE HRESULT ma_IPropertyStore_GetAt(ma_IPropertyStore* pThis, DWORD propIndex, PROPERTYKEY* pPropKey) { return pThis->lpVtbl->GetAt(pThis, propIndex, pPropKey); }
13792 static MA_INLINE HRESULT ma_IPropertyStore_GetValue(ma_IPropertyStore* pThis, const PROPERTYKEY* const pKey, PROPVARIANT* pPropVar) { return pThis->lpVtbl->GetValue(pThis, pKey, pPropVar); }
13793 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); }
13794 static MA_INLINE HRESULT ma_IPropertyStore_Commit(ma_IPropertyStore* pThis) { return pThis->lpVtbl->Commit(pThis); }
13795 
13796 
13797 /* IAudioClient */
13798 typedef struct
13799 {
13800  /* IUnknown */
13801  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient* pThis, const IID* const riid, void** ppObject);
13802  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient* pThis);
13803  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient* pThis);
13804 
13805  /* IAudioClient */
13806  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);
13807  HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient* pThis, ma_uint32* pNumBufferFrames);
13808  HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency);
13809  HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient* pThis, ma_uint32* pNumPaddingFrames);
13810  HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
13811  HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat);
13812  HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
13813  HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient* pThis);
13814  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient* pThis);
13815  HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient* pThis);
13816  HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient* pThis, HANDLE eventHandle);
13817  HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient* pThis, const IID* const riid, void** pp);
13818 } ma_IAudioClientVtbl;
13819 struct ma_IAudioClient
13820 {
13821  ma_IAudioClientVtbl* lpVtbl;
13822 };
13823 static MA_INLINE HRESULT ma_IAudioClient_QueryInterface(ma_IAudioClient* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13824 static MA_INLINE ULONG ma_IAudioClient_AddRef(ma_IAudioClient* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13825 static MA_INLINE ULONG ma_IAudioClient_Release(ma_IAudioClient* pThis) { return pThis->lpVtbl->Release(pThis); }
13826 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); }
13827 static MA_INLINE HRESULT ma_IAudioClient_GetBufferSize(ma_IAudioClient* pThis, ma_uint32* pNumBufferFrames) { return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
13828 static MA_INLINE HRESULT ma_IAudioClient_GetStreamLatency(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency) { return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
13829 static MA_INLINE HRESULT ma_IAudioClient_GetCurrentPadding(ma_IAudioClient* pThis, ma_uint32* pNumPaddingFrames) { return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
13830 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); }
13831 static MA_INLINE HRESULT ma_IAudioClient_GetMixFormat(ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat) { return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
13832 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); }
13833 static MA_INLINE HRESULT ma_IAudioClient_Start(ma_IAudioClient* pThis) { return pThis->lpVtbl->Start(pThis); }
13834 static MA_INLINE HRESULT ma_IAudioClient_Stop(ma_IAudioClient* pThis) { return pThis->lpVtbl->Stop(pThis); }
13835 static MA_INLINE HRESULT ma_IAudioClient_Reset(ma_IAudioClient* pThis) { return pThis->lpVtbl->Reset(pThis); }
13836 static MA_INLINE HRESULT ma_IAudioClient_SetEventHandle(ma_IAudioClient* pThis, HANDLE eventHandle) { return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
13837 static MA_INLINE HRESULT ma_IAudioClient_GetService(ma_IAudioClient* pThis, const IID* const riid, void** pp) { return pThis->lpVtbl->GetService(pThis, riid, pp); }
13838 
13839 /* IAudioClient2 */
13840 typedef struct
13841 {
13842  /* IUnknown */
13843  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient2* pThis, const IID* const riid, void** ppObject);
13844  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient2* pThis);
13845  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient2* pThis);
13846 
13847  /* IAudioClient */
13848  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);
13849  HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient2* pThis, ma_uint32* pNumBufferFrames);
13850  HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency);
13851  HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient2* pThis, ma_uint32* pNumPaddingFrames);
13852  HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
13853  HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat);
13854  HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
13855  HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient2* pThis);
13856  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient2* pThis);
13857  HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient2* pThis);
13858  HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient2* pThis, HANDLE eventHandle);
13859  HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient2* pThis, const IID* const riid, void** pp);
13860 
13861  /* IAudioClient2 */
13862  HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable);
13863  HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient2* pThis, const ma_AudioClientProperties* pProperties);
13864  HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient2* pThis, const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
13865 } ma_IAudioClient2Vtbl;
13866 struct ma_IAudioClient2
13867 {
13868  ma_IAudioClient2Vtbl* lpVtbl;
13869 };
13870 static MA_INLINE HRESULT ma_IAudioClient2_QueryInterface(ma_IAudioClient2* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13871 static MA_INLINE ULONG ma_IAudioClient2_AddRef(ma_IAudioClient2* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13872 static MA_INLINE ULONG ma_IAudioClient2_Release(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Release(pThis); }
13873 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); }
13874 static MA_INLINE HRESULT ma_IAudioClient2_GetBufferSize(ma_IAudioClient2* pThis, ma_uint32* pNumBufferFrames) { return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
13875 static MA_INLINE HRESULT ma_IAudioClient2_GetStreamLatency(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency) { return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
13876 static MA_INLINE HRESULT ma_IAudioClient2_GetCurrentPadding(ma_IAudioClient2* pThis, ma_uint32* pNumPaddingFrames) { return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
13877 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); }
13878 static MA_INLINE HRESULT ma_IAudioClient2_GetMixFormat(ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat) { return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
13879 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); }
13880 static MA_INLINE HRESULT ma_IAudioClient2_Start(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Start(pThis); }
13881 static MA_INLINE HRESULT ma_IAudioClient2_Stop(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Stop(pThis); }
13882 static MA_INLINE HRESULT ma_IAudioClient2_Reset(ma_IAudioClient2* pThis) { return pThis->lpVtbl->Reset(pThis); }
13883 static MA_INLINE HRESULT ma_IAudioClient2_SetEventHandle(ma_IAudioClient2* pThis, HANDLE eventHandle) { return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
13884 static MA_INLINE HRESULT ma_IAudioClient2_GetService(ma_IAudioClient2* pThis, const IID* const riid, void** pp) { return pThis->lpVtbl->GetService(pThis, riid, pp); }
13885 static MA_INLINE HRESULT ma_IAudioClient2_IsOffloadCapable(ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable) { return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
13886 static MA_INLINE HRESULT ma_IAudioClient2_SetClientProperties(ma_IAudioClient2* pThis, const ma_AudioClientProperties* pProperties) { return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
13887 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); }
13888 
13889 
13890 /* IAudioClient3 */
13891 typedef struct
13892 {
13893  /* IUnknown */
13894  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient3* pThis, const IID* const riid, void** ppObject);
13895  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient3* pThis);
13896  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient3* pThis);
13897 
13898  /* IAudioClient */
13899  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);
13900  HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient3* pThis, ma_uint32* pNumBufferFrames);
13901  HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency);
13902  HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient3* pThis, ma_uint32* pNumPaddingFrames);
13903  HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
13904  HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat);
13905  HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
13906  HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient3* pThis);
13907  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient3* pThis);
13908  HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient3* pThis);
13909  HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient3* pThis, HANDLE eventHandle);
13910  HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient3* pThis, const IID* const riid, void** pp);
13911 
13912  /* IAudioClient2 */
13913  HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable);
13914  HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient3* pThis, const ma_AudioClientProperties* pProperties);
13915  HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient3* pThis, const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
13916 
13917  /* IAudioClient3 */
13918  HRESULT (STDMETHODCALLTYPE * GetSharedModeEnginePeriod) (ma_IAudioClient3* pThis, const WAVEFORMATEX* pFormat, ma_uint32* pDefaultPeriodInFrames, ma_uint32* pFundamentalPeriodInFrames, ma_uint32* pMinPeriodInFrames, ma_uint32* pMaxPeriodInFrames);
13919  HRESULT (STDMETHODCALLTYPE * GetCurrentSharedModeEnginePeriod)(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, ma_uint32* pCurrentPeriodInFrames);
13920  HRESULT (STDMETHODCALLTYPE * InitializeSharedAudioStream) (ma_IAudioClient3* pThis, DWORD streamFlags, ma_uint32 periodInFrames, const WAVEFORMATEX* pFormat, const GUID* pAudioSessionGuid);
13921 } ma_IAudioClient3Vtbl;
13922 struct ma_IAudioClient3
13923 {
13924  ma_IAudioClient3Vtbl* lpVtbl;
13925 };
13926 static MA_INLINE HRESULT ma_IAudioClient3_QueryInterface(ma_IAudioClient3* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13927 static MA_INLINE ULONG ma_IAudioClient3_AddRef(ma_IAudioClient3* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13928 static MA_INLINE ULONG ma_IAudioClient3_Release(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Release(pThis); }
13929 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); }
13930 static MA_INLINE HRESULT ma_IAudioClient3_GetBufferSize(ma_IAudioClient3* pThis, ma_uint32* pNumBufferFrames) { return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
13931 static MA_INLINE HRESULT ma_IAudioClient3_GetStreamLatency(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency) { return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
13932 static MA_INLINE HRESULT ma_IAudioClient3_GetCurrentPadding(ma_IAudioClient3* pThis, ma_uint32* pNumPaddingFrames) { return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
13933 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); }
13934 static MA_INLINE HRESULT ma_IAudioClient3_GetMixFormat(ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat) { return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
13935 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); }
13936 static MA_INLINE HRESULT ma_IAudioClient3_Start(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Start(pThis); }
13937 static MA_INLINE HRESULT ma_IAudioClient3_Stop(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Stop(pThis); }
13938 static MA_INLINE HRESULT ma_IAudioClient3_Reset(ma_IAudioClient3* pThis) { return pThis->lpVtbl->Reset(pThis); }
13939 static MA_INLINE HRESULT ma_IAudioClient3_SetEventHandle(ma_IAudioClient3* pThis, HANDLE eventHandle) { return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
13940 static MA_INLINE HRESULT ma_IAudioClient3_GetService(ma_IAudioClient3* pThis, const IID* const riid, void** pp) { return pThis->lpVtbl->GetService(pThis, riid, pp); }
13941 static MA_INLINE HRESULT ma_IAudioClient3_IsOffloadCapable(ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable) { return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
13942 static MA_INLINE HRESULT ma_IAudioClient3_SetClientProperties(ma_IAudioClient3* pThis, const ma_AudioClientProperties* pProperties) { return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
13943 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); }
13944 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); }
13945 static MA_INLINE HRESULT ma_IAudioClient3_GetCurrentSharedModeEnginePeriod(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, ma_uint32* pCurrentPeriodInFrames) { return pThis->lpVtbl->GetCurrentSharedModeEnginePeriod(pThis, ppFormat, pCurrentPeriodInFrames); }
13946 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); }
13947 
13948 
13949 /* IAudioRenderClient */
13950 typedef struct
13951 {
13952  /* IUnknown */
13953  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioRenderClient* pThis, const IID* const riid, void** ppObject);
13954  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioRenderClient* pThis);
13955  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioRenderClient* pThis);
13956 
13957  /* IAudioRenderClient */
13958  HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioRenderClient* pThis, ma_uint32 numFramesRequested, BYTE** ppData);
13959  HRESULT (STDMETHODCALLTYPE * ReleaseBuffer)(ma_IAudioRenderClient* pThis, ma_uint32 numFramesWritten, DWORD dwFlags);
13960 } ma_IAudioRenderClientVtbl;
13961 struct ma_IAudioRenderClient
13962 {
13963  ma_IAudioRenderClientVtbl* lpVtbl;
13964 };
13965 static MA_INLINE HRESULT ma_IAudioRenderClient_QueryInterface(ma_IAudioRenderClient* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13966 static MA_INLINE ULONG ma_IAudioRenderClient_AddRef(ma_IAudioRenderClient* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13967 static MA_INLINE ULONG ma_IAudioRenderClient_Release(ma_IAudioRenderClient* pThis) { return pThis->lpVtbl->Release(pThis); }
13968 static MA_INLINE HRESULT ma_IAudioRenderClient_GetBuffer(ma_IAudioRenderClient* pThis, ma_uint32 numFramesRequested, BYTE** ppData) { return pThis->lpVtbl->GetBuffer(pThis, numFramesRequested, ppData); }
13969 static MA_INLINE HRESULT ma_IAudioRenderClient_ReleaseBuffer(ma_IAudioRenderClient* pThis, ma_uint32 numFramesWritten, DWORD dwFlags) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesWritten, dwFlags); }
13970 
13971 
13972 /* IAudioCaptureClient */
13973 typedef struct
13974 {
13975  /* IUnknown */
13976  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioCaptureClient* pThis, const IID* const riid, void** ppObject);
13977  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioCaptureClient* pThis);
13978  ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioCaptureClient* pThis);
13979 
13980  /* IAudioRenderClient */
13981  HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioCaptureClient* pThis, BYTE** ppData, ma_uint32* pNumFramesToRead, DWORD* pFlags, ma_uint64* pDevicePosition, ma_uint64* pQPCPosition);
13982  HRESULT (STDMETHODCALLTYPE * ReleaseBuffer) (ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead);
13983  HRESULT (STDMETHODCALLTYPE * GetNextPacketSize)(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket);
13984 } ma_IAudioCaptureClientVtbl;
13985 struct ma_IAudioCaptureClient
13986 {
13987  ma_IAudioCaptureClientVtbl* lpVtbl;
13988 };
13989 static MA_INLINE HRESULT ma_IAudioCaptureClient_QueryInterface(ma_IAudioCaptureClient* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
13990 static MA_INLINE ULONG ma_IAudioCaptureClient_AddRef(ma_IAudioCaptureClient* pThis) { return pThis->lpVtbl->AddRef(pThis); }
13991 static MA_INLINE ULONG ma_IAudioCaptureClient_Release(ma_IAudioCaptureClient* pThis) { return pThis->lpVtbl->Release(pThis); }
13992 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); }
13993 static MA_INLINE HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); }
13994 static MA_INLINE HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket) { return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); }
13995 
13996 #ifndef MA_WIN32_DESKTOP
13997 #include <mmdeviceapi.h>
13998 typedef struct ma_completion_handler_uwp ma_completion_handler_uwp;
13999 
14000 typedef struct
14001 {
14002  /* IUnknown */
14003  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_completion_handler_uwp* pThis, const IID* const riid, void** ppObject);
14004  ULONG (STDMETHODCALLTYPE * AddRef) (ma_completion_handler_uwp* pThis);
14005  ULONG (STDMETHODCALLTYPE * Release) (ma_completion_handler_uwp* pThis);
14006 
14007  /* IActivateAudioInterfaceCompletionHandler */
14008  HRESULT (STDMETHODCALLTYPE * ActivateCompleted)(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation);
14009 } ma_completion_handler_uwp_vtbl;
14010 struct ma_completion_handler_uwp
14011 {
14012  ma_completion_handler_uwp_vtbl* lpVtbl;
14013  MA_ATOMIC ma_uint32 counter;
14014  HANDLE hEvent;
14015 };
14016 
14017 static HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_QueryInterface(ma_completion_handler_uwp* pThis, const IID* const riid, void** ppObject)
14018 {
14019  /*
14020  We need to "implement" IAgileObject which is just an indicator that's used internally by WASAPI for some multithreading management. To
14021  "implement" this, we just make sure we return pThis when the IAgileObject is requested.
14022  */
14023  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)) {
14024  *ppObject = NULL;
14025  return E_NOINTERFACE;
14026  }
14027 
14028  /* Getting here means the IID is IUnknown or IMMNotificationClient. */
14029  *ppObject = (void*)pThis;
14030  ((ma_completion_handler_uwp_vtbl*)pThis->lpVtbl)->AddRef(pThis);
14031  return S_OK;
14032 }
14033 
14034 static ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_AddRef(ma_completion_handler_uwp* pThis)
14035 {
14036  return (ULONG)c89atomic_fetch_add_32(&pThis->counter, 1) + 1;
14037 }
14038 
14039 static ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_Release(ma_completion_handler_uwp* pThis)
14040 {
14041  ma_uint32 newRefCount = c89atomic_fetch_sub_32(&pThis->counter, 1) - 1;
14042  if (newRefCount == 0) {
14043  return 0; /* We don't free anything here because we never allocate the object on the heap. */
14044  }
14045 
14046  return (ULONG)newRefCount;
14047 }
14048 
14049 static HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_ActivateCompleted(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation)
14050 {
14051  (void)pActivateOperation;
14052  SetEvent(pThis->hEvent);
14053  return S_OK;
14054 }
14055 
14056 
14057 static ma_completion_handler_uwp_vtbl g_maCompletionHandlerVtblInstance = {
14058  ma_completion_handler_uwp_QueryInterface,
14059  ma_completion_handler_uwp_AddRef,
14060  ma_completion_handler_uwp_Release,
14061  ma_completion_handler_uwp_ActivateCompleted
14062 };
14063 
14064 static ma_result ma_completion_handler_uwp_init(ma_completion_handler_uwp* pHandler)
14065 {
14066  MA_ASSERT(pHandler != NULL);
14067  MA_ZERO_OBJECT(pHandler);
14068 
14069  pHandler->lpVtbl = &g_maCompletionHandlerVtblInstance;
14070  pHandler->counter = 1;
14071  pHandler->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
14072  if (pHandler->hEvent == NULL) {
14073  return ma_result_from_GetLastError(GetLastError());
14074  }
14075 
14076  return MA_SUCCESS;
14077 }
14078 
14079 static void ma_completion_handler_uwp_uninit(ma_completion_handler_uwp* pHandler)
14080 {
14081  if (pHandler->hEvent != NULL) {
14082  CloseHandle(pHandler->hEvent);
14083  }
14084 }
14085 
14086 static void ma_completion_handler_uwp_wait(ma_completion_handler_uwp* pHandler)
14087 {
14088  WaitForSingleObject(pHandler->hEvent, INFINITE);
14089 }
14090 #endif /* !MA_WIN32_DESKTOP */
14091 
14092 /* We need a virtual table for our notification client object that's used for detecting changes to the default device. */
14093 #ifdef MA_WIN32_DESKTOP
14094 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_QueryInterface(ma_IMMNotificationClient* pThis, const IID* const riid, void** ppObject)
14095 {
14096  /*
14097  We care about two interfaces - IUnknown and IMMNotificationClient. If the requested IID is something else
14098  we just return E_NOINTERFACE. Otherwise we need to increment the reference counter and return S_OK.
14099  */
14100  if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IMMNotificationClient)) {
14101  *ppObject = NULL;
14102  return E_NOINTERFACE;
14103  }
14104 
14105  /* Getting here means the IID is IUnknown or IMMNotificationClient. */
14106  *ppObject = (void*)pThis;
14107  ((ma_IMMNotificationClientVtbl*)pThis->lpVtbl)->AddRef(pThis);
14108  return S_OK;
14109 }
14110 
14111 static ULONG STDMETHODCALLTYPE ma_IMMNotificationClient_AddRef(ma_IMMNotificationClient* pThis)
14112 {
14113  return (ULONG)c89atomic_fetch_add_32(&pThis->counter, 1) + 1;
14114 }
14115 
14116 static ULONG STDMETHODCALLTYPE ma_IMMNotificationClient_Release(ma_IMMNotificationClient* pThis)
14117 {
14118  ma_uint32 newRefCount = c89atomic_fetch_sub_32(&pThis->counter, 1) - 1;
14119  if (newRefCount == 0) {
14120  return 0; /* We don't free anything here because we never allocate the object on the heap. */
14121  }
14122 
14123  return (ULONG)newRefCount;
14124 }
14125 
14126 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceStateChanged(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, DWORD dwNewState)
14127 {
14128  ma_bool32 isThisDevice = MA_FALSE;
14129  ma_bool32 isCapture = MA_FALSE;
14130  ma_bool32 isPlayback = MA_FALSE;
14131 
14132 #ifdef MA_DEBUG_OUTPUT
14133  /*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);*/
14134 #endif
14135 
14136  /*
14137  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
14138  that the device is disabled or has been unplugged.
14139  */
14140  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)) {
14141  isCapture = MA_TRUE;
14142  if (wcscmp(pThis->pDevice->capture.id.wasapi, pDeviceID) == 0) {
14143  isThisDevice = MA_TRUE;
14144  }
14145  }
14146 
14147  if (pThis->pDevice->wasapi.allowPlaybackAutoStreamRouting && (pThis->pDevice->type == ma_device_type_playback || pThis->pDevice->type == ma_device_type_duplex)) {
14148  isPlayback = MA_TRUE;
14149  if (wcscmp(pThis->pDevice->playback.id.wasapi, pDeviceID) == 0) {
14150  isThisDevice = MA_TRUE;
14151  }
14152  }
14153 
14154 
14155  /*
14156  If the device ID matches our device we need to mark our device as detached and stop it. When a
14157  device is added in OnDeviceAdded(), we'll restart it. We only mark it as detached if the device
14158  was started at the time of being removed.
14159  */
14160  if (isThisDevice) {
14161  if ((dwNewState & MA_MM_DEVICE_STATE_ACTIVE) == 0) {
14162  /*
14163  Unplugged or otherwise unavailable. Mark as detached if we were in a playing state. We'll
14164  use this to determine whether or not we need to automatically start the device when it's
14165  plugged back in again.
14166  */
14167  if (ma_device_get_state(pThis->pDevice) == MA_STATE_STARTED) {
14168  if (isPlayback) {
14169  pThis->pDevice->wasapi.isDetachedPlayback = MA_TRUE;
14170  }
14171  if (isCapture) {
14172  pThis->pDevice->wasapi.isDetachedCapture = MA_TRUE;
14173  }
14174 
14175  ma_device_stop(pThis->pDevice);
14176  }
14177  }
14178 
14179  if ((dwNewState & MA_MM_DEVICE_STATE_ACTIVE) != 0) {
14180  /* The device was activated. If we were detached, we need to start it again. */
14181  ma_bool8 tryRestartingDevice = MA_FALSE;
14182 
14183  if (isPlayback) {
14184  if (pThis->pDevice->wasapi.isDetachedPlayback) {
14185  pThis->pDevice->wasapi.isDetachedPlayback = MA_FALSE;
14186  ma_device_reroute__wasapi(pThis->pDevice, ma_device_type_playback);
14187  tryRestartingDevice = MA_TRUE;
14188  }
14189  }
14190 
14191  if (isCapture) {
14192  if (pThis->pDevice->wasapi.isDetachedCapture) {
14193  pThis->pDevice->wasapi.isDetachedCapture = MA_FALSE;
14194  ma_device_reroute__wasapi(pThis->pDevice, (pThis->pDevice->type == ma_device_type_loopback) ? ma_device_type_loopback : ma_device_type_capture);
14195  tryRestartingDevice = MA_TRUE;
14196  }
14197  }
14198 
14199  if (tryRestartingDevice) {
14200  if (pThis->pDevice->wasapi.isDetachedPlayback == MA_FALSE && pThis->pDevice->wasapi.isDetachedCapture == MA_FALSE) {
14201  ma_device_start(pThis->pDevice);
14202  }
14203  }
14204  }
14205  }
14206 
14207  return S_OK;
14208 }
14209 
14210 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceAdded(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID)
14211 {
14212 #ifdef MA_DEBUG_OUTPUT
14213  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDeviceAdded(pDeviceID=%S)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)");*/
14214 #endif
14215 
14216  /* We don't need to worry about this event for our purposes. */
14217  (void)pThis;
14218  (void)pDeviceID;
14219  return S_OK;
14220 }
14221 
14222 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceRemoved(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID)
14223 {
14224 #ifdef MA_DEBUG_OUTPUT
14225  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnDeviceRemoved(pDeviceID=%S)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)");*/
14226 #endif
14227 
14228  /* We don't need to worry about this event for our purposes. */
14229  (void)pThis;
14230  (void)pDeviceID;
14231  return S_OK;
14232 }
14233 
14234 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged(ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID)
14235 {
14236 #ifdef MA_DEBUG_OUTPUT
14237  /*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)");*/
14238 #endif
14239 
14240  /* We only ever use the eConsole role in miniaudio. */
14241  if (role != ma_eConsole) {
14242  ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting: role != eConsole\n");
14243  return S_OK;
14244  }
14245 
14246  /* We only care about devices with the same data flow and role as the current device. */
14247  if ((pThis->pDevice->type == ma_device_type_playback && dataFlow != ma_eRender) ||
14248  (pThis->pDevice->type == ma_device_type_capture && dataFlow != ma_eCapture)) {
14249  ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting abandoned because dataFlow does match device type.\n");
14250  return S_OK;
14251  }
14252 
14253  /* Don't do automatic stream routing if we're not allowed. */
14254  if ((dataFlow == ma_eRender && pThis->pDevice->wasapi.allowPlaybackAutoStreamRouting == MA_FALSE) ||
14255  (dataFlow == ma_eCapture && pThis->pDevice->wasapi.allowCaptureAutoStreamRouting == MA_FALSE)) {
14256  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");
14257  return S_OK;
14258  }
14259 
14260  /*
14261  Not currently supporting automatic stream routing in exclusive mode. This is not working correctly on my machine due to
14262  AUDCLNT_E_DEVICE_IN_USE errors when reinitializing the device. If this is a bug in miniaudio, we can try re-enabling this once
14263  it's fixed.
14264  */
14265  if ((dataFlow == ma_eRender && pThis->pDevice->playback.shareMode == ma_share_mode_exclusive) ||
14266  (dataFlow == ma_eCapture && pThis->pDevice->capture.shareMode == ma_share_mode_exclusive)) {
14267  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");
14268  return S_OK;
14269  }
14270 
14271 
14272 
14273 
14274  /*
14275  Second attempt at device rerouting. We're going to retrieve the device's state at the time of
14276  the route change. We're then going to stop the device, reinitialize the device, and then start
14277  it again if the state before stopping was MA_STATE_STARTED.
14278  */
14279  {
14280  ma_uint32 previousState = ma_device_get_state(pThis->pDevice);
14281  ma_bool8 restartDevice = MA_FALSE;
14282 
14283  if (previousState == MA_STATE_STARTED) {
14284  ma_device_stop(pThis->pDevice);
14285  restartDevice = MA_TRUE;
14286  }
14287 
14288  if (pDefaultDeviceID != NULL) { /* <-- The input device ID will be null if there's no other device available. */
14289  if (dataFlow == ma_eRender) {
14290  ma_device_reroute__wasapi(pThis->pDevice, ma_device_type_playback);
14291 
14292  if (pThis->pDevice->wasapi.isDetachedPlayback) {
14293  pThis->pDevice->wasapi.isDetachedPlayback = MA_FALSE;
14294 
14295  if (pThis->pDevice->type == ma_device_type_duplex && pThis->pDevice->wasapi.isDetachedCapture) {
14296  restartDevice = MA_FALSE; /* It's a duplex device and the capture side is detached. We cannot be restarting the device just yet. */
14297  } else {
14298  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. */
14299  }
14300  }
14301  } else {
14302  ma_device_reroute__wasapi(pThis->pDevice, (pThis->pDevice->type == ma_device_type_loopback) ? ma_device_type_loopback : ma_device_type_capture);
14303 
14304  if (pThis->pDevice->wasapi.isDetachedCapture) {
14305  pThis->pDevice->wasapi.isDetachedCapture = MA_FALSE;
14306 
14307  if (pThis->pDevice->type == ma_device_type_duplex && pThis->pDevice->wasapi.isDetachedPlayback) {
14308  restartDevice = MA_FALSE; /* It's a duplex device and the playback side is detached. We cannot be restarting the device just yet. */
14309  } else {
14310  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. */
14311  }
14312  }
14313  }
14314 
14315  if (restartDevice) {
14316  ma_device_start(pThis->pDevice);
14317  }
14318  }
14319  }
14320 
14321  return S_OK;
14322 }
14323 
14324 static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnPropertyValueChanged(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, const PROPERTYKEY key)
14325 {
14326 #ifdef MA_DEBUG_OUTPUT
14327  /*ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "IMMNotificationClient_OnPropertyValueChanged(pDeviceID=%S)\n", (pDeviceID != NULL) ? pDeviceID : L"(NULL)");*/
14328 #endif
14329 
14330  (void)pThis;
14331  (void)pDeviceID;
14332  (void)key;
14333  return S_OK;
14334 }
14335 
14336 static ma_IMMNotificationClientVtbl g_maNotificationCientVtbl = {
14337  ma_IMMNotificationClient_QueryInterface,
14338  ma_IMMNotificationClient_AddRef,
14339  ma_IMMNotificationClient_Release,
14340  ma_IMMNotificationClient_OnDeviceStateChanged,
14341  ma_IMMNotificationClient_OnDeviceAdded,
14342  ma_IMMNotificationClient_OnDeviceRemoved,
14343  ma_IMMNotificationClient_OnDefaultDeviceChanged,
14344  ma_IMMNotificationClient_OnPropertyValueChanged
14345 };
14346 #endif /* MA_WIN32_DESKTOP */
14347 
14348 #ifdef MA_WIN32_DESKTOP
14349 typedef ma_IMMDevice ma_WASAPIDeviceInterface;
14350 #else
14351 typedef ma_IUnknown ma_WASAPIDeviceInterface;
14352 #endif
14353 
14354 
14355 #define MA_CONTEXT_COMMAND_QUIT__WASAPI 1
14356 #define MA_CONTEXT_COMMAND_CREATE_IAUDIOCLIENT__WASAPI 2
14357 #define MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI 3
14358 
14359 static ma_context_command__wasapi ma_context_init_command__wasapi(int code)
14360 {
14362 
14363  MA_ZERO_OBJECT(&cmd);
14364  cmd.code = code;
14365 
14366  return cmd;
14367 }
14368 
14369 static ma_result ma_context_post_command__wasapi(ma_context* pContext, const ma_context_command__wasapi* pCmd)
14370 {
14371  /* For now we are doing everything synchronously, but I might relax this later if the need arises. */
14372  ma_result result;
14373  ma_bool32 isUsingLocalEvent = MA_FALSE;
14374  ma_event localEvent;
14375 
14376  MA_ASSERT(pContext != NULL);
14377  MA_ASSERT(pCmd != NULL);
14378 
14379  if (pCmd->pEvent == NULL) {
14380  isUsingLocalEvent = MA_TRUE;
14381 
14382  result = ma_event_init(&localEvent);
14383  if (result != MA_SUCCESS) {
14384  return result; /* Failed to create the event for this command. */
14385  }
14386  }
14387 
14388  /* Here is where we add the command to the list. If there's not enough room we'll spin until there is. */
14389  ma_mutex_lock(&pContext->wasapi.commandLock);
14390  {
14391  ma_uint32 index;
14392 
14393  /* Spin until we've got some space available. */
14394  while (pContext->wasapi.commandCount == ma_countof(pContext->wasapi.commands)) {
14395  ma_yield();
14396  }
14397 
14398  /* Space is now available. Can safely add to the list. */
14399  index = (pContext->wasapi.commandIndex + pContext->wasapi.commandCount) % ma_countof(pContext->wasapi.commands);
14400  pContext->wasapi.commands[index] = *pCmd;
14401  pContext->wasapi.commands[index].pEvent = &localEvent;
14402  pContext->wasapi.commandCount += 1;
14403 
14404  /* Now that the command has been added, release the semaphore so ma_context_next_command__wasapi() can return. */
14405  ma_semaphore_release(&pContext->wasapi.commandSem);
14406  }
14407  ma_mutex_unlock(&pContext->wasapi.commandLock);
14408 
14409  if (isUsingLocalEvent) {
14410  ma_event_wait(&localEvent);
14411  ma_event_uninit(&localEvent);
14412  }
14413 
14414  return MA_SUCCESS;
14415 }
14416 
14417 static ma_result ma_context_next_command__wasapi(ma_context* pContext, ma_context_command__wasapi* pCmd)
14418 {
14419  ma_result result = MA_SUCCESS;
14420 
14421  MA_ASSERT(pContext != NULL);
14422  MA_ASSERT(pCmd != NULL);
14423 
14424  result = ma_semaphore_wait(&pContext->wasapi.commandSem);
14425  if (result == MA_SUCCESS) {
14426  ma_mutex_lock(&pContext->wasapi.commandLock);
14427  {
14428  *pCmd = pContext->wasapi.commands[pContext->wasapi.commandIndex];
14429  pContext->wasapi.commandIndex = (pContext->wasapi.commandIndex + 1) % ma_countof(pContext->wasapi.commands);
14430  pContext->wasapi.commandCount -= 1;
14431  }
14432  ma_mutex_unlock(&pContext->wasapi.commandLock);
14433  }
14434 
14435  return result;
14436 }
14437 
14438 static ma_thread_result MA_THREADCALL ma_context_command_thread__wasapi(void* pUserData)
14439 {
14440  ma_result result;
14441  ma_context* pContext = (ma_context*)pUserData;
14442  MA_ASSERT(pContext != NULL);
14443 
14444  for (;;) {
14446  result = ma_context_next_command__wasapi(pContext, &cmd);
14447  if (result != MA_SUCCESS) {
14448  break;
14449  }
14450 
14451  switch (cmd.code)
14452  {
14453  case MA_CONTEXT_COMMAND_QUIT__WASAPI:
14454  {
14455  /* Do nothing. Handled after the switch. */
14456  } break;
14457 
14458  case MA_CONTEXT_COMMAND_CREATE_IAUDIOCLIENT__WASAPI:
14459  {
14460  if (cmd.data.createAudioClient.deviceType == ma_device_type_playback) {
14461  *cmd.data.createAudioClient.pResult = ma_result_from_HRESULT(ma_IAudioClient_GetService((ma_IAudioClient*)cmd.data.createAudioClient.pAudioClient, &MA_IID_IAudioRenderClient, cmd.data.createAudioClient.ppAudioClientService));
14462  } else {
14463  *cmd.data.createAudioClient.pResult = ma_result_from_HRESULT(ma_IAudioClient_GetService((ma_IAudioClient*)cmd.data.createAudioClient.pAudioClient, &MA_IID_IAudioCaptureClient, cmd.data.createAudioClient.ppAudioClientService));
14464  }
14465  } break;
14466 
14467  case MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI:
14468  {
14469  if (cmd.data.releaseAudioClient.deviceType == ma_device_type_playback) {
14470  if (cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientPlayback != NULL) {
14471  ma_IAudioClient_Release((ma_IAudioClient*)cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientPlayback);
14472  cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientPlayback = NULL;
14473  }
14474  }
14475 
14476  if (cmd.data.releaseAudioClient.deviceType == ma_device_type_capture) {
14477  if (cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientCapture != NULL) {
14478  ma_IAudioClient_Release((ma_IAudioClient*)cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientCapture);
14479  cmd.data.releaseAudioClient.pDevice->wasapi.pAudioClientCapture = NULL;
14480  }
14481  }
14482  } break;
14483 
14484  default:
14485  {
14486  /* Unknown command. Ignore it, but trigger an assert in debug mode so we're aware of it. */
14488  } break;
14489  }
14490 
14491  if (cmd.pEvent != NULL) {
14492  ma_event_signal(cmd.pEvent);
14493  }
14494 
14495  if (cmd.code == MA_CONTEXT_COMMAND_QUIT__WASAPI) {
14496  break; /* Received a quit message. Get out of here. */
14497  }
14498  }
14499 
14500  return (ma_thread_result)0;
14501 }
14502 
14503 static ma_result ma_device_create_IAudioClient_service__wasapi(ma_context* pContext, ma_device_type deviceType, ma_IAudioClient* pAudioClient, void** ppAudioClientService)
14504 {
14505  ma_result result;
14506  ma_result cmdResult;
14507  ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_CREATE_IAUDIOCLIENT__WASAPI);
14508  cmd.data.createAudioClient.deviceType = deviceType;
14509  cmd.data.createAudioClient.pAudioClient = (void*)pAudioClient;
14510  cmd.data.createAudioClient.ppAudioClientService = ppAudioClientService;
14511  cmd.data.createAudioClient.pResult = &cmdResult; /* Declared locally, but won't be dereferenced after this function returns since execution of the command will wait here. */
14512 
14513  result = ma_context_post_command__wasapi(pContext, &cmd); /* This will not return until the command has actually been run. */
14514  if (result != MA_SUCCESS) {
14515  return result;
14516  }
14517 
14518  return *cmd.data.createAudioClient.pResult;
14519 }
14520 
14521 #if 0 /* Not used at the moment, but leaving here for future use. */
14522 static ma_result ma_device_release_IAudioClient_service__wasapi(ma_device* pDevice, ma_device_type deviceType)
14523 {
14524  ma_result result;
14525  ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI);
14526  cmd.data.releaseAudioClient.pDevice = pDevice;
14527  cmd.data.releaseAudioClient.deviceType = deviceType;
14528 
14529  result = ma_context_post_command__wasapi(pDevice->pContext, &cmd); /* This will not return until the command has actually been run. */
14530  if (result != MA_SUCCESS) {
14531  return result;
14532  }
14533 
14534  return MA_SUCCESS;
14535 }
14536 #endif
14537 
14538 
14539 static void ma_add_native_data_format_to_device_info_from_WAVEFORMATEX(const WAVEFORMATEX* pWF, ma_share_mode shareMode, ma_device_info* pInfo)
14540 {
14541  MA_ASSERT(pWF != NULL);
14542  MA_ASSERT(pInfo != NULL);
14543 
14544  if (pInfo->nativeDataFormatCount >= ma_countof(pInfo->nativeDataFormats)) {
14545  return; /* Too many data formats. Need to ignore this one. Don't think this should ever happen with WASAPI. */
14546  }
14547 
14548  pInfo->nativeDataFormats[pInfo->nativeDataFormatCount].format = ma_format_from_WAVEFORMATEX(pWF);
14549  pInfo->nativeDataFormats[pInfo->nativeDataFormatCount].channels = pWF->nChannels;
14550  pInfo->nativeDataFormats[pInfo->nativeDataFormatCount].sampleRate = pWF->nSamplesPerSec;
14552  pInfo->nativeDataFormatCount += 1;
14553 }
14554 
14555 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)
14556 {
14557  HRESULT hr;
14558  WAVEFORMATEX* pWF = NULL;
14559 
14560  MA_ASSERT(pAudioClient != NULL);
14561  MA_ASSERT(pInfo != NULL);
14562 
14563  /* Shared Mode. We use GetMixFormat() here. */
14564  hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pAudioClient, (WAVEFORMATEX**)&pWF);
14565  if (SUCCEEDED(hr)) {
14566  ma_add_native_data_format_to_device_info_from_WAVEFORMATEX(pWF, ma_share_mode_shared, pInfo);
14567  } else {
14568  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));
14569  }
14570 
14571  /*
14572  Exlcusive Mode. We repeatedly call IsFormatSupported() here. This is not currently supported on
14573  UWP. Failure to retrieve the exclusive mode format is not considered an error, so from here on
14574  out, MA_SUCCESS is guaranteed to be returned.
14575  */
14576  #ifdef MA_WIN32_DESKTOP
14577  {
14578  ma_IPropertyStore *pProperties;
14579 
14580  /*
14581  The first thing to do is get the format from PKEY_AudioEngine_DeviceFormat. This should give us a channel count we assume is
14582  correct which will simplify our searching.
14583  */
14584  hr = ma_IMMDevice_OpenPropertyStore((ma_IMMDevice*)pMMDevice, STGM_READ, &pProperties);
14585  if (SUCCEEDED(hr)) {
14586  PROPVARIANT var;
14587  ma_PropVariantInit(&var);
14588 
14589  hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_AudioEngine_DeviceFormat, &var);
14590  if (SUCCEEDED(hr)) {
14591  pWF = (WAVEFORMATEX*)var.blob.pBlobData;
14592 
14593  /*
14594  In my testing, the format returned by PKEY_AudioEngine_DeviceFormat is suitable for exclusive mode so we check this format
14595  first. If this fails, fall back to a search.
14596  */
14597  hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pWF, NULL);
14598  if (SUCCEEDED(hr)) {
14599  /* The format returned by PKEY_AudioEngine_DeviceFormat is supported. */
14600  ma_add_native_data_format_to_device_info_from_WAVEFORMATEX(pWF, ma_share_mode_exclusive, pInfo);
14601  } else {
14602  /*
14603  The format returned by PKEY_AudioEngine_DeviceFormat is not supported, so fall back to a search. We assume the channel
14604  count returned by MA_PKEY_AudioEngine_DeviceFormat is valid and correct. For simplicity we're only returning one format.
14605  */
14606  ma_uint32 channels = pInfo->minChannels;
14607  ma_channel defaultChannelMap[MA_MAX_CHANNELS];
14608  WAVEFORMATEXTENSIBLE wf;
14609  ma_bool32 found;
14610  ma_uint32 iFormat;
14611 
14612  /* Make sure we don't overflow the channel map. */
14613  if (channels > MA_MAX_CHANNELS) {
14614  channels = MA_MAX_CHANNELS;
14615  }
14616 
14617  ma_get_standard_channel_map(ma_standard_channel_map_microsoft, channels, defaultChannelMap);
14618 
14619  MA_ZERO_OBJECT(&wf);
14620  wf.Format.cbSize = sizeof(wf);
14621  wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
14622  wf.Format.nChannels = (WORD)channels;
14623  wf.dwChannelMask = ma_channel_map_to_channel_mask__win32(defaultChannelMap, channels);
14624 
14625  found = MA_FALSE;
14626  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); ++iFormat) {
14627  ma_format format = g_maFormatPriorities[iFormat];
14628  ma_uint32 iSampleRate;
14629 
14630  wf.Format.wBitsPerSample = (WORD)(ma_get_bytes_per_sample(format)*8);
14631  wf.Format.nBlockAlign = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
14632  wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
14633  wf.Samples.wValidBitsPerSample = /*(format == ma_format_s24_32) ? 24 :*/ wf.Format.wBitsPerSample;
14634  if (format == ma_format_f32) {
14635  wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
14636  } else {
14637  wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
14638  }
14639 
14640  for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iSampleRate) {
14641  wf.Format.nSamplesPerSec = g_maStandardSampleRatePriorities[iSampleRate];
14642 
14643  hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, (WAVEFORMATEX*)&wf, NULL);
14644  if (SUCCEEDED(hr)) {
14645  ma_add_native_data_format_to_device_info_from_WAVEFORMATEX((WAVEFORMATEX*)&wf, ma_share_mode_exclusive, pInfo);
14646  found = MA_TRUE;
14647  break;
14648  }
14649  }
14650 
14651  if (found) {
14652  break;
14653  }
14654  }
14655 
14656  ma_PropVariantClear(pContext, &var);
14657 
14658  if (!found) {
14659  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);
14660  }
14661  }
14662  } else {
14663  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));
14664  }
14665 
14666  ma_IPropertyStore_Release(pProperties);
14667  } else {
14668  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));
14669  }
14670  }
14671  #endif
14672 
14673  return MA_SUCCESS;
14674 }
14675 
14676 #ifdef MA_WIN32_DESKTOP
14677 static ma_EDataFlow ma_device_type_to_EDataFlow(ma_device_type deviceType)
14678 {
14679  if (deviceType == ma_device_type_playback) {
14680  return ma_eRender;
14681  } else if (deviceType == ma_device_type_capture) {
14682  return ma_eCapture;
14683  } else {
14685  return ma_eRender; /* Should never hit this. */
14686  }
14687 }
14688 
14689 static ma_result ma_context_create_IMMDeviceEnumerator__wasapi(ma_context* pContext, ma_IMMDeviceEnumerator** ppDeviceEnumerator)
14690 {
14691  HRESULT hr;
14692  ma_IMMDeviceEnumerator* pDeviceEnumerator;
14693 
14694  MA_ASSERT(pContext != NULL);
14695  MA_ASSERT(ppDeviceEnumerator != NULL);
14696 
14697  *ppDeviceEnumerator = NULL; /* Safety. */
14698 
14699  hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
14700  if (FAILED(hr)) {
14701  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
14702  }
14703 
14704  *ppDeviceEnumerator = pDeviceEnumerator;
14705 
14706  return MA_SUCCESS;
14707 }
14708 
14709 static LPWSTR ma_context_get_default_device_id_from_IMMDeviceEnumerator__wasapi(ma_context* pContext, ma_IMMDeviceEnumerator* pDeviceEnumerator, ma_device_type deviceType)
14710 {
14711  HRESULT hr;
14712  ma_IMMDevice* pMMDefaultDevice = NULL;
14713  LPWSTR pDefaultDeviceID = NULL;
14714  ma_EDataFlow dataFlow;
14715  ma_ERole role;
14716 
14717  MA_ASSERT(pContext != NULL);
14718  MA_ASSERT(pDeviceEnumerator != NULL);
14719 
14720  (void)pContext;
14721 
14722  /* Grab the EDataFlow type from the device type. */
14723  dataFlow = ma_device_type_to_EDataFlow(deviceType);
14724 
14725  /* The role is always eConsole, but we may make this configurable later. */
14726  role = ma_eConsole;
14727 
14728  hr = ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(pDeviceEnumerator, dataFlow, role, &pMMDefaultDevice);
14729  if (FAILED(hr)) {
14730  return NULL;
14731  }
14732 
14733  hr = ma_IMMDevice_GetId(pMMDefaultDevice, &pDefaultDeviceID);
14734 
14735  ma_IMMDevice_Release(pMMDefaultDevice);
14736  pMMDefaultDevice = NULL;
14737 
14738  if (FAILED(hr)) {
14739  return NULL;
14740  }
14741 
14742  return pDefaultDeviceID;
14743 }
14744 
14745 static LPWSTR ma_context_get_default_device_id__wasapi(ma_context* pContext, ma_device_type deviceType) /* Free the returned pointer with ma_CoTaskMemFree() */
14746 {
14747  ma_result result;
14748  ma_IMMDeviceEnumerator* pDeviceEnumerator;
14749  LPWSTR pDefaultDeviceID = NULL;
14750 
14751  MA_ASSERT(pContext != NULL);
14752 
14753  result = ma_context_create_IMMDeviceEnumerator__wasapi(pContext, &pDeviceEnumerator);
14754  if (result != MA_SUCCESS) {
14755  return NULL;
14756  }
14757 
14758  pDefaultDeviceID = ma_context_get_default_device_id_from_IMMDeviceEnumerator__wasapi(pContext, pDeviceEnumerator, deviceType);
14759 
14760  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
14761  return pDefaultDeviceID;
14762 }
14763 
14764 static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_IMMDevice** ppMMDevice)
14765 {
14766  ma_IMMDeviceEnumerator* pDeviceEnumerator;
14767  HRESULT hr;
14768 
14769  MA_ASSERT(pContext != NULL);
14770  MA_ASSERT(ppMMDevice != NULL);
14771 
14772  hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
14773  if (FAILED(hr)) {
14774  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.", ma_result_from_HRESULT(hr));
14775  }
14776 
14777  if (pDeviceID == NULL) {
14778  hr = ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(pDeviceEnumerator, (deviceType == ma_device_type_capture) ? ma_eCapture : ma_eRender, ma_eConsole, ppMMDevice);
14779  } else {
14780  hr = ma_IMMDeviceEnumerator_GetDevice(pDeviceEnumerator, pDeviceID->wasapi, ppMMDevice);
14781  }
14782 
14783  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
14784  if (FAILED(hr)) {
14785  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve IMMDevice.", ma_result_from_HRESULT(hr));
14786  }
14787 
14788  return MA_SUCCESS;
14789 }
14790 
14791 static ma_result ma_context_get_device_id_from_MMDevice__wasapi(ma_context* pContext, ma_IMMDevice* pMMDevice, ma_device_id* pDeviceID)
14792 {
14793  LPWSTR pDeviceIDString;
14794  HRESULT hr;
14795 
14796  MA_ASSERT(pDeviceID != NULL);
14797 
14798  hr = ma_IMMDevice_GetId(pMMDevice, &pDeviceIDString);
14799  if (SUCCEEDED(hr)) {
14800  size_t idlen = wcslen(pDeviceIDString);
14801  if (idlen+1 > ma_countof(pDeviceID->wasapi)) {
14802  ma_CoTaskMemFree(pContext, pDeviceIDString);
14803  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. */
14804  return MA_ERROR;
14805  }
14806 
14807  MA_COPY_MEMORY(pDeviceID->wasapi, pDeviceIDString, idlen * sizeof(wchar_t));
14808  pDeviceID->wasapi[idlen] = '\0';
14809 
14810  ma_CoTaskMemFree(pContext, pDeviceIDString);
14811 
14812  return MA_SUCCESS;
14813  }
14814 
14815  return MA_ERROR;
14816 }
14817 
14818 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)
14819 {
14820  ma_result result;
14821  HRESULT hr;
14822 
14823  MA_ASSERT(pContext != NULL);
14824  MA_ASSERT(pMMDevice != NULL);
14825  MA_ASSERT(pInfo != NULL);
14826 
14827  /* ID. */
14828  result = ma_context_get_device_id_from_MMDevice__wasapi(pContext, pMMDevice, &pInfo->id);
14829  if (result == MA_SUCCESS) {
14830  if (pDefaultDeviceID != NULL) {
14831  if (wcscmp(pInfo->id.wasapi, pDefaultDeviceID) == 0) {
14832  pInfo->isDefault = MA_TRUE;
14833  }
14834  }
14835  }
14836 
14837  /* Description / Friendly Name */
14838  {
14839  ma_IPropertyStore *pProperties;
14840  hr = ma_IMMDevice_OpenPropertyStore(pMMDevice, STGM_READ, &pProperties);
14841  if (SUCCEEDED(hr)) {
14842  PROPVARIANT var;
14843 
14844  ma_PropVariantInit(&var);
14845  hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &var);
14846  if (SUCCEEDED(hr)) {
14847  WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, pInfo->name, sizeof(pInfo->name), 0, FALSE);
14848  ma_PropVariantClear(pContext, &var);
14849  }
14850 
14851  ma_IPropertyStore_Release(pProperties);
14852  }
14853  }
14854 
14855  /* Format */
14856  if (!onlySimpleInfo) {
14857  ma_IAudioClient* pAudioClient;
14858  hr = ma_IMMDevice_Activate(pMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
14859  if (SUCCEEDED(hr)) {
14860  result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext, pMMDevice, pAudioClient, pInfo);
14861 
14862  ma_IAudioClient_Release(pAudioClient);
14863  return result;
14864  } else {
14865  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));
14866  }
14867  }
14868 
14869  return MA_SUCCESS;
14870 }
14871 
14872 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)
14873 {
14874  ma_result result = MA_SUCCESS;
14875  UINT deviceCount;
14876  HRESULT hr;
14877  ma_uint32 iDevice;
14878  LPWSTR pDefaultDeviceID = NULL;
14879  ma_IMMDeviceCollection* pDeviceCollection = NULL;
14880 
14881  MA_ASSERT(pContext != NULL);
14882  MA_ASSERT(callback != NULL);
14883 
14884  /* Grab the default device. We use this to know whether or not flag the returned device info as being the default. */
14885  pDefaultDeviceID = ma_context_get_default_device_id_from_IMMDeviceEnumerator__wasapi(pContext, pDeviceEnumerator, deviceType);
14886 
14887  /* We need to enumerate the devices which returns a device collection. */
14888  hr = ma_IMMDeviceEnumerator_EnumAudioEndpoints(pDeviceEnumerator, ma_device_type_to_EDataFlow(deviceType), MA_MM_DEVICE_STATE_ACTIVE, &pDeviceCollection);
14889  if (SUCCEEDED(hr)) {
14890  hr = ma_IMMDeviceCollection_GetCount(pDeviceCollection, &deviceCount);
14891  if (FAILED(hr)) {
14892  result = ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to get device count.", ma_result_from_HRESULT(hr));
14893  goto done;
14894  }
14895 
14896  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
14897  ma_device_info deviceInfo;
14898  ma_IMMDevice* pMMDevice;
14899 
14900  MA_ZERO_OBJECT(&deviceInfo);
14901 
14902  hr = ma_IMMDeviceCollection_Item(pDeviceCollection, iDevice, &pMMDevice);
14903  if (SUCCEEDED(hr)) {
14904  result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, pDefaultDeviceID, MA_TRUE, &deviceInfo); /* MA_TRUE = onlySimpleInfo. */
14905 
14906  ma_IMMDevice_Release(pMMDevice);
14907  if (result == MA_SUCCESS) {
14908  ma_bool32 cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
14909  if (cbResult == MA_FALSE) {
14910  break;
14911  }
14912  }
14913  }
14914  }
14915  }
14916 
14917 done:
14918  if (pDefaultDeviceID != NULL) {
14919  ma_CoTaskMemFree(pContext, pDefaultDeviceID);
14920  pDefaultDeviceID = NULL;
14921  }
14922 
14923  if (pDeviceCollection != NULL) {
14924  ma_IMMDeviceCollection_Release(pDeviceCollection);
14925  pDeviceCollection = NULL;
14926  }
14927 
14928  return result;
14929 }
14930 
14931 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)
14932 {
14933  ma_result result;
14934  HRESULT hr;
14935 
14936  MA_ASSERT(pContext != NULL);
14937  MA_ASSERT(ppAudioClient != NULL);
14938  MA_ASSERT(ppMMDevice != NULL);
14939 
14940  result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, ppMMDevice);
14941  if (result != MA_SUCCESS) {
14942  return result;
14943  }
14944 
14945  hr = ma_IMMDevice_Activate(*ppMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)ppAudioClient);
14946  if (FAILED(hr)) {
14947  return ma_result_from_HRESULT(hr);
14948  }
14949 
14950  return MA_SUCCESS;
14951 }
14952 #else
14953 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)
14954 {
14955  ma_IActivateAudioInterfaceAsyncOperation *pAsyncOp = NULL;
14956  ma_completion_handler_uwp completionHandler;
14957  IID iid;
14958  LPOLESTR iidStr;
14959  HRESULT hr;
14960  ma_result result;
14961  HRESULT activateResult;
14962  ma_IUnknown* pActivatedInterface;
14963 
14964  MA_ASSERT(pContext != NULL);
14965  MA_ASSERT(ppAudioClient != NULL);
14966 
14967  if (pDeviceID != NULL) {
14968  MA_COPY_MEMORY(&iid, pDeviceID->wasapi, sizeof(iid));
14969  } else {
14970  if (deviceType == ma_device_type_playback) {
14971  iid = MA_IID_DEVINTERFACE_AUDIO_RENDER;
14972  } else {
14973  iid = MA_IID_DEVINTERFACE_AUDIO_CAPTURE;
14974  }
14975  }
14976 
14977 #if defined(__cplusplus)
14978  hr = StringFromIID(iid, &iidStr);
14979 #else
14980  hr = StringFromIID(&iid, &iidStr);
14981 #endif
14982  if (FAILED(hr)) {
14983  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));
14984  }
14985 
14986  result = ma_completion_handler_uwp_init(&completionHandler);
14987  if (result != MA_SUCCESS) {
14988  ma_CoTaskMemFree(pContext, iidStr);
14989  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for waiting for ActivateAudioInterfaceAsync().", result);
14990  }
14991 
14992 #if defined(__cplusplus)
14993  hr = ActivateAudioInterfaceAsync(iidStr, MA_IID_IAudioClient, NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
14994 #else
14995  hr = ActivateAudioInterfaceAsync(iidStr, &MA_IID_IAudioClient, NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
14996 #endif
14997  if (FAILED(hr)) {
14998  ma_completion_handler_uwp_uninit(&completionHandler);
14999  ma_CoTaskMemFree(pContext, iidStr);
15000  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] ActivateAudioInterfaceAsync() failed.", ma_result_from_HRESULT(hr));
15001  }
15002 
15003  ma_CoTaskMemFree(pContext, iidStr);
15004 
15005  /* Wait for the async operation for finish. */
15006  ma_completion_handler_uwp_wait(&completionHandler);
15007  ma_completion_handler_uwp_uninit(&completionHandler);
15008 
15009  hr = ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(pAsyncOp, &activateResult, &pActivatedInterface);
15010  ma_IActivateAudioInterfaceAsyncOperation_Release(pAsyncOp);
15011 
15012  if (FAILED(hr) || FAILED(activateResult)) {
15013  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));
15014  }
15015 
15016  /* Here is where we grab the IAudioClient interface. */
15017  hr = ma_IUnknown_QueryInterface(pActivatedInterface, &MA_IID_IAudioClient, (void**)ppAudioClient);
15018  if (FAILED(hr)) {
15019  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to query IAudioClient interface.", ma_result_from_HRESULT(hr));
15020  }
15021 
15022  if (ppActivatedInterface) {
15023  *ppActivatedInterface = pActivatedInterface;
15024  } else {
15025  ma_IUnknown_Release(pActivatedInterface);
15026  }
15027 
15028  return MA_SUCCESS;
15029 }
15030 #endif
15031 
15032 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)
15033 {
15034 #ifdef MA_WIN32_DESKTOP
15035  return ma_context_get_IAudioClient_Desktop__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
15036 #else
15037  return ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
15038 #endif
15039 }
15040 
15041 
15042 static ma_result ma_context_enumerate_devices__wasapi(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
15043 {
15044  /* Different enumeration for desktop and UWP. */
15045 #ifdef MA_WIN32_DESKTOP
15046  /* Desktop */
15047  HRESULT hr;
15048  ma_IMMDeviceEnumerator* pDeviceEnumerator;
15049 
15050  hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
15051  if (FAILED(hr)) {
15052  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
15053  }
15054 
15055  ma_context_enumerate_devices_by_type__wasapi(pContext, pDeviceEnumerator, ma_device_type_playback, callback, pUserData);
15056  ma_context_enumerate_devices_by_type__wasapi(pContext, pDeviceEnumerator, ma_device_type_capture, callback, pUserData);
15057 
15058  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
15059 #else
15060  /*
15061  UWP
15062 
15063  The MMDevice API is only supported on desktop applications. For now, while I'm still figuring out how to properly enumerate
15064  over devices without using MMDevice, I'm restricting devices to defaults.
15065 
15066  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/
15067  */
15068  if (callback) {
15069  ma_bool32 cbResult = MA_TRUE;
15070 
15071  /* Playback. */
15072  if (cbResult) {
15073  ma_device_info deviceInfo;
15074  MA_ZERO_OBJECT(&deviceInfo);
15075  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
15076  deviceInfo.isDefault = MA_TRUE;
15077  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
15078  }
15079 
15080  /* Capture. */
15081  if (cbResult) {
15082  ma_device_info deviceInfo;
15083  MA_ZERO_OBJECT(&deviceInfo);
15084  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
15085  deviceInfo.isDefault = MA_TRUE;
15086  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
15087  }
15088  }
15089 #endif
15090 
15091  return MA_SUCCESS;
15092 }
15093 
15094 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)
15095 {
15096 #ifdef MA_WIN32_DESKTOP
15097  ma_result result;
15098  ma_IMMDevice* pMMDevice = NULL;
15099  LPWSTR pDefaultDeviceID = NULL;
15100 
15101  result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, &pMMDevice);
15102  if (result != MA_SUCCESS) {
15103  return result;
15104  }
15105 
15106  /* We need the default device ID so we can set the isDefault flag in the device info. */
15107  pDefaultDeviceID = ma_context_get_default_device_id__wasapi(pContext, deviceType);
15108 
15109  result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, pDefaultDeviceID, MA_FALSE, pDeviceInfo); /* MA_FALSE = !onlySimpleInfo. */
15110 
15111  if (pDefaultDeviceID != NULL) {
15112  ma_CoTaskMemFree(pContext, pDefaultDeviceID);
15113  pDefaultDeviceID = NULL;
15114  }
15115 
15116  ma_IMMDevice_Release(pMMDevice);
15117 
15118  return result;
15119 #else
15120  ma_IAudioClient* pAudioClient;
15121  ma_result result;
15122 
15123  /* UWP currently only uses default devices. */
15124  if (deviceType == ma_device_type_playback) {
15125  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
15126  } else {
15127  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
15128  }
15129 
15130  result = ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, &pAudioClient, NULL);
15131  if (result != MA_SUCCESS) {
15132  return result;
15133  }
15134 
15135  result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext, NULL, pAudioClient, pDeviceInfo);
15136 
15137  pDeviceInfo->isDefault = MA_TRUE; /* UWP only supports default devices. */
15138 
15139  ma_IAudioClient_Release(pAudioClient);
15140  return result;
15141 #endif
15142 }
15143 
15144 static ma_result ma_device_uninit__wasapi(ma_device* pDevice)
15145 {
15146  MA_ASSERT(pDevice != NULL);
15147 
15148 #ifdef MA_WIN32_DESKTOP
15149  if (pDevice->wasapi.pDeviceEnumerator) {
15150  ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient);
15151  ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator);
15152  }
15153 #endif
15154 
15155  if (pDevice->wasapi.pRenderClient) {
15156  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
15157  }
15158  if (pDevice->wasapi.pCaptureClient) {
15159  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
15160  }
15161 
15162  if (pDevice->wasapi.pAudioClientPlayback) {
15163  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
15164  }
15165  if (pDevice->wasapi.pAudioClientCapture) {
15166  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
15167  }
15168 
15169  if (pDevice->wasapi.hEventPlayback) {
15170  CloseHandle(pDevice->wasapi.hEventPlayback);
15171  }
15172  if (pDevice->wasapi.hEventCapture) {
15173  CloseHandle(pDevice->wasapi.hEventCapture);
15174  }
15175 
15176  return MA_SUCCESS;
15177 }
15178 
15179 
15180 typedef struct
15181 {
15182  /* Input. */
15183  ma_format formatIn;
15184  ma_uint32 channelsIn;
15185  ma_uint32 sampleRateIn;
15186  ma_channel channelMapIn[MA_MAX_CHANNELS];
15187  ma_uint32 periodSizeInFramesIn;
15188  ma_uint32 periodSizeInMillisecondsIn;
15189  ma_uint32 periodsIn;
15190  ma_share_mode shareMode;
15191  ma_performance_profile performanceProfile;
15192  ma_bool32 noAutoConvertSRC;
15193  ma_bool32 noDefaultQualitySRC;
15194  ma_bool32 noHardwareOffloading;
15195 
15196  /* Output. */
15197  ma_IAudioClient* pAudioClient;
15198  ma_IAudioRenderClient* pRenderClient;
15199  ma_IAudioCaptureClient* pCaptureClient;
15200  ma_format formatOut;
15201  ma_uint32 channelsOut;
15202  ma_uint32 sampleRateOut;
15203  ma_channel channelMapOut[MA_MAX_CHANNELS];
15204  ma_uint32 periodSizeInFramesOut;
15205  ma_uint32 periodsOut;
15206  ma_bool32 usingAudioClient3;
15207  char deviceName[256];
15208  ma_device_id id;
15209 } ma_device_init_internal_data__wasapi;
15210 
15211 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)
15212 {
15213  HRESULT hr;
15214  ma_result result = MA_SUCCESS;
15215  const char* errorMsg = "";
15216  MA_AUDCLNT_SHAREMODE shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
15217  DWORD streamFlags = 0;
15218  MA_REFERENCE_TIME periodDurationInMicroseconds;
15219  ma_bool32 wasInitializedUsingIAudioClient3 = MA_FALSE;
15220  WAVEFORMATEXTENSIBLE wf;
15221  ma_WASAPIDeviceInterface* pDeviceInterface = NULL;
15222  ma_IAudioClient2* pAudioClient2;
15223  ma_uint32 nativeSampleRate;
15224 
15225  MA_ASSERT(pContext != NULL);
15226  MA_ASSERT(pData != NULL);
15227 
15228  /* This function is only used to initialize one device type: either playback, capture or loopback. Never full-duplex. */
15229  if (deviceType == ma_device_type_duplex) {
15230  return MA_INVALID_ARGS;
15231  }
15232 
15233  pData->pAudioClient = NULL;
15234  pData->pRenderClient = NULL;
15235  pData->pCaptureClient = NULL;
15236 
15237  streamFlags = MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
15238  if (!pData->noAutoConvertSRC && pData->sampleRateIn != 0 && pData->shareMode != ma_share_mode_exclusive) { /* <-- Exclusive streams must use the native sample rate. */
15239  streamFlags |= MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
15240  }
15241  if (!pData->noDefaultQualitySRC && pData->sampleRateIn != 0 && (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) != 0) {
15242  streamFlags |= MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
15243  }
15244  if (deviceType == ma_device_type_loopback) {
15245  streamFlags |= MA_AUDCLNT_STREAMFLAGS_LOOPBACK;
15246  }
15247 
15248  result = ma_context_get_IAudioClient__wasapi(pContext, deviceType, pDeviceID, &pData->pAudioClient, &pDeviceInterface);
15249  if (result != MA_SUCCESS) {
15250  goto done;
15251  }
15252 
15253  MA_ZERO_OBJECT(&wf);
15254 
15255  /* Try enabling hardware offloading. */
15256  if (!pData->noHardwareOffloading) {
15257  hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient2, (void**)&pAudioClient2);
15258  if (SUCCEEDED(hr)) {
15259  BOOL isHardwareOffloadingSupported = 0;
15260  hr = ma_IAudioClient2_IsOffloadCapable(pAudioClient2, MA_AudioCategory_Other, &isHardwareOffloadingSupported);
15261  if (SUCCEEDED(hr) && isHardwareOffloadingSupported) {
15262  ma_AudioClientProperties clientProperties;
15263  MA_ZERO_OBJECT(&clientProperties);
15264  clientProperties.cbSize = sizeof(clientProperties);
15265  clientProperties.bIsOffload = 1;
15266  clientProperties.eCategory = MA_AudioCategory_Other;
15267  ma_IAudioClient2_SetClientProperties(pAudioClient2, &clientProperties);
15268  }
15269 
15270  pAudioClient2->lpVtbl->Release(pAudioClient2);
15271  }
15272  }
15273 
15274  /* 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. */
15275  result = MA_FORMAT_NOT_SUPPORTED;
15276  if (pData->shareMode == ma_share_mode_exclusive) {
15277  #ifdef MA_WIN32_DESKTOP
15278  /* In exclusive mode on desktop we always use the backend's native format. */
15279  ma_IPropertyStore* pStore = NULL;
15280  hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pStore);
15281  if (SUCCEEDED(hr)) {
15282  PROPVARIANT prop;
15283  ma_PropVariantInit(&prop);
15284  hr = ma_IPropertyStore_GetValue(pStore, &MA_PKEY_AudioEngine_DeviceFormat, &prop);
15285  if (SUCCEEDED(hr)) {
15286  WAVEFORMATEX* pActualFormat = (WAVEFORMATEX*)prop.blob.pBlobData;
15287  hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pData->pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pActualFormat, NULL);
15288  if (SUCCEEDED(hr)) {
15289  MA_COPY_MEMORY(&wf, pActualFormat, sizeof(WAVEFORMATEXTENSIBLE));
15290  }
15291 
15292  ma_PropVariantClear(pContext, &prop);
15293  }
15294 
15295  ma_IPropertyStore_Release(pStore);
15296  }
15297  #else
15298  /*
15299  I do not know how to query the device's native format on UWP so for now I'm just disabling support for
15300  exclusive mode. The alternative is to enumerate over different formats and check IsFormatSupported()
15301  until you find one that works.
15302 
15303  TODO: Add support for exclusive mode to UWP.
15304  */
15305  hr = S_FALSE;
15306  #endif
15307 
15308  if (hr == S_OK) {
15309  shareMode = MA_AUDCLNT_SHAREMODE_EXCLUSIVE;
15310  result = MA_SUCCESS;
15311  } else {
15312  result = MA_SHARE_MODE_NOT_SUPPORTED;
15313  }
15314  } else {
15315  /* In shared mode we are always using the format reported by the operating system. */
15316  WAVEFORMATEXTENSIBLE* pNativeFormat = NULL;
15317  hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pData->pAudioClient, (WAVEFORMATEX**)&pNativeFormat);
15318  if (hr != S_OK) {
15319  result = MA_FORMAT_NOT_SUPPORTED;
15320  } else {
15321  MA_COPY_MEMORY(&wf, pNativeFormat, sizeof(wf));
15322  result = MA_SUCCESS;
15323  }
15324 
15325  ma_CoTaskMemFree(pContext, pNativeFormat);
15326 
15327  shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
15328  }
15329 
15330  /* Return an error if we still haven't found a format. */
15331  if (result != MA_SUCCESS) {
15332  errorMsg = "[WASAPI] Failed to find best device mix format.";
15333  goto done;
15334  }
15335 
15336  /*
15337  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
15338  WASAPI to perform the sample rate conversion.
15339  */
15340  nativeSampleRate = wf.Format.nSamplesPerSec;
15341  if (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) {
15342  wf.Format.nSamplesPerSec = (pData->sampleRateIn != 0) ? pData->sampleRateIn : MA_DEFAULT_SAMPLE_RATE;
15343  wf.Format.nAvgBytesPerSec = wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
15344  }
15345 
15346  pData->formatOut = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)&wf);
15347  if (pData->formatOut == ma_format_unknown) {
15348  /*
15349  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
15350  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
15351  completeness we'll check for it and return MA_FORMAT_NOT_SUPPORTED.
15352  */
15353  if (shareMode == MA_AUDCLNT_SHAREMODE_EXCLUSIVE) {
15354  result = MA_SHARE_MODE_NOT_SUPPORTED;
15355  } else {
15356  result = MA_FORMAT_NOT_SUPPORTED;
15357  }
15358 
15359  errorMsg = "[WASAPI] Native format not supported.";
15360  goto done;
15361  }
15362 
15363  pData->channelsOut = wf.Format.nChannels;
15364  pData->sampleRateOut = wf.Format.nSamplesPerSec;
15365 
15366  /* Get the internal channel map based on the channel mask. */
15367  ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
15368 
15369  /* Period size. */
15370  pData->periodsOut = (pData->periodsIn != 0) ? pData->periodsIn : MA_DEFAULT_PERIODS;
15371  pData->periodSizeInFramesOut = pData->periodSizeInFramesIn;
15372  if (pData->periodSizeInFramesOut == 0) {
15373  if (pData->periodSizeInMillisecondsIn == 0) {
15374  if (pData->performanceProfile == ma_performance_profile_low_latency) {
15375  pData->periodSizeInFramesOut = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY, wf.Format.nSamplesPerSec);
15376  } else {
15378  }
15379  } else {
15380  pData->periodSizeInFramesOut = ma_calculate_buffer_size_in_frames_from_milliseconds(pData->periodSizeInMillisecondsIn, wf.Format.nSamplesPerSec);
15381  }
15382  }
15383 
15384  periodDurationInMicroseconds = ((ma_uint64)pData->periodSizeInFramesOut * 1000 * 1000) / wf.Format.nSamplesPerSec;
15385 
15386 
15387  /* Slightly different initialization for shared and exclusive modes. We try exclusive mode first, and if it fails, fall back to shared mode. */
15388  if (shareMode == MA_AUDCLNT_SHAREMODE_EXCLUSIVE) {
15389  MA_REFERENCE_TIME bufferDuration = periodDurationInMicroseconds * 10;
15390 
15391  /*
15392  If the periodicy is too small, Initialize() will fail with AUDCLNT_E_INVALID_DEVICE_PERIOD. In this case we should just keep increasing
15393  it and trying it again.
15394  */
15395  hr = E_FAIL;
15396  for (;;) {
15397  hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf, NULL);
15398  if (hr == MA_AUDCLNT_E_INVALID_DEVICE_PERIOD) {
15399  if (bufferDuration > 500*10000) {
15400  break;
15401  } else {
15402  if (bufferDuration == 0) { /* <-- Just a sanity check to prevent an infinit loop. Should never happen, but it makes me feel better. */
15403  break;
15404  }
15405 
15406  bufferDuration = bufferDuration * 2;
15407  continue;
15408  }
15409  } else {
15410  break;
15411  }
15412  }
15413 
15414  if (hr == MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
15415  ma_uint32 bufferSizeInFrames;
15416  hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
15417  if (SUCCEEDED(hr)) {
15418  bufferDuration = (MA_REFERENCE_TIME)((10000.0 * 1000 / wf.Format.nSamplesPerSec * bufferSizeInFrames) + 0.5);
15419 
15420  /* Unfortunately we need to release and re-acquire the audio client according to MSDN. Seems silly - why not just call IAudioClient_Initialize() again?! */
15421  ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
15422 
15423  #ifdef MA_WIN32_DESKTOP
15424  hr = ma_IMMDevice_Activate(pDeviceInterface, &MA_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pData->pAudioClient);
15425  #else
15426  hr = ma_IUnknown_QueryInterface(pDeviceInterface, &MA_IID_IAudioClient, (void**)&pData->pAudioClient);
15427  #endif
15428 
15429  if (SUCCEEDED(hr)) {
15430  hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf, NULL);
15431  }
15432  }
15433  }
15434 
15435  if (FAILED(hr)) {
15436  /* 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. */
15437  if (hr == E_ACCESSDENIED) {
15438  errorMsg = "[WASAPI] Failed to initialize device in exclusive mode. Access denied.", result = MA_ACCESS_DENIED;
15439  } else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
15440  errorMsg = "[WASAPI] Failed to initialize device in exclusive mode. Device in use.", result = MA_BUSY;
15441  } else {
15442  errorMsg = "[WASAPI] Failed to initialize device in exclusive mode."; result = ma_result_from_HRESULT(hr);
15443  }
15444  goto done;
15445  }
15446  }
15447 
15448  if (shareMode == MA_AUDCLNT_SHAREMODE_SHARED) {
15449  /*
15450  Low latency shared mode via IAudioClient3.
15451 
15452  NOTE
15453  ====
15454  Contrary to the documentation on MSDN (https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient3-initializesharedaudiostream), the
15455  use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM and AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY with IAudioClient3_InitializeSharedAudioStream() absolutely does not work. Using
15456  any of these flags will result in HRESULT code 0x88890021. The other problem is that calling IAudioClient3_GetSharedModeEnginePeriod() with a sample rate different to
15457  that returned by IAudioClient_GetMixFormat() also results in an error. I'm therefore disabling low-latency shared mode with AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM.
15458  */
15459  #ifndef MA_WASAPI_NO_LOW_LATENCY_SHARED_MODE
15460  {
15461  if ((streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) == 0 || nativeSampleRate == wf.Format.nSamplesPerSec) {
15462  ma_IAudioClient3* pAudioClient3 = NULL;
15463  hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient3, (void**)&pAudioClient3);
15464  if (SUCCEEDED(hr)) {
15465  ma_uint32 defaultPeriodInFrames;
15466  ma_uint32 fundamentalPeriodInFrames;
15467  ma_uint32 minPeriodInFrames;
15468  ma_uint32 maxPeriodInFrames;
15469  hr = ma_IAudioClient3_GetSharedModeEnginePeriod(pAudioClient3, (WAVEFORMATEX*)&wf, &defaultPeriodInFrames, &fundamentalPeriodInFrames, &minPeriodInFrames, &maxPeriodInFrames);
15470  if (SUCCEEDED(hr)) {
15471  ma_uint32 desiredPeriodInFrames = pData->periodSizeInFramesOut;
15472  ma_uint32 actualPeriodInFrames = desiredPeriodInFrames;
15473 
15474  /* Make sure the period size is a multiple of fundamentalPeriodInFrames. */
15475  actualPeriodInFrames = actualPeriodInFrames / fundamentalPeriodInFrames;
15476  actualPeriodInFrames = actualPeriodInFrames * fundamentalPeriodInFrames;
15477 
15478  /* The period needs to be clamped between minPeriodInFrames and maxPeriodInFrames. */
15479  actualPeriodInFrames = ma_clamp(actualPeriodInFrames, minPeriodInFrames, maxPeriodInFrames);
15480 
15481  #if defined(MA_DEBUG_OUTPUT)
15482  {
15483  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] Trying IAudioClient3_InitializeSharedAudioStream(actualPeriodInFrames=%d)\n", actualPeriodInFrames);
15484  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " defaultPeriodInFrames=%d\n", defaultPeriodInFrames);
15485  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " fundamentalPeriodInFrames=%d\n", fundamentalPeriodInFrames);
15486  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " minPeriodInFrames=%d\n", minPeriodInFrames);
15487  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " maxPeriodInFrames=%d\n", maxPeriodInFrames);
15488  }
15489  #endif
15490 
15491  /* If the client requested a largish buffer than we don't actually want to use low latency shared mode because it forces small buffers. */
15492  if (actualPeriodInFrames >= desiredPeriodInFrames) {
15493  /*
15494  MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY must not be in the stream flags. If either of these are specified,
15495  IAudioClient3_InitializeSharedAudioStream() will fail.
15496  */
15497  hr = ma_IAudioClient3_InitializeSharedAudioStream(pAudioClient3, streamFlags & ~(MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY), actualPeriodInFrames, (WAVEFORMATEX*)&wf, NULL);
15498  if (SUCCEEDED(hr)) {
15499  wasInitializedUsingIAudioClient3 = MA_TRUE;
15500  pData->periodSizeInFramesOut = actualPeriodInFrames;
15501  #if defined(MA_DEBUG_OUTPUT)
15502  {
15503  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] Using IAudioClient3\n");
15504  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " periodSizeInFramesOut=%d\n", pData->periodSizeInFramesOut);
15505  }
15506  #endif
15507  } else {
15508  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] IAudioClient3_InitializeSharedAudioStream failed. Falling back to IAudioClient.\n");
15509  }
15510  } else {
15511  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");
15512  }
15513  } else {
15514  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] IAudioClient3_GetSharedModeEnginePeriod failed. Falling back to IAudioClient.\n");
15515  }
15516 
15517  ma_IAudioClient3_Release(pAudioClient3);
15518  pAudioClient3 = NULL;
15519  }
15520  }
15521  }
15522  #else
15523  {
15524  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");
15525  }
15526  #endif
15527 
15528  /* If we don't have an IAudioClient3 then we need to use the normal initialization routine. */
15529  if (!wasInitializedUsingIAudioClient3) {
15530  MA_REFERENCE_TIME bufferDuration = periodDurationInMicroseconds * pData->periodsOut * 10; /* <-- Multiply by 10 for microseconds to 100-nanoseconds. */
15531  hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, 0, (WAVEFORMATEX*)&wf, NULL);
15532  if (FAILED(hr)) {
15533  if (hr == E_ACCESSDENIED) {
15534  errorMsg = "[WASAPI] Failed to initialize device. Access denied.", result = MA_ACCESS_DENIED;
15535  } else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
15536  errorMsg = "[WASAPI] Failed to initialize device. Device in use.", result = MA_BUSY;
15537  } else {
15538  errorMsg = "[WASAPI] Failed to initialize device.", result = ma_result_from_HRESULT(hr);
15539  }
15540 
15541  goto done;
15542  }
15543  }
15544  }
15545 
15546  if (!wasInitializedUsingIAudioClient3) {
15547  ma_uint32 bufferSizeInFrames;
15548  hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
15549  if (FAILED(hr)) {
15550  errorMsg = "[WASAPI] Failed to get audio client's actual buffer size.", result = ma_result_from_HRESULT(hr);
15551  goto done;
15552  }
15553 
15554  pData->periodSizeInFramesOut = bufferSizeInFrames / pData->periodsOut;
15555  }
15556 
15557  pData->usingAudioClient3 = wasInitializedUsingIAudioClient3;
15558 
15559 
15560  if (deviceType == ma_device_type_playback) {
15561  result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pRenderClient);
15562  } else {
15563  result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pCaptureClient);
15564  }
15565 
15566  /*if (FAILED(hr)) {*/
15567  if (result != MA_SUCCESS) {
15568  errorMsg = "[WASAPI] Failed to get audio client service.";
15569  goto done;
15570  }
15571 
15572 
15573  /* Grab the name of the device. */
15574  #ifdef MA_WIN32_DESKTOP
15575  {
15576  ma_IPropertyStore *pProperties;
15577  hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pProperties);
15578  if (SUCCEEDED(hr)) {
15579  PROPVARIANT varName;
15580  ma_PropVariantInit(&varName);
15581  hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &varName);
15582  if (SUCCEEDED(hr)) {
15583  WideCharToMultiByte(CP_UTF8, 0, varName.pwszVal, -1, pData->deviceName, sizeof(pData->deviceName), 0, FALSE);
15584  ma_PropVariantClear(pContext, &varName);
15585  }
15586 
15587  ma_IPropertyStore_Release(pProperties);
15588  }
15589  }
15590  #endif
15591 
15592  /*
15593  For the WASAPI backend we need to know the actual IDs of the device in order to do automatic
15594  stream routing so that IDs can be compared and we can determine which device has been detached
15595  and whether or not it matches with our ma_device.
15596  */
15597  #ifdef MA_WIN32_DESKTOP
15598  {
15599  /* Desktop */
15600  ma_context_get_device_id_from_MMDevice__wasapi(pContext, pDeviceInterface, &pData->id);
15601  }
15602  #else
15603  {
15604  /* UWP */
15605  /* TODO: Implement me. Need to figure out how to get the ID of the default device. */
15606  }
15607  #endif
15608 
15609 done:
15610  /* Clean up. */
15611 #ifdef MA_WIN32_DESKTOP
15612  if (pDeviceInterface != NULL) {
15613  ma_IMMDevice_Release(pDeviceInterface);
15614  }
15615 #else
15616  if (pDeviceInterface != NULL) {
15617  ma_IUnknown_Release(pDeviceInterface);
15618  }
15619 #endif
15620 
15621  if (result != MA_SUCCESS) {
15622  if (pData->pRenderClient) {
15623  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pData->pRenderClient);
15624  pData->pRenderClient = NULL;
15625  }
15626  if (pData->pCaptureClient) {
15627  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pData->pCaptureClient);
15628  pData->pCaptureClient = NULL;
15629  }
15630  if (pData->pAudioClient) {
15631  ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
15632  pData->pAudioClient = NULL;
15633  }
15634 
15635  if (errorMsg != NULL && errorMsg[0] != '\0') {
15636  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_ERROR, errorMsg);
15637  }
15638 
15639  return result;
15640  } else {
15641  return MA_SUCCESS;
15642  }
15643 }
15644 
15645 static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type deviceType)
15646 {
15647  ma_device_init_internal_data__wasapi data;
15648  ma_result result;
15649 
15650  MA_ASSERT(pDevice != NULL);
15651 
15652  /* We only re-initialize the playback or capture device. Never a full-duplex device. */
15653  if (deviceType == ma_device_type_duplex) {
15654  return MA_INVALID_ARGS;
15655  }
15656 
15657 
15658  /*
15659  Before reinitializing the device we need to free the previous audio clients.
15660 
15661  There's a known memory leak here. We will be calling this from the routing change callback that
15662  is fired by WASAPI. If we attempt to release the IAudioClient we will deadlock. In my opinion
15663  this is a bug. I'm not sure what I need to do to handle this cleanly, but I think we'll probably
15664  need some system where we post an event, but delay the execution of it until the callback has
15665  returned. I'm not sure how to do this reliably, however. I have set up some infrastructure for
15666  a command thread which might be useful for this.
15667  */
15668  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
15669  if (pDevice->wasapi.pCaptureClient) {
15670  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
15671  pDevice->wasapi.pCaptureClient = NULL;
15672  }
15673 
15674  if (pDevice->wasapi.pAudioClientCapture) {
15675  /*ma_device_release_IAudioClient_service__wasapi(pDevice, ma_device_type_capture);*/
15676  pDevice->wasapi.pAudioClientCapture = NULL;
15677  }
15678  }
15679 
15680  if (deviceType == ma_device_type_playback) {
15681  if (pDevice->wasapi.pRenderClient) {
15682  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
15683  pDevice->wasapi.pRenderClient = NULL;
15684  }
15685 
15686  if (pDevice->wasapi.pAudioClientPlayback) {
15687  /*ma_device_release_IAudioClient_service__wasapi(pDevice, ma_device_type_playback);*/
15688  pDevice->wasapi.pAudioClientPlayback = NULL;
15689  }
15690  }
15691 
15692 
15693  if (deviceType == ma_device_type_playback) {
15694  data.formatIn = pDevice->playback.format;
15695  data.channelsIn = pDevice->playback.channels;
15696  MA_COPY_MEMORY(data.channelMapIn, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
15697  data.shareMode = pDevice->playback.shareMode;
15698  } else {
15699  data.formatIn = pDevice->capture.format;
15700  data.channelsIn = pDevice->capture.channels;
15701  MA_COPY_MEMORY(data.channelMapIn, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
15702  data.shareMode = pDevice->capture.shareMode;
15703  }
15704 
15705  data.sampleRateIn = pDevice->sampleRate;
15706  data.periodSizeInFramesIn = pDevice->wasapi.originalPeriodSizeInFrames;
15707  data.periodSizeInMillisecondsIn = pDevice->wasapi.originalPeriodSizeInMilliseconds;
15708  data.periodsIn = pDevice->wasapi.originalPeriods;
15709  data.performanceProfile = pDevice->wasapi.originalPerformanceProfile;
15710  data.noAutoConvertSRC = pDevice->wasapi.noAutoConvertSRC;
15711  data.noDefaultQualitySRC = pDevice->wasapi.noDefaultQualitySRC;
15712  data.noHardwareOffloading = pDevice->wasapi.noHardwareOffloading;
15713  result = ma_device_init_internal__wasapi(pDevice->pContext, deviceType, NULL, &data);
15714  if (result != MA_SUCCESS) {
15715  return result;
15716  }
15717 
15718  /* At this point we have some new objects ready to go. We need to uninitialize the previous ones and then set the new ones. */
15719  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
15720  pDevice->wasapi.pAudioClientCapture = data.pAudioClient;
15721  pDevice->wasapi.pCaptureClient = data.pCaptureClient;
15722 
15723  pDevice->capture.internalFormat = data.formatOut;
15724  pDevice->capture.internalChannels = data.channelsOut;
15725  pDevice->capture.internalSampleRate = data.sampleRateOut;
15726  MA_COPY_MEMORY(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
15727  pDevice->capture.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
15728  pDevice->capture.internalPeriods = data.periodsOut;
15729  ma_strcpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), data.deviceName);
15730 
15731  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
15732 
15733  pDevice->wasapi.periodSizeInFramesCapture = data.periodSizeInFramesOut;
15734  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualPeriodSizeInFramesCapture);
15735 
15736  /* We must always have a valid ID. */
15737  ma_wcscpy_s(pDevice->capture.id.wasapi, sizeof(pDevice->capture.id.wasapi), data.id.wasapi);
15738  }
15739 
15740  if (deviceType == ma_device_type_playback) {
15741  pDevice->wasapi.pAudioClientPlayback = data.pAudioClient;
15742  pDevice->wasapi.pRenderClient = data.pRenderClient;
15743 
15744  pDevice->playback.internalFormat = data.formatOut;
15745  pDevice->playback.internalChannels = data.channelsOut;
15746  pDevice->playback.internalSampleRate = data.sampleRateOut;
15747  MA_COPY_MEMORY(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
15748  pDevice->playback.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
15749  pDevice->playback.internalPeriods = data.periodsOut;
15750  ma_strcpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), data.deviceName);
15751 
15752  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
15753 
15754  pDevice->wasapi.periodSizeInFramesPlayback = data.periodSizeInFramesOut;
15755  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualPeriodSizeInFramesPlayback);
15756 
15757  /* We must always have a valid ID. */
15758  ma_wcscpy_s(pDevice->playback.id.wasapi, sizeof(pDevice->playback.id.wasapi), data.id.wasapi);
15759  }
15760 
15761  return MA_SUCCESS;
15762 }
15763 
15764 static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
15765 {
15766  ma_result result = MA_SUCCESS;
15767 
15768 #ifdef MA_WIN32_DESKTOP
15769  HRESULT hr;
15770  ma_IMMDeviceEnumerator* pDeviceEnumerator;
15771 #endif
15772 
15773  MA_ASSERT(pDevice != NULL);
15774 
15775  MA_ZERO_OBJECT(&pDevice->wasapi);
15776  pDevice->wasapi.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
15777  pDevice->wasapi.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
15778  pDevice->wasapi.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
15779 
15780  /* Exclusive mode is not allowed with loopback. */
15782  return MA_INVALID_DEVICE_CONFIG;
15783  }
15784 
15786  ma_device_init_internal_data__wasapi data;
15787  data.formatIn = pDescriptorCapture->format;
15788  data.channelsIn = pDescriptorCapture->channels;
15789  data.sampleRateIn = pDescriptorCapture->sampleRate;
15790  MA_COPY_MEMORY(data.channelMapIn, pDescriptorCapture->channelMap, sizeof(pDescriptorCapture->channelMap));
15791  data.periodSizeInFramesIn = pDescriptorCapture->periodSizeInFrames;
15792  data.periodSizeInMillisecondsIn = pDescriptorCapture->periodSizeInMilliseconds;
15793  data.periodsIn = pDescriptorCapture->periodCount;
15794  data.shareMode = pDescriptorCapture->shareMode;
15795  data.performanceProfile = pConfig->performanceProfile;
15796  data.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
15797  data.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
15798  data.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
15799 
15800  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);
15801  if (result != MA_SUCCESS) {
15802  return result;
15803  }
15804 
15805  pDevice->wasapi.pAudioClientCapture = data.pAudioClient;
15806  pDevice->wasapi.pCaptureClient = data.pCaptureClient;
15807  pDevice->wasapi.originalPeriodSizeInMilliseconds = pDescriptorCapture->periodSizeInMilliseconds;
15808  pDevice->wasapi.originalPeriodSizeInFrames = pDescriptorCapture->periodSizeInFrames;
15809  pDevice->wasapi.originalPeriods = pDescriptorCapture->periodCount;
15810  pDevice->wasapi.originalPerformanceProfile = pConfig->performanceProfile;
15811 
15812  /*
15813  The event for capture needs to be manual reset for the same reason as playback. We keep the initial state set to unsignaled,
15814  however, because we want to block until we actually have something for the first call to ma_device_read().
15815  */
15816  pDevice->wasapi.hEventCapture = CreateEventW(NULL, FALSE, FALSE, NULL); /* Auto reset, unsignaled by default. */
15817  if (pDevice->wasapi.hEventCapture == NULL) {
15818  result = ma_result_from_GetLastError(GetLastError());
15819 
15820  if (pDevice->wasapi.pCaptureClient != NULL) {
15821  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
15822  pDevice->wasapi.pCaptureClient = NULL;
15823  }
15824  if (pDevice->wasapi.pAudioClientCapture != NULL) {
15825  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
15826  pDevice->wasapi.pAudioClientCapture = NULL;
15827  }
15828 
15829  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for capture.", result);
15830  }
15831  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
15832 
15833  pDevice->wasapi.periodSizeInFramesCapture = data.periodSizeInFramesOut;
15834  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualPeriodSizeInFramesCapture);
15835 
15836  /* We must always have a valid ID. */
15837  ma_wcscpy_s(pDevice->capture.id.wasapi, sizeof(pDevice->capture.id.wasapi), data.id.wasapi);
15838 
15839  /* The descriptor needs to be updated with actual values. */
15840  pDescriptorCapture->format = data.formatOut;
15841  pDescriptorCapture->channels = data.channelsOut;
15842  pDescriptorCapture->sampleRate = data.sampleRateOut;
15843  MA_COPY_MEMORY(pDescriptorCapture->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
15844  pDescriptorCapture->periodSizeInFrames = data.periodSizeInFramesOut;
15845  pDescriptorCapture->periodCount = data.periodsOut;
15846  }
15847 
15848  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
15849  ma_device_init_internal_data__wasapi data;
15850  data.formatIn = pDescriptorPlayback->format;
15851  data.channelsIn = pDescriptorPlayback->channels;
15852  data.sampleRateIn = pDescriptorPlayback->sampleRate;
15853  MA_COPY_MEMORY(data.channelMapIn, pDescriptorPlayback->channelMap, sizeof(pDescriptorPlayback->channelMap));
15854  data.periodSizeInFramesIn = pDescriptorPlayback->periodSizeInFrames;
15855  data.periodSizeInMillisecondsIn = pDescriptorPlayback->periodSizeInMilliseconds;
15856  data.periodsIn = pDescriptorPlayback->periodCount;
15857  data.shareMode = pDescriptorPlayback->shareMode;
15858  data.performanceProfile = pConfig->performanceProfile;
15859  data.noAutoConvertSRC = pConfig->wasapi.noAutoConvertSRC;
15860  data.noDefaultQualitySRC = pConfig->wasapi.noDefaultQualitySRC;
15861  data.noHardwareOffloading = pConfig->wasapi.noHardwareOffloading;
15862 
15863  result = ma_device_init_internal__wasapi(pDevice->pContext, ma_device_type_playback, pDescriptorPlayback->pDeviceID, &data);
15864  if (result != MA_SUCCESS) {
15865  if (pConfig->deviceType == ma_device_type_duplex) {
15866  if (pDevice->wasapi.pCaptureClient != NULL) {
15867  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
15868  pDevice->wasapi.pCaptureClient = NULL;
15869  }
15870  if (pDevice->wasapi.pAudioClientCapture != NULL) {
15871  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
15872  pDevice->wasapi.pAudioClientCapture = NULL;
15873  }
15874 
15875  CloseHandle(pDevice->wasapi.hEventCapture);
15876  pDevice->wasapi.hEventCapture = NULL;
15877  }
15878  return result;
15879  }
15880 
15881  pDevice->wasapi.pAudioClientPlayback = data.pAudioClient;
15882  pDevice->wasapi.pRenderClient = data.pRenderClient;
15883  pDevice->wasapi.originalPeriodSizeInMilliseconds = pDescriptorPlayback->periodSizeInMilliseconds;
15884  pDevice->wasapi.originalPeriodSizeInFrames = pDescriptorPlayback->periodSizeInFrames;
15885  pDevice->wasapi.originalPeriods = pDescriptorPlayback->periodCount;
15886  pDevice->wasapi.originalPerformanceProfile = pConfig->performanceProfile;
15887 
15888  /*
15889  The event for playback is needs to be manual reset because we want to explicitly control the fact that it becomes signalled
15890  only after the whole available space has been filled, never before.
15891 
15892  The playback event also needs to be initially set to a signaled state so that the first call to ma_device_write() is able
15893  to get passed WaitForMultipleObjects().
15894  */
15895  pDevice->wasapi.hEventPlayback = CreateEventW(NULL, FALSE, TRUE, NULL); /* Auto reset, signaled by default. */
15896  if (pDevice->wasapi.hEventPlayback == NULL) {
15897  result = ma_result_from_GetLastError(GetLastError());
15898 
15899  if (pConfig->deviceType == ma_device_type_duplex) {
15900  if (pDevice->wasapi.pCaptureClient != NULL) {
15901  ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
15902  pDevice->wasapi.pCaptureClient = NULL;
15903  }
15904  if (pDevice->wasapi.pAudioClientCapture != NULL) {
15905  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
15906  pDevice->wasapi.pAudioClientCapture = NULL;
15907  }
15908 
15909  CloseHandle(pDevice->wasapi.hEventCapture);
15910  pDevice->wasapi.hEventCapture = NULL;
15911  }
15912 
15913  if (pDevice->wasapi.pRenderClient != NULL) {
15914  ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
15915  pDevice->wasapi.pRenderClient = NULL;
15916  }
15917  if (pDevice->wasapi.pAudioClientPlayback != NULL) {
15918  ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
15919  pDevice->wasapi.pAudioClientPlayback = NULL;
15920  }
15921 
15922  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for playback.", result);
15923  }
15924  ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
15925 
15926  pDevice->wasapi.periodSizeInFramesPlayback = data.periodSizeInFramesOut;
15927  ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualPeriodSizeInFramesPlayback);
15928 
15929  /* We must always have a valid ID. */
15930  ma_wcscpy_s(pDevice->playback.id.wasapi, sizeof(pDevice->playback.id.wasapi), data.id.wasapi);
15931 
15932  /* The descriptor needs to be updated with actual values. */
15933  pDescriptorPlayback->format = data.formatOut;
15934  pDescriptorPlayback->channels = data.channelsOut;
15935  pDescriptorPlayback->sampleRate = data.sampleRateOut;
15936  MA_COPY_MEMORY(pDescriptorPlayback->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
15937  pDescriptorPlayback->periodSizeInFrames = data.periodSizeInFramesOut;
15938  pDescriptorPlayback->periodCount = data.periodsOut;
15939  }
15940 
15941  /*
15942  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
15943  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
15944  stop the device outright and let the application handle it.
15945  */
15946 #ifdef MA_WIN32_DESKTOP
15947  if (pConfig->wasapi.noAutoStreamRouting == MA_FALSE) {
15948  if ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pConfig->capture.pDeviceID == NULL) {
15949  pDevice->wasapi.allowCaptureAutoStreamRouting = MA_TRUE;
15950  }
15951  if ((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pConfig->playback.pDeviceID == NULL) {
15952  pDevice->wasapi.allowPlaybackAutoStreamRouting = MA_TRUE;
15953  }
15954  }
15955 
15956  hr = ma_CoCreateInstance(pDevice->pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
15957  if (FAILED(hr)) {
15958  ma_device_uninit__wasapi(pDevice);
15959  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
15960  }
15961 
15962  pDevice->wasapi.notificationClient.lpVtbl = (void*)&g_maNotificationCientVtbl;
15963  pDevice->wasapi.notificationClient.counter = 1;
15964  pDevice->wasapi.notificationClient.pDevice = pDevice;
15965 
15966  hr = pDeviceEnumerator->lpVtbl->RegisterEndpointNotificationCallback(pDeviceEnumerator, &pDevice->wasapi.notificationClient);
15967  if (SUCCEEDED(hr)) {
15968  pDevice->wasapi.pDeviceEnumerator = (ma_ptr)pDeviceEnumerator;
15969  } else {
15970  /* Not the end of the world if we fail to register the notification callback. We just won't support automatic stream routing. */
15971  ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
15972  }
15973 #endif
15974 
15975  c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_FALSE);
15976  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_FALSE);
15977 
15978  return MA_SUCCESS;
15979 }
15980 
15981 static ma_result ma_device__get_available_frames__wasapi(ma_device* pDevice, ma_IAudioClient* pAudioClient, ma_uint32* pFrameCount)
15982 {
15983  ma_uint32 paddingFramesCount;
15984  HRESULT hr;
15985  ma_share_mode shareMode;
15986 
15987  MA_ASSERT(pDevice != NULL);
15988  MA_ASSERT(pFrameCount != NULL);
15989 
15990  *pFrameCount = 0;
15991 
15992  if ((ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientPlayback && (ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientCapture) {
15993  return MA_INVALID_OPERATION;
15994  }
15995 
15996  /*
15997  I've had a report that GetCurrentPadding() is returning a frame count of 0 which is preventing
15998  higher level function calls from doing anything because it thinks nothing is available. I have
15999  taken a look at the documentation and it looks like this is unnecessary in exclusive mode.
16000 
16001  From Microsoft's documentation:
16002 
16003  For an exclusive-mode rendering or capture stream that was initialized with the
16004  AUDCLNT_STREAMFLAGS_EVENTCALLBACK flag, the client typically has no use for the padding
16005  value reported by GetCurrentPadding. Instead, the client accesses an entire buffer during
16006  each processing pass.
16007 
16008  Considering this, I'm going to skip GetCurrentPadding() for exclusive mode and just report the
16009  entire buffer. This depends on the caller making sure they wait on the event handler.
16010  */
16011  shareMode = ((ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) ? pDevice->playback.shareMode : pDevice->capture.shareMode;
16012  if (shareMode == ma_share_mode_shared) {
16013  /* Shared mode. */
16014  hr = ma_IAudioClient_GetCurrentPadding(pAudioClient, &paddingFramesCount);
16015  if (FAILED(hr)) {
16016  return ma_result_from_HRESULT(hr);
16017  }
16018 
16019  if ((ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) {
16020  *pFrameCount = pDevice->wasapi.actualPeriodSizeInFramesPlayback - paddingFramesCount;
16021  } else {
16022  *pFrameCount = paddingFramesCount;
16023  }
16024  } else {
16025  /* Exclusive mode. */
16026  if ((ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) {
16027  *pFrameCount = pDevice->wasapi.actualPeriodSizeInFramesPlayback;
16028  } else {
16029  *pFrameCount = pDevice->wasapi.actualPeriodSizeInFramesCapture;
16030  }
16031  }
16032 
16033  return MA_SUCCESS;
16034 }
16035 
16036 
16037 static ma_result ma_device_reroute__wasapi(ma_device* pDevice, ma_device_type deviceType)
16038 {
16039  ma_result result;
16040 
16041  if (deviceType == ma_device_type_duplex) {
16042  return MA_INVALID_ARGS;
16043  }
16044 
16045  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "=== CHANGING DEVICE ===\n");
16046 
16047  result = ma_device_reinit__wasapi(pDevice, deviceType);
16048  if (result != MA_SUCCESS) {
16049  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Reinitializing device after route change failed.\n");
16050  return result;
16051  }
16052 
16053  ma_device__post_init_setup(pDevice, deviceType);
16054 
16055  return MA_SUCCESS;
16056 }
16057 
16058 static ma_result ma_device_start__wasapi(ma_device* pDevice)
16059 {
16060  HRESULT hr;
16061 
16062  MA_ASSERT(pDevice != NULL);
16063 
16064  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
16065  hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
16066  if (FAILED(hr)) {
16067  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device.", ma_result_from_HRESULT(hr));
16068  }
16069 
16070  c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_TRUE);
16071  }
16072 
16073  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
16074  /* No need to do anything for playback as that'll be started automatically in the data loop. */
16075  }
16076 
16077  return MA_SUCCESS;
16078 }
16079 
16080 static ma_result ma_device_stop__wasapi(ma_device* pDevice)
16081 {
16082  ma_result result;
16083  HRESULT hr;
16084 
16085  MA_ASSERT(pDevice != NULL);
16086 
16087  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
16088  hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
16089  if (FAILED(hr)) {
16090  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal capture device.", ma_result_from_HRESULT(hr));
16091  }
16092 
16093  /* The audio client needs to be reset otherwise restarting will fail. */
16094  hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
16095  if (FAILED(hr)) {
16096  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to reset internal capture device.", ma_result_from_HRESULT(hr));
16097  }
16098 
16099  c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_FALSE);
16100  }
16101 
16102  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
16103  /*
16104  The buffer needs to be drained before stopping the device. Not doing this will result in the last few frames not getting output to
16105  the speakers. This is a problem for very short sounds because it'll result in a significant portion of it not getting played.
16106  */
16107  if (c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) {
16108  /* We need to make sure we put a timeout here or else we'll risk getting stuck in a deadlock in some cases. */
16109  DWORD waitTime = pDevice->wasapi.actualPeriodSizeInFramesPlayback / pDevice->playback.internalSampleRate;
16110 
16111  if (pDevice->playback.shareMode == ma_share_mode_exclusive) {
16112  WaitForSingleObject(pDevice->wasapi.hEventPlayback, waitTime);
16113  } else {
16114  ma_uint32 prevFramesAvaialablePlayback = (ma_uint32)-1;
16115  ma_uint32 framesAvailablePlayback;
16116  for (;;) {
16117  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
16118  if (result != MA_SUCCESS) {
16119  break;
16120  }
16121 
16122  if (framesAvailablePlayback >= pDevice->wasapi.actualPeriodSizeInFramesPlayback) {
16123  break;
16124  }
16125 
16126  /*
16127  Just a safety check to avoid an infinite loop. If this iteration results in a situation where the number of available frames
16128  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.
16129  */
16130  if (framesAvailablePlayback == prevFramesAvaialablePlayback) {
16131  break;
16132  }
16133  prevFramesAvaialablePlayback = framesAvailablePlayback;
16134 
16135  WaitForSingleObject(pDevice->wasapi.hEventPlayback, waitTime);
16136  ResetEvent(pDevice->wasapi.hEventPlayback); /* Manual reset. */
16137  }
16138  }
16139  }
16140 
16141  hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
16142  if (FAILED(hr)) {
16143  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal playback device.", ma_result_from_HRESULT(hr));
16144  }
16145 
16146  /* The audio client needs to be reset otherwise restarting will fail. */
16147  hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
16148  if (FAILED(hr)) {
16149  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to reset internal playback device.", ma_result_from_HRESULT(hr));
16150  }
16151 
16152  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_FALSE);
16153  }
16154 
16155  return MA_SUCCESS;
16156 }
16157 
16158 
16159 #ifndef MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS
16160 #define MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS 5000
16161 #endif
16162 
16163 static ma_result ma_device_data_loop__wasapi(ma_device* pDevice)
16164 {
16165  ma_result result;
16166  HRESULT hr;
16167  ma_bool32 exitLoop = MA_FALSE;
16168  ma_uint32 framesWrittenToPlaybackDevice = 0;
16169  ma_uint32 mappedDeviceBufferSizeInFramesCapture = 0;
16170  ma_uint32 mappedDeviceBufferSizeInFramesPlayback = 0;
16171  ma_uint32 mappedDeviceBufferFramesRemainingCapture = 0;
16172  ma_uint32 mappedDeviceBufferFramesRemainingPlayback = 0;
16173  BYTE* pMappedDeviceBufferCapture = NULL;
16174  BYTE* pMappedDeviceBufferPlayback = NULL;
16175  ma_uint32 bpfCaptureDevice = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
16176  ma_uint32 bpfPlaybackDevice = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
16177  ma_uint32 bpfCaptureClient = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
16178  ma_uint32 bpfPlaybackClient = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
16179  ma_uint8 inputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
16180  ma_uint32 inputDataInClientFormatCap = 0;
16181  ma_uint8 outputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
16182  ma_uint32 outputDataInClientFormatCap = 0;
16183  ma_uint32 outputDataInClientFormatCount = 0;
16184  ma_uint32 outputDataInClientFormatConsumed = 0;
16185  ma_uint32 periodSizeInFramesCapture = 0;
16186 
16187  MA_ASSERT(pDevice != NULL);
16188 
16189  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
16190  periodSizeInFramesCapture = pDevice->capture.internalPeriodSizeInFrames;
16191  inputDataInClientFormatCap = sizeof(inputDataInClientFormat) / bpfCaptureClient;
16192  }
16193 
16194  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
16195  outputDataInClientFormatCap = sizeof(outputDataInClientFormat) / bpfPlaybackClient;
16196  }
16197 
16198  while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
16199  switch (pDevice->type)
16200  {
16201  case ma_device_type_duplex:
16202  {
16203  ma_uint32 framesAvailableCapture;
16204  ma_uint32 framesAvailablePlayback;
16205  DWORD flagsCapture; /* Passed to IAudioCaptureClient_GetBuffer(). */
16206 
16207  /* The process is to map the playback buffer and fill it as quickly as possible from input data. */
16208  if (pMappedDeviceBufferPlayback == NULL) {
16209  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
16210  if (result != MA_SUCCESS) {
16211  return result;
16212  }
16213 
16214  /* In exclusive mode, the frame count needs to exactly match the value returned by GetCurrentPadding(). */
16215  if (pDevice->playback.shareMode != ma_share_mode_exclusive) {
16216  if (framesAvailablePlayback > pDevice->wasapi.periodSizeInFramesPlayback) {
16217  framesAvailablePlayback = pDevice->wasapi.periodSizeInFramesPlayback;
16218  }
16219  }
16220 
16221  /* We're ready to map the playback device's buffer. We don't release this until it's been entirely filled. */
16222  hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedDeviceBufferPlayback);
16223  if (FAILED(hr)) {
16224  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));
16225  exitLoop = MA_TRUE;
16226  break;
16227  }
16228 
16229  mappedDeviceBufferSizeInFramesPlayback = framesAvailablePlayback;
16230  mappedDeviceBufferFramesRemainingPlayback = framesAvailablePlayback;
16231  }
16232 
16233  if (mappedDeviceBufferFramesRemainingPlayback > 0) {
16234  /* At this point we should have a buffer available for output. We need to keep writing input samples to it. */
16235  for (;;) {
16236  /* Try grabbing some captured data if we haven't already got a mapped buffer. */
16237  if (pMappedDeviceBufferCapture == NULL) {
16238  if (pDevice->capture.shareMode == ma_share_mode_shared) {
16239  if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
16240  return MA_ERROR; /* Wait failed. */
16241  }
16242  }
16243 
16244  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
16245  if (result != MA_SUCCESS) {
16246  exitLoop = MA_TRUE;
16247  break;
16248  }
16249 
16250  /* Wait for more if nothing is available. */
16251  if (framesAvailableCapture == 0) {
16252  /* In exclusive mode we waited at the top. */
16253  if (pDevice->capture.shareMode != ma_share_mode_shared) {
16254  if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
16255  return MA_ERROR; /* Wait failed. */
16256  }
16257  }
16258 
16259  continue;
16260  }
16261 
16262  /* Getting here means there's data available for writing to the output device. */
16263  mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
16264  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
16265  if (FAILED(hr)) {
16266  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));
16267  exitLoop = MA_TRUE;
16268  break;
16269  }
16270 
16271 
16272  /* Overrun detection. */
16273  if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) != 0) {
16274  /* Glitched. Probably due to an overrun. */
16275  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Data discontinuity (possible overrun). framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
16276 
16277  /*
16278  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
16279  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
16280  last period.
16281  */
16282  if (framesAvailableCapture >= pDevice->wasapi.actualPeriodSizeInFramesCapture) {
16283  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Synchronizing capture stream. ");
16284  do
16285  {
16286  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
16287  if (FAILED(hr)) {
16288  break;
16289  }
16290 
16291  framesAvailableCapture -= mappedDeviceBufferSizeInFramesCapture;
16292 
16293  if (framesAvailableCapture > 0) {
16294  mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
16295  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
16296  if (FAILED(hr)) {
16297  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));
16298  exitLoop = MA_TRUE;
16299  break;
16300  }
16301  } else {
16302  pMappedDeviceBufferCapture = NULL;
16303  mappedDeviceBufferSizeInFramesCapture = 0;
16304  }
16305  } while (framesAvailableCapture > periodSizeInFramesCapture);
16306  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
16307  }
16308  } else {
16309  #ifdef MA_DEBUG_OUTPUT
16310  if (flagsCapture != 0) {
16311  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Capture Flags: %ld\n", flagsCapture);
16312  }
16313  #endif
16314  }
16315 
16316  mappedDeviceBufferFramesRemainingCapture = mappedDeviceBufferSizeInFramesCapture;
16317  }
16318 
16319 
16320  /* 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. */
16321  for (;;) {
16322  BYTE* pRunningDeviceBufferCapture;
16323  BYTE* pRunningDeviceBufferPlayback;
16324  ma_uint32 framesToProcess;
16325  ma_uint32 framesProcessed;
16326 
16327  pRunningDeviceBufferCapture = pMappedDeviceBufferCapture + ((mappedDeviceBufferSizeInFramesCapture - mappedDeviceBufferFramesRemainingCapture ) * bpfCaptureDevice);
16328  pRunningDeviceBufferPlayback = pMappedDeviceBufferPlayback + ((mappedDeviceBufferSizeInFramesPlayback - mappedDeviceBufferFramesRemainingPlayback) * bpfPlaybackDevice);
16329 
16330  /* There may be some data sitting in the converter that needs to be processed first. Once this is exhaused, run the data callback again. */
16331  if (!pDevice->playback.converter.isPassthrough && outputDataInClientFormatConsumed < outputDataInClientFormatCount) {
16332  ma_uint64 convertedFrameCountClient = (outputDataInClientFormatCount - outputDataInClientFormatConsumed);
16333  ma_uint64 convertedFrameCountDevice = mappedDeviceBufferFramesRemainingPlayback;
16334  void* pConvertedFramesClient = outputDataInClientFormat + (outputDataInClientFormatConsumed * bpfPlaybackClient);
16335  void* pConvertedFramesDevice = pRunningDeviceBufferPlayback;
16336  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pConvertedFramesClient, &convertedFrameCountClient, pConvertedFramesDevice, &convertedFrameCountDevice);
16337  if (result != MA_SUCCESS) {
16338  break;
16339  }
16340 
16341  outputDataInClientFormatConsumed += (ma_uint32)convertedFrameCountClient; /* Safe cast. */
16342  mappedDeviceBufferFramesRemainingPlayback -= (ma_uint32)convertedFrameCountDevice; /* Safe cast. */
16343 
16344  if (mappedDeviceBufferFramesRemainingPlayback == 0) {
16345  break;
16346  }
16347  }
16348 
16349  /*
16350  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
16351  buffers directly to the callback.
16352  */
16353  if (pDevice->capture.converter.isPassthrough && pDevice->playback.converter.isPassthrough) {
16354  /* Optimal path. We can pass mapped pointers directly to the callback. */
16355  framesToProcess = ma_min(mappedDeviceBufferFramesRemainingCapture, mappedDeviceBufferFramesRemainingPlayback);
16356  framesProcessed = framesToProcess;
16357 
16358  ma_device__on_data(pDevice, pRunningDeviceBufferPlayback, pRunningDeviceBufferCapture, framesToProcess);
16359 
16360  mappedDeviceBufferFramesRemainingCapture -= framesProcessed;
16361  mappedDeviceBufferFramesRemainingPlayback -= framesProcessed;
16362 
16363  if (mappedDeviceBufferFramesRemainingCapture == 0) {
16364  break; /* Exhausted input data. */
16365  }
16366  if (mappedDeviceBufferFramesRemainingPlayback == 0) {
16367  break; /* Exhausted output data. */
16368  }
16369  } else if (pDevice->capture.converter.isPassthrough) {
16370  /* The input buffer is a passthrough, but the playback buffer requires a conversion. */
16371  framesToProcess = ma_min(mappedDeviceBufferFramesRemainingCapture, outputDataInClientFormatCap);
16372  framesProcessed = framesToProcess;
16373 
16374  ma_device__on_data(pDevice, outputDataInClientFormat, pRunningDeviceBufferCapture, framesToProcess);
16375  outputDataInClientFormatCount = framesProcessed;
16376  outputDataInClientFormatConsumed = 0;
16377 
16378  mappedDeviceBufferFramesRemainingCapture -= framesProcessed;
16379  if (mappedDeviceBufferFramesRemainingCapture == 0) {
16380  break; /* Exhausted input data. */
16381  }
16382  } else if (pDevice->playback.converter.isPassthrough) {
16383  /* The input buffer requires conversion, the playback buffer is passthrough. */
16384  ma_uint64 capturedDeviceFramesToProcess = mappedDeviceBufferFramesRemainingCapture;
16385  ma_uint64 capturedClientFramesToProcess = ma_min(inputDataInClientFormatCap, mappedDeviceBufferFramesRemainingPlayback);
16386 
16387  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningDeviceBufferCapture, &capturedDeviceFramesToProcess, inputDataInClientFormat, &capturedClientFramesToProcess);
16388  if (result != MA_SUCCESS) {
16389  break;
16390  }
16391 
16392  if (capturedClientFramesToProcess == 0) {
16393  break;
16394  }
16395 
16396  ma_device__on_data(pDevice, pRunningDeviceBufferPlayback, inputDataInClientFormat, (ma_uint32)capturedClientFramesToProcess); /* Safe cast. */
16397 
16398  mappedDeviceBufferFramesRemainingCapture -= (ma_uint32)capturedDeviceFramesToProcess;
16399  mappedDeviceBufferFramesRemainingPlayback -= (ma_uint32)capturedClientFramesToProcess;
16400  } else {
16401  ma_uint64 capturedDeviceFramesToProcess = mappedDeviceBufferFramesRemainingCapture;
16402  ma_uint64 capturedClientFramesToProcess = ma_min(inputDataInClientFormatCap, outputDataInClientFormatCap);
16403 
16404  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningDeviceBufferCapture, &capturedDeviceFramesToProcess, inputDataInClientFormat, &capturedClientFramesToProcess);
16405  if (result != MA_SUCCESS) {
16406  break;
16407  }
16408 
16409  if (capturedClientFramesToProcess == 0) {
16410  break;
16411  }
16412 
16413  ma_device__on_data(pDevice, outputDataInClientFormat, inputDataInClientFormat, (ma_uint32)capturedClientFramesToProcess);
16414 
16415  mappedDeviceBufferFramesRemainingCapture -= (ma_uint32)capturedDeviceFramesToProcess;
16416  outputDataInClientFormatCount = (ma_uint32)capturedClientFramesToProcess;
16417  outputDataInClientFormatConsumed = 0;
16418  }
16419  }
16420 
16421 
16422  /* If at this point we've run out of capture data we need to release the buffer. */
16423  if (mappedDeviceBufferFramesRemainingCapture == 0 && pMappedDeviceBufferCapture != NULL) {
16424  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
16425  if (FAILED(hr)) {
16426  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));
16427  exitLoop = MA_TRUE;
16428  break;
16429  }
16430 
16431  pMappedDeviceBufferCapture = NULL;
16432  mappedDeviceBufferFramesRemainingCapture = 0;
16433  mappedDeviceBufferSizeInFramesCapture = 0;
16434  }
16435 
16436  /* Get out of this loop if we're run out of room in the playback buffer. */
16437  if (mappedDeviceBufferFramesRemainingPlayback == 0) {
16438  break;
16439  }
16440  }
16441  }
16442 
16443 
16444  /* If at this point we've run out of data we need to release the buffer. */
16445  if (mappedDeviceBufferFramesRemainingPlayback == 0 && pMappedDeviceBufferPlayback != NULL) {
16446  hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedDeviceBufferSizeInFramesPlayback, 0);
16447  if (FAILED(hr)) {
16448  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));
16449  exitLoop = MA_TRUE;
16450  break;
16451  }
16452 
16453  framesWrittenToPlaybackDevice += mappedDeviceBufferSizeInFramesPlayback;
16454 
16455  pMappedDeviceBufferPlayback = NULL;
16456  mappedDeviceBufferFramesRemainingPlayback = 0;
16457  mappedDeviceBufferSizeInFramesPlayback = 0;
16458  }
16459 
16460  if (!c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) {
16461  ma_uint32 startThreshold = pDevice->playback.internalPeriodSizeInFrames * 1;
16462 
16463  /* 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. */
16464  if (startThreshold > pDevice->wasapi.actualPeriodSizeInFramesPlayback) {
16465  startThreshold = pDevice->wasapi.actualPeriodSizeInFramesPlayback;
16466  }
16467 
16468  if (pDevice->playback.shareMode == ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= startThreshold) {
16469  hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
16470  if (FAILED(hr)) {
16471  ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
16472  ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
16473  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.", ma_result_from_HRESULT(hr));
16474  }
16475 
16476  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_TRUE);
16477  }
16478  }
16479 
16480  /* Make sure the device has started before waiting. */
16481  if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
16482  return MA_ERROR; /* Wait failed. */
16483  }
16484  } break;
16485 
16486 
16487 
16490  {
16491  ma_uint32 framesAvailableCapture;
16492  DWORD flagsCapture; /* Passed to IAudioCaptureClient_GetBuffer(). */
16493 
16494  /* Wait for data to become available first. */
16495  if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
16496  /*
16497  For capture we can terminate here because it probably means the microphone just isn't delivering data for whatever reason, but
16498  for loopback is most likely means nothing is actually playing. We want to keep trying in this situation.
16499  */
16500  if (pDevice->type == ma_device_type_loopback) {
16501  continue; /* Keep waiting in loopback mode. */
16502  } else {
16503  exitLoop = MA_TRUE;
16504  break; /* Wait failed. */
16505  }
16506  }
16507 
16508  /* 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. */
16509  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
16510  if (result != MA_SUCCESS) {
16511  exitLoop = MA_TRUE;
16512  break;
16513  }
16514 
16515  if (framesAvailableCapture < pDevice->wasapi.periodSizeInFramesCapture) {
16516  continue; /* Nothing available. Keep waiting. */
16517  }
16518 
16519  /* Map the data buffer in preparation for sending to the client. */
16520  mappedDeviceBufferSizeInFramesCapture = framesAvailableCapture;
16521  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
16522  if (FAILED(hr)) {
16523  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));
16524  exitLoop = MA_TRUE;
16525  break;
16526  }
16527 
16528  /* Overrun detection. */
16529  if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) != 0) {
16530  /* Glitched. Probably due to an overrun. */
16531  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Data discontinuity (possible overrun). framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
16532 
16533  /*
16534  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
16535  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
16536  last period.
16537  */
16538  if (framesAvailableCapture >= pDevice->wasapi.actualPeriodSizeInFramesCapture) {
16539  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Synchronizing capture stream. ");
16540  do
16541  {
16542  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
16543  if (FAILED(hr)) {
16544  break;
16545  }
16546 
16547  framesAvailableCapture -= mappedDeviceBufferSizeInFramesCapture;
16548 
16549  if (framesAvailableCapture > 0) {
16550  mappedDeviceBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
16551  hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedDeviceBufferCapture, &mappedDeviceBufferSizeInFramesCapture, &flagsCapture, NULL, NULL);
16552  if (FAILED(hr)) {
16553  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));
16554  exitLoop = MA_TRUE;
16555  break;
16556  }
16557  } else {
16558  pMappedDeviceBufferCapture = NULL;
16559  mappedDeviceBufferSizeInFramesCapture = 0;
16560  }
16561  } while (framesAvailableCapture > periodSizeInFramesCapture);
16562  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedDeviceBufferSizeInFramesCapture);
16563  }
16564  } else {
16565  #ifdef MA_DEBUG_OUTPUT
16566  if (flagsCapture != 0) {
16567  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Capture Flags: %ld\n", flagsCapture);
16568  }
16569  #endif
16570  }
16571 
16572  /* We should have a buffer at this point, but let's just do a sanity check anyway. */
16573  if (mappedDeviceBufferSizeInFramesCapture > 0 && pMappedDeviceBufferCapture != NULL) {
16574  ma_device__send_frames_to_client(pDevice, mappedDeviceBufferSizeInFramesCapture, pMappedDeviceBufferCapture);
16575 
16576  /* At this point we're done with the buffer. */
16577  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
16578  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. */
16579  mappedDeviceBufferSizeInFramesCapture = 0;
16580  if (FAILED(hr)) {
16581  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.");
16582  exitLoop = MA_TRUE;
16583  break;
16584  }
16585  }
16586  } break;
16587 
16588 
16589 
16591  {
16592  ma_uint32 framesAvailablePlayback;
16593 
16594  /* Check how much space is available. If this returns 0 we just keep waiting. */
16595  result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
16596  if (result != MA_SUCCESS) {
16597  exitLoop = MA_TRUE;
16598  break;
16599  }
16600 
16601  if (framesAvailablePlayback >= pDevice->wasapi.periodSizeInFramesPlayback) {
16602  /* Map a the data buffer in preparation for the callback. */
16603  hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedDeviceBufferPlayback);
16604  if (FAILED(hr)) {
16605  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));
16606  exitLoop = MA_TRUE;
16607  break;
16608  }
16609 
16610  /* We should have a buffer at this point. */
16611  ma_device__read_frames_from_client(pDevice, framesAvailablePlayback, pMappedDeviceBufferPlayback);
16612 
16613  /* At this point we're done writing to the device and we just need to release the buffer. */
16614  hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, 0);
16615  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. */
16616  mappedDeviceBufferSizeInFramesPlayback = 0;
16617 
16618  if (FAILED(hr)) {
16619  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));
16620  exitLoop = MA_TRUE;
16621  break;
16622  }
16623 
16624  framesWrittenToPlaybackDevice += framesAvailablePlayback;
16625  }
16626 
16627  if (!c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) {
16628  hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
16629  if (FAILED(hr)) {
16630  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.", ma_result_from_HRESULT(hr));
16631  exitLoop = MA_TRUE;
16632  break;
16633  }
16634 
16635  c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_TRUE);
16636  }
16637 
16638  /* Make sure we don't wait on the event before we've started the device or we may end up deadlocking. */
16639  if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
16640  exitLoop = MA_TRUE;
16641  break; /* Wait failed. Probably timed out. */
16642  }
16643  } break;
16644 
16645  default: return MA_INVALID_ARGS;
16646  }
16647  }
16648 
16649  /* Here is where the device needs to be stopped. */
16650  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
16651  /* Any mapped buffers need to be released. */
16652  if (pMappedDeviceBufferCapture != NULL) {
16653  hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedDeviceBufferSizeInFramesCapture);
16654  }
16655  }
16656 
16657  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
16658  /* Any mapped buffers need to be released. */
16659  if (pMappedDeviceBufferPlayback != NULL) {
16660  hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedDeviceBufferSizeInFramesPlayback, 0);
16661  }
16662  }
16663 
16664  return MA_SUCCESS;
16665 }
16666 
16667 static ma_result ma_device_data_loop_wakeup__wasapi(ma_device* pDevice)
16668 {
16669  MA_ASSERT(pDevice != NULL);
16670 
16671  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
16672  SetEvent((HANDLE)pDevice->wasapi.hEventCapture);
16673  }
16674 
16675  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
16676  SetEvent((HANDLE)pDevice->wasapi.hEventPlayback);
16677  }
16678 
16679  return MA_SUCCESS;
16680 }
16681 
16682 
16683 static ma_result ma_context_uninit__wasapi(ma_context* pContext)
16684 {
16685  MA_ASSERT(pContext != NULL);
16686  MA_ASSERT(pContext->backend == ma_backend_wasapi);
16687 
16688  if (pContext->wasapi.commandThread != NULL) {
16689  ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_QUIT__WASAPI);
16690  ma_context_post_command__wasapi(pContext, &cmd);
16691  ma_thread_wait(&pContext->wasapi.commandThread);
16692 
16693  /* Only after the thread has been terminated can we uninitialize the sync objects for the command thread. */
16694  ma_semaphore_uninit(&pContext->wasapi.commandSem);
16695  ma_mutex_uninit(&pContext->wasapi.commandLock);
16696  }
16697 
16698  return MA_SUCCESS;
16699 }
16700 
16701 static ma_result ma_context_init__wasapi(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
16702 {
16703  ma_result result = MA_SUCCESS;
16704 
16705  MA_ASSERT(pContext != NULL);
16706 
16707  (void)pConfig;
16708 
16709 #ifdef MA_WIN32_DESKTOP
16710  /*
16711  WASAPI is only supported in Vista SP1 and newer. The reason for SP1 and not the base version of Vista is that event-driven
16712  exclusive mode does not work until SP1.
16713 
16714  Unfortunately older compilers don't define these functions so we need to dynamically load them in order to avoid a link error.
16715  */
16716  {
16717  ma_OSVERSIONINFOEXW osvi;
16718  ma_handle kernel32DLL;
16719  ma_PFNVerifyVersionInfoW _VerifyVersionInfoW;
16720  ma_PFNVerSetConditionMask _VerSetConditionMask;
16721 
16722  kernel32DLL = ma_dlopen(pContext, "kernel32.dll");
16723  if (kernel32DLL == NULL) {
16724  return MA_NO_BACKEND;
16725  }
16726 
16727  _VerifyVersionInfoW = (ma_PFNVerifyVersionInfoW )ma_dlsym(pContext, kernel32DLL, "VerifyVersionInfoW");
16728  _VerSetConditionMask = (ma_PFNVerSetConditionMask)ma_dlsym(pContext, kernel32DLL, "VerSetConditionMask");
16729  if (_VerifyVersionInfoW == NULL || _VerSetConditionMask == NULL) {
16730  ma_dlclose(pContext, kernel32DLL);
16731  return MA_NO_BACKEND;
16732  }
16733 
16734  MA_ZERO_OBJECT(&osvi);
16735  osvi.dwOSVersionInfoSize = sizeof(osvi);
16736  osvi.dwMajorVersion = ((MA_WIN32_WINNT_VISTA >> 8) & 0xFF);
16737  osvi.dwMinorVersion = ((MA_WIN32_WINNT_VISTA >> 0) & 0xFF);
16738  osvi.wServicePackMajor = 1;
16739  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))) {
16740  result = MA_SUCCESS;
16741  } else {
16742  result = MA_NO_BACKEND;
16743  }
16744 
16745  ma_dlclose(pContext, kernel32DLL);
16746  }
16747 #endif
16748 
16749  if (result != MA_SUCCESS) {
16750  return result;
16751  }
16752 
16753  MA_ZERO_OBJECT(&pContext->wasapi);
16754 
16755  /*
16756  Annoyingly, WASAPI does not allow you to release an IAudioClient object from a different thread
16757  than the one that retrieved it with GetService(). This can result in a deadlock in two
16758  situations:
16759 
16760  1) When calling ma_device_uninit() from a different thread to ma_device_init(); and
16761  2) When uninitializing and reinitializing the internal IAudioClient object in response to
16762  automatic stream routing.
16763 
16764  We could define ma_device_uninit() such that it must be called on the same thread as
16765  ma_device_init(). We could also just not release the IAudioClient when performing automatic
16766  stream routing to avoid the deadlock. Neither of these are acceptable solutions in my view so
16767  we're going to have to work around this with a worker thread. This is not ideal, but I can't
16768  think of a better way to do this.
16769 
16770  More information about this can be found here:
16771 
16772  https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudiorenderclient
16773 
16774  Note this section:
16775 
16776  When releasing an IAudioRenderClient interface instance, the client must call the interface's
16777  Release method from the same thread as the call to IAudioClient::GetService that created the
16778  object.
16779  */
16780  {
16781  result = ma_mutex_init(&pContext->wasapi.commandLock);
16782  if (result != MA_SUCCESS) {
16783  return result;
16784  }
16785 
16786  result = ma_semaphore_init(0, &pContext->wasapi.commandSem);
16787  if (result != MA_SUCCESS) {
16788  ma_mutex_uninit(&pContext->wasapi.commandLock);
16789  return result;
16790  }
16791 
16792  result = ma_thread_create(&pContext->wasapi.commandThread, ma_thread_priority_normal, 0, ma_context_command_thread__wasapi, pContext, &pContext->allocationCallbacks);
16793  if (result != MA_SUCCESS) {
16794  ma_semaphore_uninit(&pContext->wasapi.commandSem);
16795  ma_mutex_uninit(&pContext->wasapi.commandLock);
16796  return result;
16797  }
16798  }
16799 
16800 
16801  pCallbacks->onContextInit = ma_context_init__wasapi;
16802  pCallbacks->onContextUninit = ma_context_uninit__wasapi;
16803  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__wasapi;
16804  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__wasapi;
16805  pCallbacks->onDeviceInit = ma_device_init__wasapi;
16806  pCallbacks->onDeviceUninit = ma_device_uninit__wasapi;
16807  pCallbacks->onDeviceStart = ma_device_start__wasapi;
16808  pCallbacks->onDeviceStop = ma_device_stop__wasapi;
16809  pCallbacks->onDeviceRead = NULL; /* Not used. Reading is done manually in the audio thread. */
16810  pCallbacks->onDeviceWrite = NULL; /* Not used. Writing is done manually in the audio thread. */
16811  pCallbacks->onDeviceDataLoop = ma_device_data_loop__wasapi;
16812  pCallbacks->onDeviceDataLoopWakeup = ma_device_data_loop_wakeup__wasapi;
16813 
16814  return MA_SUCCESS;
16815 }
16816 #endif
16817 
16818 /******************************************************************************
16819 
16820 DirectSound Backend
16821 
16822 ******************************************************************************/
16823 #ifdef MA_HAS_DSOUND
16824 /*#include <dsound.h>*/
16825 
16826 /*static const GUID MA_GUID_IID_DirectSoundNotify = {0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16}};*/
16827 
16828 /* miniaudio only uses priority or exclusive modes. */
16829 #define MA_DSSCL_NORMAL 1
16830 #define MA_DSSCL_PRIORITY 2
16831 #define MA_DSSCL_EXCLUSIVE 3
16832 #define MA_DSSCL_WRITEPRIMARY 4
16833 
16834 #define MA_DSCAPS_PRIMARYMONO 0x00000001
16835 #define MA_DSCAPS_PRIMARYSTEREO 0x00000002
16836 #define MA_DSCAPS_PRIMARY8BIT 0x00000004
16837 #define MA_DSCAPS_PRIMARY16BIT 0x00000008
16838 #define MA_DSCAPS_CONTINUOUSRATE 0x00000010
16839 #define MA_DSCAPS_EMULDRIVER 0x00000020
16840 #define MA_DSCAPS_CERTIFIED 0x00000040
16841 #define MA_DSCAPS_SECONDARYMONO 0x00000100
16842 #define MA_DSCAPS_SECONDARYSTEREO 0x00000200
16843 #define MA_DSCAPS_SECONDARY8BIT 0x00000400
16844 #define MA_DSCAPS_SECONDARY16BIT 0x00000800
16845 
16846 #define MA_DSBCAPS_PRIMARYBUFFER 0x00000001
16847 #define MA_DSBCAPS_STATIC 0x00000002
16848 #define MA_DSBCAPS_LOCHARDWARE 0x00000004
16849 #define MA_DSBCAPS_LOCSOFTWARE 0x00000008
16850 #define MA_DSBCAPS_CTRL3D 0x00000010
16851 #define MA_DSBCAPS_CTRLFREQUENCY 0x00000020
16852 #define MA_DSBCAPS_CTRLPAN 0x00000040
16853 #define MA_DSBCAPS_CTRLVOLUME 0x00000080
16854 #define MA_DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100
16855 #define MA_DSBCAPS_CTRLFX 0x00000200
16856 #define MA_DSBCAPS_STICKYFOCUS 0x00004000
16857 #define MA_DSBCAPS_GLOBALFOCUS 0x00008000
16858 #define MA_DSBCAPS_GETCURRENTPOSITION2 0x00010000
16859 #define MA_DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000
16860 #define MA_DSBCAPS_LOCDEFER 0x00040000
16861 #define MA_DSBCAPS_TRUEPLAYPOSITION 0x00080000
16862 
16863 #define MA_DSBPLAY_LOOPING 0x00000001
16864 #define MA_DSBPLAY_LOCHARDWARE 0x00000002
16865 #define MA_DSBPLAY_LOCSOFTWARE 0x00000004
16866 #define MA_DSBPLAY_TERMINATEBY_TIME 0x00000008
16867 #define MA_DSBPLAY_TERMINATEBY_DISTANCE 0x00000010
16868 #define MA_DSBPLAY_TERMINATEBY_PRIORITY 0x00000020
16869 
16870 #define MA_DSCBSTART_LOOPING 0x00000001
16871 
16872 typedef struct
16873 {
16874  DWORD dwSize;
16875  DWORD dwFlags;
16876  DWORD dwBufferBytes;
16877  DWORD dwReserved;
16878  WAVEFORMATEX* lpwfxFormat;
16879  GUID guid3DAlgorithm;
16880 } MA_DSBUFFERDESC;
16881 
16882 typedef struct
16883 {
16884  DWORD dwSize;
16885  DWORD dwFlags;
16886  DWORD dwBufferBytes;
16887  DWORD dwReserved;
16888  WAVEFORMATEX* lpwfxFormat;
16889  DWORD dwFXCount;
16890  void* lpDSCFXDesc; /* <-- miniaudio doesn't use this, so set to void*. */
16891 } MA_DSCBUFFERDESC;
16892 
16893 typedef struct
16894 {
16895  DWORD dwSize;
16896  DWORD dwFlags;
16897  DWORD dwMinSecondarySampleRate;
16898  DWORD dwMaxSecondarySampleRate;
16899  DWORD dwPrimaryBuffers;
16900  DWORD dwMaxHwMixingAllBuffers;
16901  DWORD dwMaxHwMixingStaticBuffers;
16902  DWORD dwMaxHwMixingStreamingBuffers;
16903  DWORD dwFreeHwMixingAllBuffers;
16904  DWORD dwFreeHwMixingStaticBuffers;
16905  DWORD dwFreeHwMixingStreamingBuffers;
16906  DWORD dwMaxHw3DAllBuffers;
16907  DWORD dwMaxHw3DStaticBuffers;
16908  DWORD dwMaxHw3DStreamingBuffers;
16909  DWORD dwFreeHw3DAllBuffers;
16910  DWORD dwFreeHw3DStaticBuffers;
16911  DWORD dwFreeHw3DStreamingBuffers;
16912  DWORD dwTotalHwMemBytes;
16913  DWORD dwFreeHwMemBytes;
16914  DWORD dwMaxContigFreeHwMemBytes;
16915  DWORD dwUnlockTransferRateHwBuffers;
16916  DWORD dwPlayCpuOverheadSwBuffers;
16917  DWORD dwReserved1;
16918  DWORD dwReserved2;
16919 } MA_DSCAPS;
16920 
16921 typedef struct
16922 {
16923  DWORD dwSize;
16924  DWORD dwFlags;
16925  DWORD dwBufferBytes;
16926  DWORD dwUnlockTransferRate;
16927  DWORD dwPlayCpuOverhead;
16928 } MA_DSBCAPS;
16929 
16930 typedef struct
16931 {
16932  DWORD dwSize;
16933  DWORD dwFlags;
16934  DWORD dwFormats;
16935  DWORD dwChannels;
16936 } MA_DSCCAPS;
16937 
16938 typedef struct
16939 {
16940  DWORD dwSize;
16941  DWORD dwFlags;
16942  DWORD dwBufferBytes;
16943  DWORD dwReserved;
16944 } MA_DSCBCAPS;
16945 
16946 typedef struct
16947 {
16948  DWORD dwOffset;
16949  HANDLE hEventNotify;
16950 } MA_DSBPOSITIONNOTIFY;
16951 
16952 typedef struct ma_IDirectSound ma_IDirectSound;
16953 typedef struct ma_IDirectSoundBuffer ma_IDirectSoundBuffer;
16954 typedef struct ma_IDirectSoundCapture ma_IDirectSoundCapture;
16955 typedef struct ma_IDirectSoundCaptureBuffer ma_IDirectSoundCaptureBuffer;
16956 typedef struct ma_IDirectSoundNotify ma_IDirectSoundNotify;
16957 
16958 
16959 /*
16960 COM objects. The way these work is that you have a vtable (a list of function pointers, kind of
16961 like how C++ works internally), and then you have a structure with a single member, which is a
16962 pointer to the vtable. The vtable is where the methods of the object are defined. Methods need
16963 to be in a specific order, and parent classes need to have their methods declared first.
16964 */
16965 
16966 /* IDirectSound */
16967 typedef struct
16968 {
16969  /* IUnknown */
16970  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSound* pThis, const IID* const riid, void** ppObject);
16971  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSound* pThis);
16972  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSound* pThis);
16973 
16974  /* IDirectSound */
16975  HRESULT (STDMETHODCALLTYPE * CreateSoundBuffer) (ma_IDirectSound* pThis, const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer, void* pUnkOuter);
16976  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps);
16977  HRESULT (STDMETHODCALLTYPE * DuplicateSoundBuffer)(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate);
16978  HRESULT (STDMETHODCALLTYPE * SetCooperativeLevel) (ma_IDirectSound* pThis, HWND hwnd, DWORD dwLevel);
16979  HRESULT (STDMETHODCALLTYPE * Compact) (ma_IDirectSound* pThis);
16980  HRESULT (STDMETHODCALLTYPE * GetSpeakerConfig) (ma_IDirectSound* pThis, DWORD* pSpeakerConfig);
16981  HRESULT (STDMETHODCALLTYPE * SetSpeakerConfig) (ma_IDirectSound* pThis, DWORD dwSpeakerConfig);
16982  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSound* pThis, const GUID* pGuidDevice);
16983 } ma_IDirectSoundVtbl;
16984 struct ma_IDirectSound
16985 {
16986  ma_IDirectSoundVtbl* lpVtbl;
16987 };
16988 static MA_INLINE HRESULT ma_IDirectSound_QueryInterface(ma_IDirectSound* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
16989 static MA_INLINE ULONG ma_IDirectSound_AddRef(ma_IDirectSound* pThis) { return pThis->lpVtbl->AddRef(pThis); }
16990 static MA_INLINE ULONG ma_IDirectSound_Release(ma_IDirectSound* pThis) { return pThis->lpVtbl->Release(pThis); }
16991 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); }
16992 static MA_INLINE HRESULT ma_IDirectSound_GetCaps(ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSCaps); }
16993 static MA_INLINE HRESULT ma_IDirectSound_DuplicateSoundBuffer(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate) { return pThis->lpVtbl->DuplicateSoundBuffer(pThis, pDSBufferOriginal, ppDSBufferDuplicate); }
16994 static MA_INLINE HRESULT ma_IDirectSound_SetCooperativeLevel(ma_IDirectSound* pThis, HWND hwnd, DWORD dwLevel) { return pThis->lpVtbl->SetCooperativeLevel(pThis, hwnd, dwLevel); }
16995 static MA_INLINE HRESULT ma_IDirectSound_Compact(ma_IDirectSound* pThis) { return pThis->lpVtbl->Compact(pThis); }
16996 static MA_INLINE HRESULT ma_IDirectSound_GetSpeakerConfig(ma_IDirectSound* pThis, DWORD* pSpeakerConfig) { return pThis->lpVtbl->GetSpeakerConfig(pThis, pSpeakerConfig); }
16997 static MA_INLINE HRESULT ma_IDirectSound_SetSpeakerConfig(ma_IDirectSound* pThis, DWORD dwSpeakerConfig) { return pThis->lpVtbl->SetSpeakerConfig(pThis, dwSpeakerConfig); }
16998 static MA_INLINE HRESULT ma_IDirectSound_Initialize(ma_IDirectSound* pThis, const GUID* pGuidDevice) { return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
16999 
17000 
17001 /* IDirectSoundBuffer */
17002 typedef struct
17003 {
17004  /* IUnknown */
17005  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundBuffer* pThis, const IID* const riid, void** ppObject);
17006  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundBuffer* pThis);
17007  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundBuffer* pThis);
17008 
17009  /* IDirectSoundBuffer */
17010  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps);
17011  HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundBuffer* pThis, DWORD* pCurrentPlayCursor, DWORD* pCurrentWriteCursor);
17012  HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten);
17013  HRESULT (STDMETHODCALLTYPE * GetVolume) (ma_IDirectSoundBuffer* pThis, LONG* pVolume);
17014  HRESULT (STDMETHODCALLTYPE * GetPan) (ma_IDirectSoundBuffer* pThis, LONG* pPan);
17015  HRESULT (STDMETHODCALLTYPE * GetFrequency) (ma_IDirectSoundBuffer* pThis, DWORD* pFrequency);
17016  HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundBuffer* pThis, DWORD* pStatus);
17017  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound, const MA_DSBUFFERDESC* pDSBufferDesc);
17018  HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundBuffer* pThis, DWORD dwOffset, DWORD dwBytes, void** ppAudioPtr1, DWORD* pAudioBytes1, void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags);
17019  HRESULT (STDMETHODCALLTYPE * Play) (ma_IDirectSoundBuffer* pThis, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags);
17020  HRESULT (STDMETHODCALLTYPE * SetCurrentPosition)(ma_IDirectSoundBuffer* pThis, DWORD dwNewPosition);
17021  HRESULT (STDMETHODCALLTYPE * SetFormat) (ma_IDirectSoundBuffer* pThis, const WAVEFORMATEX* pFormat);
17022  HRESULT (STDMETHODCALLTYPE * SetVolume) (ma_IDirectSoundBuffer* pThis, LONG volume);
17023  HRESULT (STDMETHODCALLTYPE * SetPan) (ma_IDirectSoundBuffer* pThis, LONG pan);
17024  HRESULT (STDMETHODCALLTYPE * SetFrequency) (ma_IDirectSoundBuffer* pThis, DWORD dwFrequency);
17025  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundBuffer* pThis);
17026  HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundBuffer* pThis, void* pAudioPtr1, DWORD dwAudioBytes1, void* pAudioPtr2, DWORD dwAudioBytes2);
17027  HRESULT (STDMETHODCALLTYPE * Restore) (ma_IDirectSoundBuffer* pThis);
17028 } ma_IDirectSoundBufferVtbl;
17029 struct ma_IDirectSoundBuffer
17030 {
17031  ma_IDirectSoundBufferVtbl* lpVtbl;
17032 };
17033 static MA_INLINE HRESULT ma_IDirectSoundBuffer_QueryInterface(ma_IDirectSoundBuffer* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
17034 static MA_INLINE ULONG ma_IDirectSoundBuffer_AddRef(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->AddRef(pThis); }
17035 static MA_INLINE ULONG ma_IDirectSoundBuffer_Release(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->Release(pThis); }
17036 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetCaps(ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSBufferCaps); }
17037 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetCurrentPosition(ma_IDirectSoundBuffer* pThis, DWORD* pCurrentPlayCursor, DWORD* pCurrentWriteCursor) { return pThis->lpVtbl->GetCurrentPosition(pThis, pCurrentPlayCursor, pCurrentWriteCursor); }
17038 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetFormat(ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten) { return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
17039 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetVolume(ma_IDirectSoundBuffer* pThis, LONG* pVolume) { return pThis->lpVtbl->GetVolume(pThis, pVolume); }
17040 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetPan(ma_IDirectSoundBuffer* pThis, LONG* pPan) { return pThis->lpVtbl->GetPan(pThis, pPan); }
17041 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetFrequency(ma_IDirectSoundBuffer* pThis, DWORD* pFrequency) { return pThis->lpVtbl->GetFrequency(pThis, pFrequency); }
17042 static MA_INLINE HRESULT ma_IDirectSoundBuffer_GetStatus(ma_IDirectSoundBuffer* pThis, DWORD* pStatus) { return pThis->lpVtbl->GetStatus(pThis, pStatus); }
17043 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Initialize(ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound, const MA_DSBUFFERDESC* pDSBufferDesc) { return pThis->lpVtbl->Initialize(pThis, pDirectSound, pDSBufferDesc); }
17044 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); }
17045 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Play(ma_IDirectSoundBuffer* pThis, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) { return pThis->lpVtbl->Play(pThis, dwReserved1, dwPriority, dwFlags); }
17046 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetCurrentPosition(ma_IDirectSoundBuffer* pThis, DWORD dwNewPosition) { return pThis->lpVtbl->SetCurrentPosition(pThis, dwNewPosition); }
17047 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetFormat(ma_IDirectSoundBuffer* pThis, const WAVEFORMATEX* pFormat) { return pThis->lpVtbl->SetFormat(pThis, pFormat); }
17048 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetVolume(ma_IDirectSoundBuffer* pThis, LONG volume) { return pThis->lpVtbl->SetVolume(pThis, volume); }
17049 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetPan(ma_IDirectSoundBuffer* pThis, LONG pan) { return pThis->lpVtbl->SetPan(pThis, pan); }
17050 static MA_INLINE HRESULT ma_IDirectSoundBuffer_SetFrequency(ma_IDirectSoundBuffer* pThis, DWORD dwFrequency) { return pThis->lpVtbl->SetFrequency(pThis, dwFrequency); }
17051 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Stop(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->Stop(pThis); }
17052 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); }
17053 static MA_INLINE HRESULT ma_IDirectSoundBuffer_Restore(ma_IDirectSoundBuffer* pThis) { return pThis->lpVtbl->Restore(pThis); }
17054 
17055 
17056 /* IDirectSoundCapture */
17057 typedef struct
17058 {
17059  /* IUnknown */
17060  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCapture* pThis, const IID* const riid, void** ppObject);
17061  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCapture* pThis);
17062  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCapture* pThis);
17063 
17064  /* IDirectSoundCapture */
17065  HRESULT (STDMETHODCALLTYPE * CreateCaptureBuffer)(ma_IDirectSoundCapture* pThis, const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer, void* pUnkOuter);
17066  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps);
17067  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCapture* pThis, const GUID* pGuidDevice);
17068 } ma_IDirectSoundCaptureVtbl;
17069 struct ma_IDirectSoundCapture
17070 {
17071  ma_IDirectSoundCaptureVtbl* lpVtbl;
17072 };
17073 static MA_INLINE HRESULT ma_IDirectSoundCapture_QueryInterface(ma_IDirectSoundCapture* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
17074 static MA_INLINE ULONG ma_IDirectSoundCapture_AddRef(ma_IDirectSoundCapture* pThis) { return pThis->lpVtbl->AddRef(pThis); }
17075 static MA_INLINE ULONG ma_IDirectSoundCapture_Release(ma_IDirectSoundCapture* pThis) { return pThis->lpVtbl->Release(pThis); }
17076 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); }
17077 static MA_INLINE HRESULT ma_IDirectSoundCapture_GetCaps (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSCCaps); }
17078 static MA_INLINE HRESULT ma_IDirectSoundCapture_Initialize (ma_IDirectSoundCapture* pThis, const GUID* pGuidDevice) { return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
17079 
17080 
17081 /* IDirectSoundCaptureBuffer */
17082 typedef struct
17083 {
17084  /* IUnknown */
17085  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCaptureBuffer* pThis, const IID* const riid, void** ppObject);
17086  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCaptureBuffer* pThis);
17087  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCaptureBuffer* pThis);
17088 
17089  /* IDirectSoundCaptureBuffer */
17090  HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps);
17091  HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pCapturePosition, DWORD* pReadPosition);
17092  HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten);
17093  HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundCaptureBuffer* pThis, DWORD* pStatus);
17094  HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture, const MA_DSCBUFFERDESC* pDSCBufferDesc);
17095  HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundCaptureBuffer* pThis, DWORD dwOffset, DWORD dwBytes, void** ppAudioPtr1, DWORD* pAudioBytes1, void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags);
17096  HRESULT (STDMETHODCALLTYPE * Start) (ma_IDirectSoundCaptureBuffer* pThis, DWORD dwFlags);
17097  HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundCaptureBuffer* pThis);
17098  HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundCaptureBuffer* pThis, void* pAudioPtr1, DWORD dwAudioBytes1, void* pAudioPtr2, DWORD dwAudioBytes2);
17099 } ma_IDirectSoundCaptureBufferVtbl;
17100 struct ma_IDirectSoundCaptureBuffer
17101 {
17102  ma_IDirectSoundCaptureBufferVtbl* lpVtbl;
17103 };
17104 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_QueryInterface(ma_IDirectSoundCaptureBuffer* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
17105 static MA_INLINE ULONG ma_IDirectSoundCaptureBuffer_AddRef(ma_IDirectSoundCaptureBuffer* pThis) { return pThis->lpVtbl->AddRef(pThis); }
17106 static MA_INLINE ULONG ma_IDirectSoundCaptureBuffer_Release(ma_IDirectSoundCaptureBuffer* pThis) { return pThis->lpVtbl->Release(pThis); }
17107 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetCaps(ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps) { return pThis->lpVtbl->GetCaps(pThis, pDSCBCaps); }
17108 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetCurrentPosition(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pCapturePosition, DWORD* pReadPosition) { return pThis->lpVtbl->GetCurrentPosition(pThis, pCapturePosition, pReadPosition); }
17109 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetFormat(ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten) { return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
17110 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_GetStatus(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pStatus) { return pThis->lpVtbl->GetStatus(pThis, pStatus); }
17111 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Initialize(ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture, const MA_DSCBUFFERDESC* pDSCBufferDesc) { return pThis->lpVtbl->Initialize(pThis, pDirectSoundCapture, pDSCBufferDesc); }
17112 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); }
17113 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Start(ma_IDirectSoundCaptureBuffer* pThis, DWORD dwFlags) { return pThis->lpVtbl->Start(pThis, dwFlags); }
17114 static MA_INLINE HRESULT ma_IDirectSoundCaptureBuffer_Stop(ma_IDirectSoundCaptureBuffer* pThis) { return pThis->lpVtbl->Stop(pThis); }
17115 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); }
17116 
17117 
17118 /* IDirectSoundNotify */
17119 typedef struct
17120 {
17121  /* IUnknown */
17122  HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundNotify* pThis, const IID* const riid, void** ppObject);
17123  ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundNotify* pThis);
17124  ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundNotify* pThis);
17125 
17126  /* IDirectSoundNotify */
17127  HRESULT (STDMETHODCALLTYPE * SetNotificationPositions)(ma_IDirectSoundNotify* pThis, DWORD dwPositionNotifies, const MA_DSBPOSITIONNOTIFY* pPositionNotifies);
17128 } ma_IDirectSoundNotifyVtbl;
17129 struct ma_IDirectSoundNotify
17130 {
17131  ma_IDirectSoundNotifyVtbl* lpVtbl;
17132 };
17133 static MA_INLINE HRESULT ma_IDirectSoundNotify_QueryInterface(ma_IDirectSoundNotify* pThis, const IID* const riid, void** ppObject) { return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
17134 static MA_INLINE ULONG ma_IDirectSoundNotify_AddRef(ma_IDirectSoundNotify* pThis) { return pThis->lpVtbl->AddRef(pThis); }
17135 static MA_INLINE ULONG ma_IDirectSoundNotify_Release(ma_IDirectSoundNotify* pThis) { return pThis->lpVtbl->Release(pThis); }
17136 static MA_INLINE HRESULT ma_IDirectSoundNotify_SetNotificationPositions(ma_IDirectSoundNotify* pThis, DWORD dwPositionNotifies, const MA_DSBPOSITIONNOTIFY* pPositionNotifies) { return pThis->lpVtbl->SetNotificationPositions(pThis, dwPositionNotifies, pPositionNotifies); }
17137 
17138 
17139 typedef BOOL (CALLBACK * ma_DSEnumCallbackAProc) (LPGUID pDeviceGUID, LPCSTR pDeviceDescription, LPCSTR pModule, LPVOID pContext);
17140 typedef HRESULT (WINAPI * ma_DirectSoundCreateProc) (const GUID* pcGuidDevice, ma_IDirectSound** ppDS8, LPUNKNOWN pUnkOuter);
17141 typedef HRESULT (WINAPI * ma_DirectSoundEnumerateAProc) (ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
17142 typedef HRESULT (WINAPI * ma_DirectSoundCaptureCreateProc) (const GUID* pcGuidDevice, ma_IDirectSoundCapture** ppDSC8, LPUNKNOWN pUnkOuter);
17143 typedef HRESULT (WINAPI * ma_DirectSoundCaptureEnumerateAProc)(ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
17144 
17145 static ma_uint32 ma_get_best_sample_rate_within_range(ma_uint32 sampleRateMin, ma_uint32 sampleRateMax)
17146 {
17147  /* Normalize the range in case we were given something stupid. */
17148  if (sampleRateMin < (ma_uint32)ma_standard_sample_rate_min) {
17149  sampleRateMin = (ma_uint32)ma_standard_sample_rate_min;
17150  }
17151  if (sampleRateMax > (ma_uint32)ma_standard_sample_rate_max) {
17152  sampleRateMax = (ma_uint32)ma_standard_sample_rate_max;
17153  }
17154  if (sampleRateMin > sampleRateMax) {
17155  sampleRateMin = sampleRateMax;
17156  }
17157 
17158  if (sampleRateMin == sampleRateMax) {
17159  return sampleRateMax;
17160  } else {
17161  size_t iStandardRate;
17162  for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
17163  ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
17164  if (standardRate >= sampleRateMin && standardRate <= sampleRateMax) {
17165  return standardRate;
17166  }
17167  }
17168  }
17169 
17170  /* Should never get here. */
17172  return 0;
17173 }
17174 
17175 /*
17176 Retrieves the channel count and channel map for the given speaker configuration. If the speaker configuration is unknown,
17177 the channel count and channel map will be left unmodified.
17178 */
17179 static void ma_get_channels_from_speaker_config__dsound(DWORD speakerConfig, WORD* pChannelsOut, DWORD* pChannelMapOut)
17180 {
17181  WORD channels;
17182  DWORD channelMap;
17183 
17184  channels = 0;
17185  if (pChannelsOut != NULL) {
17186  channels = *pChannelsOut;
17187  }
17188 
17189  channelMap = 0;
17190  if (pChannelMapOut != NULL) {
17191  channelMap = *pChannelMapOut;
17192  }
17193 
17194  /*
17195  The speaker configuration is a combination of speaker config and speaker geometry. The lower 8 bits is what we care about. The upper
17196  16 bits is for the geometry.
17197  */
17198  switch ((BYTE)(speakerConfig)) {
17199  case 1 /*DSSPEAKER_HEADPHONE*/: channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break;
17200  case 2 /*DSSPEAKER_MONO*/: channels = 1; channelMap = SPEAKER_FRONT_CENTER; break;
17201  case 3 /*DSSPEAKER_QUAD*/: channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
17202  case 4 /*DSSPEAKER_STEREO*/: channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break;
17203  case 5 /*DSSPEAKER_SURROUND*/: channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER; break;
17204  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;
17205  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;
17206  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;
17207  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;
17208  default: break;
17209  }
17210 
17211  if (pChannelsOut != NULL) {
17212  *pChannelsOut = channels;
17213  }
17214 
17215  if (pChannelMapOut != NULL) {
17216  *pChannelMapOut = channelMap;
17217  }
17218 }
17219 
17220 
17221 static ma_result ma_context_create_IDirectSound__dsound(ma_context* pContext, ma_share_mode shareMode, const ma_device_id* pDeviceID, ma_IDirectSound** ppDirectSound)
17222 {
17223  ma_IDirectSound* pDirectSound;
17224  HWND hWnd;
17225  HRESULT hr;
17226 
17227  MA_ASSERT(pContext != NULL);
17228  MA_ASSERT(ppDirectSound != NULL);
17229 
17230  *ppDirectSound = NULL;
17231  pDirectSound = NULL;
17232 
17233  if (FAILED(((ma_DirectSoundCreateProc)pContext->dsound.DirectSoundCreate)((pDeviceID == NULL) ? NULL : (const GUID*)pDeviceID->dsound, &pDirectSound, NULL))) {
17234  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] DirectSoundCreate() failed for playback device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
17235  }
17236 
17237  /* The cooperative level must be set before doing anything else. */
17238  hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
17239  if (hWnd == NULL) {
17240  hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
17241  }
17242 
17243  hr = ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode == ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY);
17244  if (FAILED(hr)) {
17245  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_SetCooperateiveLevel() failed for playback device.", ma_result_from_HRESULT(hr));
17246  }
17247 
17248  *ppDirectSound = pDirectSound;
17249  return MA_SUCCESS;
17250 }
17251 
17252 static ma_result ma_context_create_IDirectSoundCapture__dsound(ma_context* pContext, ma_share_mode shareMode, const ma_device_id* pDeviceID, ma_IDirectSoundCapture** ppDirectSoundCapture)
17253 {
17254  ma_IDirectSoundCapture* pDirectSoundCapture;
17255  HRESULT hr;
17256 
17257  MA_ASSERT(pContext != NULL);
17258  MA_ASSERT(ppDirectSoundCapture != NULL);
17259 
17260  /* DirectSound does not support exclusive mode for capture. */
17261  if (shareMode == ma_share_mode_exclusive) {
17263  }
17264 
17265  *ppDirectSoundCapture = NULL;
17266  pDirectSoundCapture = NULL;
17267 
17268  hr = ((ma_DirectSoundCaptureCreateProc)pContext->dsound.DirectSoundCaptureCreate)((pDeviceID == NULL) ? NULL : (const GUID*)pDeviceID->dsound, &pDirectSoundCapture, NULL);
17269  if (FAILED(hr)) {
17270  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] DirectSoundCaptureCreate() failed for capture device.", ma_result_from_HRESULT(hr));
17271  }
17272 
17273  *ppDirectSoundCapture = pDirectSoundCapture;
17274  return MA_SUCCESS;
17275 }
17276 
17277 static ma_result ma_context_get_format_info_for_IDirectSoundCapture__dsound(ma_context* pContext, ma_IDirectSoundCapture* pDirectSoundCapture, WORD* pChannels, WORD* pBitsPerSample, DWORD* pSampleRate)
17278 {
17279  HRESULT hr;
17280  MA_DSCCAPS caps;
17281  WORD bitsPerSample;
17282  DWORD sampleRate;
17283 
17284  MA_ASSERT(pContext != NULL);
17285  MA_ASSERT(pDirectSoundCapture != NULL);
17286 
17287  if (pChannels) {
17288  *pChannels = 0;
17289  }
17290  if (pBitsPerSample) {
17291  *pBitsPerSample = 0;
17292  }
17293  if (pSampleRate) {
17294  *pSampleRate = 0;
17295  }
17296 
17297  MA_ZERO_OBJECT(&caps);
17298  caps.dwSize = sizeof(caps);
17299  hr = ma_IDirectSoundCapture_GetCaps(pDirectSoundCapture, &caps);
17300  if (FAILED(hr)) {
17301  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCapture_GetCaps() failed for capture device.", ma_result_from_HRESULT(hr));
17302  }
17303 
17304  if (pChannels) {
17305  *pChannels = (WORD)caps.dwChannels;
17306  }
17307 
17308  /* 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. */
17309  bitsPerSample = 16;
17310  sampleRate = 48000;
17311 
17312  if (caps.dwChannels == 1) {
17313  if ((caps.dwFormats & WAVE_FORMAT_48M16) != 0) {
17314  sampleRate = 48000;
17315  } else if ((caps.dwFormats & WAVE_FORMAT_44M16) != 0) {
17316  sampleRate = 44100;
17317  } else if ((caps.dwFormats & WAVE_FORMAT_2M16) != 0) {
17318  sampleRate = 22050;
17319  } else if ((caps.dwFormats & WAVE_FORMAT_1M16) != 0) {
17320  sampleRate = 11025;
17321  } else if ((caps.dwFormats & WAVE_FORMAT_96M16) != 0) {
17322  sampleRate = 96000;
17323  } else {
17324  bitsPerSample = 8;
17325  if ((caps.dwFormats & WAVE_FORMAT_48M08) != 0) {
17326  sampleRate = 48000;
17327  } else if ((caps.dwFormats & WAVE_FORMAT_44M08) != 0) {
17328  sampleRate = 44100;
17329  } else if ((caps.dwFormats & WAVE_FORMAT_2M08) != 0) {
17330  sampleRate = 22050;
17331  } else if ((caps.dwFormats & WAVE_FORMAT_1M08) != 0) {
17332  sampleRate = 11025;
17333  } else if ((caps.dwFormats & WAVE_FORMAT_96M08) != 0) {
17334  sampleRate = 96000;
17335  } else {
17336  bitsPerSample = 16; /* Didn't find it. Just fall back to 16-bit. */
17337  }
17338  }
17339  } else if (caps.dwChannels == 2) {
17340  if ((caps.dwFormats & WAVE_FORMAT_48S16) != 0) {
17341  sampleRate = 48000;
17342  } else if ((caps.dwFormats & WAVE_FORMAT_44S16) != 0) {
17343  sampleRate = 44100;
17344  } else if ((caps.dwFormats & WAVE_FORMAT_2S16) != 0) {
17345  sampleRate = 22050;
17346  } else if ((caps.dwFormats & WAVE_FORMAT_1S16) != 0) {
17347  sampleRate = 11025;
17348  } else if ((caps.dwFormats & WAVE_FORMAT_96S16) != 0) {
17349  sampleRate = 96000;
17350  } else {
17351  bitsPerSample = 8;
17352  if ((caps.dwFormats & WAVE_FORMAT_48S08) != 0) {
17353  sampleRate = 48000;
17354  } else if ((caps.dwFormats & WAVE_FORMAT_44S08) != 0) {
17355  sampleRate = 44100;
17356  } else if ((caps.dwFormats & WAVE_FORMAT_2S08) != 0) {
17357  sampleRate = 22050;
17358  } else if ((caps.dwFormats & WAVE_FORMAT_1S08) != 0) {
17359  sampleRate = 11025;
17360  } else if ((caps.dwFormats & WAVE_FORMAT_96S08) != 0) {
17361  sampleRate = 96000;
17362  } else {
17363  bitsPerSample = 16; /* Didn't find it. Just fall back to 16-bit. */
17364  }
17365  }
17366  }
17367 
17368  if (pBitsPerSample) {
17369  *pBitsPerSample = bitsPerSample;
17370  }
17371  if (pSampleRate) {
17372  *pSampleRate = sampleRate;
17373  }
17374 
17375  return MA_SUCCESS;
17376 }
17377 
17378 
17379 typedef struct
17380 {
17381  ma_context* pContext;
17382  ma_device_type deviceType;
17384  void* pUserData;
17385  ma_bool32 terminated;
17386 } ma_context_enumerate_devices_callback_data__dsound;
17387 
17388 static BOOL CALLBACK ma_context_enumerate_devices_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
17389 {
17390  ma_context_enumerate_devices_callback_data__dsound* pData = (ma_context_enumerate_devices_callback_data__dsound*)lpContext;
17391  ma_device_info deviceInfo;
17392 
17393  (void)lpcstrModule;
17394 
17395  MA_ZERO_OBJECT(&deviceInfo);
17396 
17397  /* ID. */
17398  if (lpGuid != NULL) {
17399  MA_COPY_MEMORY(deviceInfo.id.dsound, lpGuid, 16);
17400  } else {
17401  MA_ZERO_MEMORY(deviceInfo.id.dsound, 16);
17402  deviceInfo.isDefault = MA_TRUE;
17403  }
17404 
17405  /* Name / Description */
17406  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), lpcstrDescription, (size_t)-1);
17407 
17408 
17409  /* Call the callback function, but make sure we stop enumerating if the callee requested so. */
17410  MA_ASSERT(pData != NULL);
17411  pData->terminated = !pData->callback(pData->pContext, pData->deviceType, &deviceInfo, pData->pUserData);
17412  if (pData->terminated) {
17413  return FALSE; /* Stop enumeration. */
17414  } else {
17415  return TRUE; /* Continue enumeration. */
17416  }
17417 }
17418 
17419 static ma_result ma_context_enumerate_devices__dsound(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
17420 {
17421  ma_context_enumerate_devices_callback_data__dsound data;
17422 
17423  MA_ASSERT(pContext != NULL);
17424  MA_ASSERT(callback != NULL);
17425 
17426  data.pContext = pContext;
17427  data.callback = callback;
17428  data.pUserData = pUserData;
17429  data.terminated = MA_FALSE;
17430 
17431  /* Playback. */
17432  if (!data.terminated) {
17433  data.deviceType = ma_device_type_playback;
17434  ((ma_DirectSoundEnumerateAProc)pContext->dsound.DirectSoundEnumerateA)(ma_context_enumerate_devices_callback__dsound, &data);
17435  }
17436 
17437  /* Capture. */
17438  if (!data.terminated) {
17439  data.deviceType = ma_device_type_capture;
17440  ((ma_DirectSoundCaptureEnumerateAProc)pContext->dsound.DirectSoundCaptureEnumerateA)(ma_context_enumerate_devices_callback__dsound, &data);
17441  }
17442 
17443  return MA_SUCCESS;
17444 }
17445 
17446 
17447 typedef struct
17448 {
17449  const ma_device_id* pDeviceID;
17450  ma_device_info* pDeviceInfo;
17451  ma_bool32 found;
17452 } ma_context_get_device_info_callback_data__dsound;
17453 
17454 static BOOL CALLBACK ma_context_get_device_info_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
17455 {
17456  ma_context_get_device_info_callback_data__dsound* pData = (ma_context_get_device_info_callback_data__dsound*)lpContext;
17457  MA_ASSERT(pData != NULL);
17458 
17459  if ((pData->pDeviceID == NULL || ma_is_guid_null(pData->pDeviceID->dsound)) && (lpGuid == NULL || ma_is_guid_null(lpGuid))) {
17460  /* Default device. */
17461  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), lpcstrDescription, (size_t)-1);
17462  pData->pDeviceInfo->isDefault = MA_TRUE;
17463  pData->found = MA_TRUE;
17464  return FALSE; /* Stop enumeration. */
17465  } else {
17466  /* Not the default device. */
17467  if (lpGuid != NULL && pData->pDeviceID != NULL) {
17468  if (memcmp(pData->pDeviceID->dsound, lpGuid, sizeof(pData->pDeviceID->dsound)) == 0) {
17469  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), lpcstrDescription, (size_t)-1);
17470  pData->found = MA_TRUE;
17471  return FALSE; /* Stop enumeration. */
17472  }
17473  }
17474  }
17475 
17476  (void)lpcstrModule;
17477  return TRUE;
17478 }
17479 
17480 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)
17481 {
17482  ma_result result;
17483  HRESULT hr;
17484 
17485  if (pDeviceID != NULL) {
17486  ma_context_get_device_info_callback_data__dsound data;
17487 
17488  /* ID. */
17489  MA_COPY_MEMORY(pDeviceInfo->id.dsound, pDeviceID->dsound, 16);
17490 
17491  /* Name / Description. This is retrieved by enumerating over each device until we find that one that matches the input ID. */
17492  data.pDeviceID = pDeviceID;
17493  data.pDeviceInfo = pDeviceInfo;
17494  data.found = MA_FALSE;
17495  if (deviceType == ma_device_type_playback) {
17496  ((ma_DirectSoundEnumerateAProc)pContext->dsound.DirectSoundEnumerateA)(ma_context_get_device_info_callback__dsound, &data);
17497  } else {
17498  ((ma_DirectSoundCaptureEnumerateAProc)pContext->dsound.DirectSoundCaptureEnumerateA)(ma_context_get_device_info_callback__dsound, &data);
17499  }
17500 
17501  if (!data.found) {
17502  return MA_NO_DEVICE;
17503  }
17504  } else {
17505  /* 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. */
17506 
17507  /* ID */
17508  MA_ZERO_MEMORY(pDeviceInfo->id.dsound, 16);
17509 
17510  /* Name / Description */
17511  if (deviceType == ma_device_type_playback) {
17512  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
17513  } else {
17514  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
17515  }
17516 
17517  pDeviceInfo->isDefault = MA_TRUE;
17518  }
17519 
17520  /* Retrieving detailed information is slightly different depending on the device type. */
17521  if (deviceType == ma_device_type_playback) {
17522  /* Playback. */
17523  ma_IDirectSound* pDirectSound;
17524  MA_DSCAPS caps;
17525  WORD channels;
17526 
17527  result = ma_context_create_IDirectSound__dsound(pContext, ma_share_mode_shared, pDeviceID, &pDirectSound);
17528  if (result != MA_SUCCESS) {
17529  return result;
17530  }
17531 
17532  MA_ZERO_OBJECT(&caps);
17533  caps.dwSize = sizeof(caps);
17534  hr = ma_IDirectSound_GetCaps(pDirectSound, &caps);
17535  if (FAILED(hr)) {
17536  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_GetCaps() failed for playback device.", ma_result_from_HRESULT(hr));
17537  }
17538 
17539 
17540  /* Channels. Only a single channel count is reported for DirectSound. */
17541  if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
17542  /* It supports at least stereo, but could support more. */
17543  DWORD speakerConfig;
17544 
17545  channels = 2;
17546 
17547  /* Look at the speaker configuration to get a better idea on the channel count. */
17548  hr = ma_IDirectSound_GetSpeakerConfig(pDirectSound, &speakerConfig);
17549  if (SUCCEEDED(hr)) {
17550  ma_get_channels_from_speaker_config__dsound(speakerConfig, &channels, NULL);
17551  }
17552  } else {
17553  /* It does not support stereo, which means we are stuck with mono. */
17554  channels = 1;
17555  }
17556 
17557 
17558  /*
17559  In DirectSound, our native formats are centered around sample rates. All formats are supported, and we're only reporting a single channel
17560  count. However, DirectSound can report a range of supported sample rates. We're only going to include standard rates known by miniaudio
17561  in order to keep the size of this within reason.
17562  */
17563  if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
17564  /* Multiple sample rates are supported. We'll report in order of our preferred sample rates. */
17565  size_t iStandardSampleRate;
17566  for (iStandardSampleRate = 0; iStandardSampleRate < ma_countof(g_maStandardSampleRatePriorities); iStandardSampleRate += 1) {
17567  ma_uint32 sampleRate = g_maStandardSampleRatePriorities[iStandardSampleRate];
17568  if (sampleRate >= caps.dwMinSecondarySampleRate && sampleRate <= caps.dwMaxSecondarySampleRate) {
17569  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = ma_format_unknown;
17570  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
17571  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
17572  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
17573  pDeviceInfo->nativeDataFormatCount += 1;
17574  }
17575  }
17576  } else {
17577  /* Only a single sample rate is supported. */
17578  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = ma_format_unknown;
17579  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
17580  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = caps.dwMaxSecondarySampleRate;
17581  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
17582  pDeviceInfo->nativeDataFormatCount += 1;
17583  }
17584 
17585  ma_IDirectSound_Release(pDirectSound);
17586  } else {
17587  /*
17588  Capture. This is a little different to playback due to the say the supported formats are reported. Technically capture
17589  devices can support a number of different formats, but for simplicity and consistency with ma_device_init() I'm just
17590  reporting the best format.
17591  */
17592  ma_IDirectSoundCapture* pDirectSoundCapture;
17593  WORD channels;
17594  WORD bitsPerSample;
17595  DWORD sampleRate;
17596 
17597  result = ma_context_create_IDirectSoundCapture__dsound(pContext, ma_share_mode_shared, pDeviceID, &pDirectSoundCapture);
17598  if (result != MA_SUCCESS) {
17599  return result;
17600  }
17601 
17602  result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pContext, pDirectSoundCapture, &channels, &bitsPerSample, &sampleRate);
17603  if (result != MA_SUCCESS) {
17604  ma_IDirectSoundCapture_Release(pDirectSoundCapture);
17605  return result;
17606  }
17607 
17608  ma_IDirectSoundCapture_Release(pDirectSoundCapture);
17609 
17610  /* The format is always an integer format and is based on the bits per sample. */
17611  if (bitsPerSample == 8) {
17612  pDeviceInfo->formats[0] = ma_format_u8;
17613  } else if (bitsPerSample == 16) {
17614  pDeviceInfo->formats[0] = ma_format_s16;
17615  } else if (bitsPerSample == 24) {
17616  pDeviceInfo->formats[0] = ma_format_s24;
17617  } else if (bitsPerSample == 32) {
17618  pDeviceInfo->formats[0] = ma_format_s32;
17619  } else {
17620  return MA_FORMAT_NOT_SUPPORTED;
17621  }
17622 
17623  pDeviceInfo->nativeDataFormats[0].channels = channels;
17624  pDeviceInfo->nativeDataFormats[0].sampleRate = sampleRate;
17625  pDeviceInfo->nativeDataFormats[0].flags = 0;
17626  pDeviceInfo->nativeDataFormatCount = 1;
17627  }
17628 
17629  return MA_SUCCESS;
17630 }
17631 
17632 
17633 
17634 static ma_result ma_device_uninit__dsound(ma_device* pDevice)
17635 {
17636  MA_ASSERT(pDevice != NULL);
17637 
17638  if (pDevice->dsound.pCaptureBuffer != NULL) {
17639  ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
17640  }
17641  if (pDevice->dsound.pCapture != NULL) {
17642  ma_IDirectSoundCapture_Release((ma_IDirectSoundCapture*)pDevice->dsound.pCapture);
17643  }
17644 
17645  if (pDevice->dsound.pPlaybackBuffer != NULL) {
17646  ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
17647  }
17648  if (pDevice->dsound.pPlaybackPrimaryBuffer != NULL) {
17649  ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer);
17650  }
17651  if (pDevice->dsound.pPlayback != NULL) {
17652  ma_IDirectSound_Release((ma_IDirectSound*)pDevice->dsound.pPlayback);
17653  }
17654 
17655  return MA_SUCCESS;
17656 }
17657 
17658 static ma_result ma_config_to_WAVEFORMATEXTENSIBLE(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, const ma_channel* pChannelMap, WAVEFORMATEXTENSIBLE* pWF)
17659 {
17660  GUID subformat;
17661 
17662  if (format == ma_format_unknown) {
17663  format = MA_DEFAULT_FORMAT;
17664  }
17665 
17666  if (channels == 0) {
17667  channels = MA_DEFAULT_CHANNELS;
17668  }
17669 
17670  if (sampleRate == 0) {
17671  sampleRate = MA_DEFAULT_SAMPLE_RATE;
17672  }
17673 
17674  switch (format)
17675  {
17676  case ma_format_u8:
17677  case ma_format_s16:
17678  case ma_format_s24:
17679  /*case ma_format_s24_32:*/
17680  case ma_format_s32:
17681  {
17682  subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
17683  } break;
17684 
17685  case ma_format_f32:
17686  {
17687  subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
17688  } break;
17689 
17690  default:
17691  return MA_FORMAT_NOT_SUPPORTED;
17692  }
17693 
17694  MA_ZERO_OBJECT(pWF);
17695  pWF->Format.cbSize = sizeof(*pWF);
17696  pWF->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
17697  pWF->Format.nChannels = (WORD)channels;
17698  pWF->Format.nSamplesPerSec = (DWORD)sampleRate;
17699  pWF->Format.wBitsPerSample = (WORD)(ma_get_bytes_per_sample(format)*8);
17700  pWF->Format.nBlockAlign = (WORD)(pWF->Format.nChannels * pWF->Format.wBitsPerSample / 8);
17701  pWF->Format.nAvgBytesPerSec = pWF->Format.nBlockAlign * pWF->Format.nSamplesPerSec;
17702  pWF->Samples.wValidBitsPerSample = pWF->Format.wBitsPerSample;
17703  pWF->dwChannelMask = ma_channel_map_to_channel_mask__win32(pChannelMap, channels);
17704  pWF->SubFormat = subformat;
17705 
17706  return MA_SUCCESS;
17707 }
17708 
17709 static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__dsound(const ma_device_descriptor* pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
17710 {
17711  /* DirectSound has a minimum period size of 20ms. */
17712  ma_uint32 minPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(20, nativeSampleRate);
17713  ma_uint32 periodSizeInFrames;
17714 
17715  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, nativeSampleRate, performanceProfile);
17716  if (periodSizeInFrames < minPeriodSizeInFrames) {
17717  periodSizeInFrames = minPeriodSizeInFrames;
17718  }
17719 
17720  return periodSizeInFrames;
17721 }
17722 
17723 static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
17724 {
17725  ma_result result;
17726  HRESULT hr;
17727 
17728  MA_ASSERT(pDevice != NULL);
17729 
17730  MA_ZERO_OBJECT(&pDevice->dsound);
17731 
17732  if (pConfig->deviceType == ma_device_type_loopback) {
17734  }
17735 
17736  /*
17737  Unfortunately DirectSound uses different APIs and data structures for playback and catpure devices. We need to initialize
17738  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
17739  full-duplex mode.
17740  */
17741  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
17742  WAVEFORMATEXTENSIBLE wf;
17743  MA_DSCBUFFERDESC descDS;
17744  ma_uint32 periodSizeInFrames;
17745  ma_uint32 periodCount;
17746  char rawdata[1024]; /* <-- Ugly hack to avoid a malloc() due to a crappy DirectSound API. */
17747  WAVEFORMATEXTENSIBLE* pActualFormat;
17748 
17749  result = ma_config_to_WAVEFORMATEXTENSIBLE(pDescriptorCapture->format, pDescriptorCapture->channels, pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, &wf);
17750  if (result != MA_SUCCESS) {
17751  return result;
17752  }
17753 
17754  result = ma_context_create_IDirectSoundCapture__dsound(pDevice->pContext, pDescriptorCapture->shareMode, pDescriptorCapture->pDeviceID, (ma_IDirectSoundCapture**)&pDevice->dsound.pCapture);
17755  if (result != MA_SUCCESS) {
17756  ma_device_uninit__dsound(pDevice);
17757  return result;
17758  }
17759 
17760  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);
17761  if (result != MA_SUCCESS) {
17762  ma_device_uninit__dsound(pDevice);
17763  return result;
17764  }
17765 
17766  wf.Format.nBlockAlign = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
17767  wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
17768  wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
17769  wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
17770 
17771  /* The size of the buffer must be a clean multiple of the period count. */
17772  periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__dsound(pDescriptorCapture, wf.Format.nSamplesPerSec, pConfig->performanceProfile);
17773  periodCount = (pDescriptorCapture->periodCount > 0) ? pDescriptorCapture->periodCount : MA_DEFAULT_PERIODS;
17774 
17775  MA_ZERO_OBJECT(&descDS);
17776  descDS.dwSize = sizeof(descDS);
17777  descDS.dwFlags = 0;
17778  descDS.dwBufferBytes = periodSizeInFrames * periodCount * wf.Format.nBlockAlign;
17779  descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
17780  hr = ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer, NULL);
17781  if (FAILED(hr)) {
17782  ma_device_uninit__dsound(pDevice);
17783  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCapture_CreateCaptureBuffer() failed for capture device.", ma_result_from_HRESULT(hr));
17784  }
17785 
17786  /* Get the _actual_ properties of the buffer. */
17787  pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
17788  hr = ma_IDirectSoundCaptureBuffer_GetFormat((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, (WAVEFORMATEX*)pActualFormat, sizeof(rawdata), NULL);
17789  if (FAILED(hr)) {
17790  ma_device_uninit__dsound(pDevice);
17791  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));
17792  }
17793 
17794  /* We can now start setting the output data formats. */
17795  pDescriptorCapture->format = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
17796  pDescriptorCapture->channels = pActualFormat->Format.nChannels;
17797  pDescriptorCapture->sampleRate = pActualFormat->Format.nSamplesPerSec;
17798 
17799  /* Get the native channel map based on the channel mask. */
17800  if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
17801  ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
17802  } else {
17803  ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
17804  }
17805 
17806  /*
17807  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
17808  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.
17809  */
17810  if (periodSizeInFrames != (descDS.dwBufferBytes / ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) / periodCount)) {
17811  descDS.dwBufferBytes = periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) * periodCount;
17812  ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
17813 
17814  hr = ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer, NULL);
17815  if (FAILED(hr)) {
17816  ma_device_uninit__dsound(pDevice);
17817  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] Second attempt at IDirectSoundCapture_CreateCaptureBuffer() failed for capture device.", ma_result_from_HRESULT(hr));
17818  }
17819  }
17820 
17821  /* DirectSound should give us a buffer exactly the size we asked for. */
17822  pDescriptorCapture->periodSizeInFrames = periodSizeInFrames;
17823  pDescriptorCapture->periodCount = periodCount;
17824  }
17825 
17826  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
17827  WAVEFORMATEXTENSIBLE wf;
17828  MA_DSBUFFERDESC descDSPrimary;
17829  MA_DSCAPS caps;
17830  char rawdata[1024]; /* <-- Ugly hack to avoid a malloc() due to a crappy DirectSound API. */
17831  WAVEFORMATEXTENSIBLE* pActualFormat;
17832  ma_uint32 periodSizeInFrames;
17833  ma_uint32 periodCount;
17834  MA_DSBUFFERDESC descDS;
17835 
17836  result = ma_config_to_WAVEFORMATEXTENSIBLE(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &wf);
17837  if (result != MA_SUCCESS) {
17838  return result;
17839  }
17840 
17841  result = ma_context_create_IDirectSound__dsound(pDevice->pContext, pDescriptorPlayback->shareMode, pDescriptorPlayback->pDeviceID, (ma_IDirectSound**)&pDevice->dsound.pPlayback);
17842  if (result != MA_SUCCESS) {
17843  ma_device_uninit__dsound(pDevice);
17844  return result;
17845  }
17846 
17847  MA_ZERO_OBJECT(&descDSPrimary);
17848  descDSPrimary.dwSize = sizeof(MA_DSBUFFERDESC);
17849  descDSPrimary.dwFlags = MA_DSBCAPS_PRIMARYBUFFER | MA_DSBCAPS_CTRLVOLUME;
17850  hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDSPrimary, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackPrimaryBuffer, NULL);
17851  if (FAILED(hr)) {
17852  ma_device_uninit__dsound(pDevice);
17853  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_CreateSoundBuffer() failed for playback device's primary buffer.", ma_result_from_HRESULT(hr));
17854  }
17855 
17856 
17857  /* We may want to make some adjustments to the format if we are using defaults. */
17858  MA_ZERO_OBJECT(&caps);
17859  caps.dwSize = sizeof(caps);
17860  hr = ma_IDirectSound_GetCaps((ma_IDirectSound*)pDevice->dsound.pPlayback, &caps);
17861  if (FAILED(hr)) {
17862  ma_device_uninit__dsound(pDevice);
17863  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_GetCaps() failed for playback device.", ma_result_from_HRESULT(hr));
17864  }
17865 
17866  if (pDescriptorPlayback->channels == 0) {
17867  if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
17868  DWORD speakerConfig;
17869 
17870  /* It supports at least stereo, but could support more. */
17871  wf.Format.nChannels = 2;
17872 
17873  /* Look at the speaker configuration to get a better idea on the channel count. */
17874  if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig((ma_IDirectSound*)pDevice->dsound.pPlayback, &speakerConfig))) {
17875  ma_get_channels_from_speaker_config__dsound(speakerConfig, &wf.Format.nChannels, &wf.dwChannelMask);
17876  }
17877  } else {
17878  /* It does not support stereo, which means we are stuck with mono. */
17879  wf.Format.nChannels = 1;
17880  }
17881  }
17882 
17883  if (pDescriptorPlayback->sampleRate == 0) {
17884  /* We base the sample rate on the values returned by GetCaps(). */
17885  if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
17886  wf.Format.nSamplesPerSec = ma_get_best_sample_rate_within_range(caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate);
17887  } else {
17888  wf.Format.nSamplesPerSec = caps.dwMaxSecondarySampleRate;
17889  }
17890  }
17891 
17892  wf.Format.nBlockAlign = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
17893  wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
17894 
17895  /*
17896  From MSDN:
17897 
17898  The method succeeds even if the hardware does not support the requested format; DirectSound sets the buffer to the closest
17899  supported format. To determine whether this has happened, an application can call the GetFormat method for the primary buffer
17900  and compare the result with the format that was requested with the SetFormat method.
17901  */
17902  hr = ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)&wf);
17903  if (FAILED(hr)) {
17904  ma_device_uninit__dsound(pDevice);
17905  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));
17906  }
17907 
17908  /* Get the _actual_ properties of the buffer. */
17909  pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
17910  hr = ma_IDirectSoundBuffer_GetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)pActualFormat, sizeof(rawdata), NULL);
17911  if (FAILED(hr)) {
17912  ma_device_uninit__dsound(pDevice);
17913  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));
17914  }
17915 
17916  /* We now have enough information to start setting some output properties. */
17917  pDescriptorPlayback->format = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
17918  pDescriptorPlayback->channels = pActualFormat->Format.nChannels;
17919  pDescriptorPlayback->sampleRate = pActualFormat->Format.nSamplesPerSec;
17920 
17921  /* Get the internal channel map based on the channel mask. */
17922  if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
17923  ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
17924  } else {
17925  ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
17926  }
17927 
17928  /* The size of the buffer must be a clean multiple of the period count. */
17929  periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__dsound(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
17930  periodCount = (pDescriptorPlayback->periodCount > 0) ? pDescriptorPlayback->periodCount : MA_DEFAULT_PERIODS;
17931 
17932  /*
17933  Meaning of dwFlags (from MSDN):
17934 
17935  DSBCAPS_CTRLPOSITIONNOTIFY
17936  The buffer has position notification capability.
17937 
17938  DSBCAPS_GLOBALFOCUS
17939  With this flag set, an application using DirectSound can continue to play its buffers if the user switches focus to
17940  another application, even if the new application uses DirectSound.
17941 
17942  DSBCAPS_GETCURRENTPOSITION2
17943  In the first version of DirectSound, the play cursor was significantly ahead of the actual playing sound on emulated
17944  sound cards; it was directly behind the write cursor. Now, if the DSBCAPS_GETCURRENTPOSITION2 flag is specified, the
17945  application can get a more accurate play cursor.
17946  */
17947  MA_ZERO_OBJECT(&descDS);
17948  descDS.dwSize = sizeof(descDS);
17949  descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2;
17950  descDS.dwBufferBytes = periodSizeInFrames * periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels);
17951  descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
17952  hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer, NULL);
17953  if (FAILED(hr)) {
17954  ma_device_uninit__dsound(pDevice);
17955  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_CreateSoundBuffer() failed for playback device's secondary buffer.", ma_result_from_HRESULT(hr));
17956  }
17957 
17958  /* DirectSound should give us a buffer exactly the size we asked for. */
17959  pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
17960  pDescriptorPlayback->periodCount = periodCount;
17961  }
17962 
17963  return MA_SUCCESS;
17964 }
17965 
17966 
17967 static ma_result ma_device_data_loop__dsound(ma_device* pDevice)
17968 {
17969  ma_result result = MA_SUCCESS;
17970  ma_uint32 bpfDeviceCapture = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
17971  ma_uint32 bpfDevicePlayback = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
17972  HRESULT hr;
17973  DWORD lockOffsetInBytesCapture;
17974  DWORD lockSizeInBytesCapture;
17975  DWORD mappedSizeInBytesCapture;
17976  DWORD mappedDeviceFramesProcessedCapture;
17977  void* pMappedDeviceBufferCapture;
17978  DWORD lockOffsetInBytesPlayback;
17979  DWORD lockSizeInBytesPlayback;
17980  DWORD mappedSizeInBytesPlayback;
17981  void* pMappedDeviceBufferPlayback;
17982  DWORD prevReadCursorInBytesCapture = 0;
17983  DWORD prevPlayCursorInBytesPlayback = 0;
17984  ma_bool32 physicalPlayCursorLoopFlagPlayback = 0;
17985  DWORD virtualWriteCursorInBytesPlayback = 0;
17986  ma_bool32 virtualWriteCursorLoopFlagPlayback = 0;
17987  ma_bool32 isPlaybackDeviceStarted = MA_FALSE;
17988  ma_uint32 framesWrittenToPlaybackDevice = 0; /* For knowing whether or not the playback device needs to be started. */
17989  ma_uint32 waitTimeInMilliseconds = 1;
17990 
17991  MA_ASSERT(pDevice != NULL);
17992 
17993  /* The first thing to do is start the capture device. The playback device is only started after the first period is written. */
17994  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
17995  if (FAILED(ma_IDirectSoundCaptureBuffer_Start((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, MA_DSCBSTART_LOOPING))) {
17996  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCaptureBuffer_Start() failed.", MA_FAILED_TO_START_BACKEND_DEVICE);
17997  }
17998  }
17999 
18000  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
18001  switch (pDevice->type)
18002  {
18003  case ma_device_type_duplex:
18004  {
18005  DWORD physicalCaptureCursorInBytes;
18006  DWORD physicalReadCursorInBytes;
18007  hr = ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes);
18008  if (FAILED(hr)) {
18009  return ma_result_from_HRESULT(hr);
18010  }
18011 
18012  /* If nothing is available we just sleep for a bit and return from this iteration. */
18013  if (physicalReadCursorInBytes == prevReadCursorInBytesCapture) {
18014  ma_sleep(waitTimeInMilliseconds);
18015  continue; /* Nothing is available in the capture buffer. */
18016  }
18017 
18018  /*
18019  The current position has moved. We need to map all of the captured samples and write them to the playback device, making sure
18020  we don't return until every frame has been copied over.
18021  */
18022  if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
18023  /* The capture position has not looped. This is the simple case. */
18024  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
18025  lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
18026  } else {
18027  /*
18028  The capture position has looped. This is the more complex case. Map to the end of the buffer. If this does not return anything,
18029  do it again from the start.
18030  */
18031  if (prevReadCursorInBytesCapture < pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) {
18032  /* Lock up to the end of the buffer. */
18033  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
18034  lockSizeInBytesCapture = (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) - prevReadCursorInBytesCapture;
18035  } else {
18036  /* Lock starting from the start of the buffer. */
18037  lockOffsetInBytesCapture = 0;
18038  lockSizeInBytesCapture = physicalReadCursorInBytes;
18039  }
18040  }
18041 
18042  if (lockSizeInBytesCapture == 0) {
18043  ma_sleep(waitTimeInMilliseconds);
18044  continue; /* Nothing is available in the capture buffer. */
18045  }
18046 
18047  hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedDeviceBufferCapture, &mappedSizeInBytesCapture, NULL, NULL, 0);
18048  if (FAILED(hr)) {
18049  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));
18050  }
18051 
18052 
18053  /* 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. */
18054  mappedDeviceFramesProcessedCapture = 0;
18055 
18056  for (;;) { /* Keep writing to the playback device. */
18057  ma_uint8 inputFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
18058  ma_uint32 inputFramesInClientFormatCap = sizeof(inputFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
18059  ma_uint8 outputFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
18060  ma_uint32 outputFramesInClientFormatCap = sizeof(outputFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
18061  ma_uint32 outputFramesInClientFormatCount;
18062  ma_uint32 outputFramesInClientFormatConsumed = 0;
18063  ma_uint64 clientCapturedFramesToProcess = ma_min(inputFramesInClientFormatCap, outputFramesInClientFormatCap);
18064  ma_uint64 deviceCapturedFramesToProcess = (mappedSizeInBytesCapture / bpfDeviceCapture) - mappedDeviceFramesProcessedCapture;
18065  void* pRunningMappedDeviceBufferCapture = ma_offset_ptr(pMappedDeviceBufferCapture, mappedDeviceFramesProcessedCapture * bpfDeviceCapture);
18066 
18067  result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningMappedDeviceBufferCapture, &deviceCapturedFramesToProcess, inputFramesInClientFormat, &clientCapturedFramesToProcess);
18068  if (result != MA_SUCCESS) {
18069  break;
18070  }
18071 
18072  outputFramesInClientFormatCount = (ma_uint32)clientCapturedFramesToProcess;
18073  mappedDeviceFramesProcessedCapture += (ma_uint32)deviceCapturedFramesToProcess;
18074 
18075  ma_device__on_data(pDevice, outputFramesInClientFormat, inputFramesInClientFormat, (ma_uint32)clientCapturedFramesToProcess);
18076 
18077  /* 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. */
18078  for (;;) {
18079  ma_uint32 framesWrittenThisIteration;
18080  DWORD physicalPlayCursorInBytes;
18081  DWORD physicalWriteCursorInBytes;
18082  DWORD availableBytesPlayback;
18083  DWORD silentPaddingInBytes = 0; /* <-- Must be initialized to 0. */
18084 
18085  /* We need the physical play and write cursors. */
18086  if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
18087  break;
18088  }
18089 
18090  if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
18091  physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
18092  }
18093  prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
18094 
18095  /* If there's any bytes available for writing we can do that now. The space between the virtual cursor position and play cursor. */
18096  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
18097  /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
18098  if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
18099  availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
18100  availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
18101  } else {
18102  /* This is an error. */
18103  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);
18104  availableBytesPlayback = 0;
18105  }
18106  } else {
18107  /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
18108  if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
18109  availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
18110  } else {
18111  /* This is an error. */
18112  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);
18113  availableBytesPlayback = 0;
18114  }
18115  }
18116 
18117  /* If there's no room available for writing we need to wait for more. */
18118  if (availableBytesPlayback == 0) {
18119  /* If we haven't started the device yet, this will never get beyond 0. In this case we need to get the device started. */
18120  if (!isPlaybackDeviceStarted) {
18121  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
18122  if (FAILED(hr)) {
18123  ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
18124  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
18125  }
18126  isPlaybackDeviceStarted = MA_TRUE;
18127  } else {
18128  ma_sleep(waitTimeInMilliseconds);
18129  continue;
18130  }
18131  }
18132 
18133 
18134  /* 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. */
18135  lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
18136  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
18137  /* Same loop iteration. Go up to the end of the buffer. */
18138  lockSizeInBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
18139  } else {
18140  /* Different loop iterations. Go up to the physical play cursor. */
18141  lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
18142  }
18143 
18144  hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedDeviceBufferPlayback, &mappedSizeInBytesPlayback, NULL, NULL, 0);
18145  if (FAILED(hr)) {
18146  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));
18147  break;
18148  }
18149 
18150  /*
18151  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
18152  endless glitching due to it constantly running out of data.
18153  */
18154  if (isPlaybackDeviceStarted) {
18155  DWORD bytesQueuedForPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - availableBytesPlayback;
18156  if (bytesQueuedForPlayback < (pDevice->playback.internalPeriodSizeInFrames*bpfDevicePlayback)) {
18157  silentPaddingInBytes = (pDevice->playback.internalPeriodSizeInFrames*2*bpfDevicePlayback) - bytesQueuedForPlayback;
18158  if (silentPaddingInBytes > lockSizeInBytesPlayback) {
18159  silentPaddingInBytes = lockSizeInBytesPlayback;
18160  }
18161 
18162  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);
18163  }
18164  }
18165 
18166  /* At this point we have a buffer for output. */
18167  if (silentPaddingInBytes > 0) {
18168  MA_ZERO_MEMORY(pMappedDeviceBufferPlayback, silentPaddingInBytes);
18169  framesWrittenThisIteration = silentPaddingInBytes/bpfDevicePlayback;
18170  } else {
18171  ma_uint64 convertedFrameCountIn = (outputFramesInClientFormatCount - outputFramesInClientFormatConsumed);
18172  ma_uint64 convertedFrameCountOut = mappedSizeInBytesPlayback/bpfDevicePlayback;
18173  void* pConvertedFramesIn = ma_offset_ptr(outputFramesInClientFormat, outputFramesInClientFormatConsumed * bpfDevicePlayback);
18174  void* pConvertedFramesOut = pMappedDeviceBufferPlayback;
18175 
18176  result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pConvertedFramesIn, &convertedFrameCountIn, pConvertedFramesOut, &convertedFrameCountOut);
18177  if (result != MA_SUCCESS) {
18178  break;
18179  }
18180 
18181  outputFramesInClientFormatConsumed += (ma_uint32)convertedFrameCountOut;
18182  framesWrittenThisIteration = (ma_uint32)convertedFrameCountOut;
18183  }
18184 
18185 
18186  hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedDeviceBufferPlayback, framesWrittenThisIteration*bpfDevicePlayback, NULL, 0);
18187  if (FAILED(hr)) {
18188  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));
18189  break;
18190  }
18191 
18192  virtualWriteCursorInBytesPlayback += framesWrittenThisIteration*bpfDevicePlayback;
18193  if ((virtualWriteCursorInBytesPlayback/bpfDevicePlayback) == pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods) {
18194  virtualWriteCursorInBytesPlayback = 0;
18195  virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
18196  }
18197 
18198  /*
18199  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
18200  a bit of a buffer to prevent the playback buffer from getting starved.
18201  */
18202  framesWrittenToPlaybackDevice += framesWrittenThisIteration;
18203  if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= (pDevice->playback.internalPeriodSizeInFrames*2)) {
18204  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
18205  if (FAILED(hr)) {
18206  ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
18207  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
18208  }
18209  isPlaybackDeviceStarted = MA_TRUE;
18210  }
18211 
18212  if (framesWrittenThisIteration < mappedSizeInBytesPlayback/bpfDevicePlayback) {
18213  break; /* We're finished with the output data.*/
18214  }
18215  }
18216 
18217  if (clientCapturedFramesToProcess == 0) {
18218  break; /* We just consumed every input sample. */
18219  }
18220  }
18221 
18222 
18223  /* At this point we're done with the mapped portion of the capture buffer. */
18224  hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedDeviceBufferCapture, mappedSizeInBytesCapture, NULL, 0);
18225  if (FAILED(hr)) {
18226  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));
18227  }
18228  prevReadCursorInBytesCapture = (lockOffsetInBytesCapture + mappedSizeInBytesCapture);
18229  } break;
18230 
18231 
18232 
18234  {
18235  DWORD physicalCaptureCursorInBytes;
18236  DWORD physicalReadCursorInBytes;
18237  hr = ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes);
18238  if (FAILED(hr)) {
18239  return MA_ERROR;
18240  }
18241 
18242  /* If the previous capture position is the same as the current position we need to wait a bit longer. */
18243  if (prevReadCursorInBytesCapture == physicalReadCursorInBytes) {
18244  ma_sleep(waitTimeInMilliseconds);
18245  continue;
18246  }
18247 
18248  /* Getting here means we have capture data available. */
18249  if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
18250  /* The capture position has not looped. This is the simple case. */
18251  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
18252  lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
18253  } else {
18254  /*
18255  The capture position has looped. This is the more complex case. Map to the end of the buffer. If this does not return anything,
18256  do it again from the start.
18257  */
18258  if (prevReadCursorInBytesCapture < pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) {
18259  /* Lock up to the end of the buffer. */
18260  lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
18261  lockSizeInBytesCapture = (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) - prevReadCursorInBytesCapture;
18262  } else {
18263  /* Lock starting from the start of the buffer. */
18264  lockOffsetInBytesCapture = 0;
18265  lockSizeInBytesCapture = physicalReadCursorInBytes;
18266  }
18267  }
18268 
18269  if (lockSizeInBytesCapture < pDevice->capture.internalPeriodSizeInFrames) {
18270  ma_sleep(waitTimeInMilliseconds);
18271  continue; /* Nothing is available in the capture buffer. */
18272  }
18273 
18274  hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedDeviceBufferCapture, &mappedSizeInBytesCapture, NULL, NULL, 0);
18275  if (FAILED(hr)) {
18276  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));
18277  }
18278 
18279  #ifdef MA_DEBUG_OUTPUT
18280  if (lockSizeInBytesCapture != mappedSizeInBytesCapture) {
18281  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Capture) lockSizeInBytesCapture=%ld != mappedSizeInBytesCapture=%ld\n", lockSizeInBytesCapture, mappedSizeInBytesCapture);
18282  }
18283  #endif
18284 
18285  ma_device__send_frames_to_client(pDevice, mappedSizeInBytesCapture/bpfDeviceCapture, pMappedDeviceBufferCapture);
18286 
18287  hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedDeviceBufferCapture, mappedSizeInBytesCapture, NULL, 0);
18288  if (FAILED(hr)) {
18289  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));
18290  }
18291  prevReadCursorInBytesCapture = lockOffsetInBytesCapture + mappedSizeInBytesCapture;
18292 
18293  if (prevReadCursorInBytesCapture == (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture)) {
18294  prevReadCursorInBytesCapture = 0;
18295  }
18296  } break;
18297 
18298 
18299 
18301  {
18302  DWORD availableBytesPlayback;
18303  DWORD physicalPlayCursorInBytes;
18304  DWORD physicalWriteCursorInBytes;
18305  hr = ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes);
18306  if (FAILED(hr)) {
18307  break;
18308  }
18309 
18310  if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
18311  physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
18312  }
18313  prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
18314 
18315  /* If there's any bytes available for writing we can do that now. The space between the virtual cursor position and play cursor. */
18316  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
18317  /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
18318  if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
18319  availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
18320  availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
18321  } else {
18322  /* This is an error. */
18323  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);
18324  availableBytesPlayback = 0;
18325  }
18326  } else {
18327  /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
18328  if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
18329  availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
18330  } else {
18331  /* This is an error. */
18332  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);
18333  availableBytesPlayback = 0;
18334  }
18335  }
18336 
18337  /* If there's no room available for writing we need to wait for more. */
18338  if (availableBytesPlayback < pDevice->playback.internalPeriodSizeInFrames) {
18339  /* If we haven't started the device yet, this will never get beyond 0. In this case we need to get the device started. */
18340  if (availableBytesPlayback == 0 && !isPlaybackDeviceStarted) {
18341  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
18342  if (FAILED(hr)) {
18343  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
18344  }
18345  isPlaybackDeviceStarted = MA_TRUE;
18346  } else {
18347  ma_sleep(waitTimeInMilliseconds);
18348  continue;
18349  }
18350  }
18351 
18352  /* 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. */
18353  lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
18354  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
18355  /* Same loop iteration. Go up to the end of the buffer. */
18356  lockSizeInBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
18357  } else {
18358  /* Different loop iterations. Go up to the physical play cursor. */
18359  lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
18360  }
18361 
18362  hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedDeviceBufferPlayback, &mappedSizeInBytesPlayback, NULL, NULL, 0);
18363  if (FAILED(hr)) {
18364  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));
18365  break;
18366  }
18367 
18368  /* At this point we have a buffer for output. */
18369  ma_device__read_frames_from_client(pDevice, (mappedSizeInBytesPlayback/bpfDevicePlayback), pMappedDeviceBufferPlayback);
18370 
18371  hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedDeviceBufferPlayback, mappedSizeInBytesPlayback, NULL, 0);
18372  if (FAILED(hr)) {
18373  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));
18374  break;
18375  }
18376 
18377  virtualWriteCursorInBytesPlayback += mappedSizeInBytesPlayback;
18378  if (virtualWriteCursorInBytesPlayback == pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) {
18379  virtualWriteCursorInBytesPlayback = 0;
18380  virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
18381  }
18382 
18383  /*
18384  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
18385  a bit of a buffer to prevent the playback buffer from getting starved.
18386  */
18387  framesWrittenToPlaybackDevice += mappedSizeInBytesPlayback/bpfDevicePlayback;
18388  if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= pDevice->playback.internalPeriodSizeInFrames) {
18389  hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
18390  if (FAILED(hr)) {
18391  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.", ma_result_from_HRESULT(hr));
18392  }
18393  isPlaybackDeviceStarted = MA_TRUE;
18394  }
18395  } break;
18396 
18397 
18398  default: return MA_INVALID_ARGS; /* Invalid device type. */
18399  }
18400 
18401  if (result != MA_SUCCESS) {
18402  return result;
18403  }
18404  }
18405 
18406  /* Getting here means the device is being stopped. */
18407  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
18408  hr = ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
18409  if (FAILED(hr)) {
18410  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCaptureBuffer_Stop() failed.", ma_result_from_HRESULT(hr));
18411  }
18412  }
18413 
18414  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
18415  /* 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. */
18416  if (isPlaybackDeviceStarted) {
18417  for (;;) {
18418  DWORD availableBytesPlayback = 0;
18419  DWORD physicalPlayCursorInBytes;
18420  DWORD physicalWriteCursorInBytes;
18421  hr = ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes);
18422  if (FAILED(hr)) {
18423  break;
18424  }
18425 
18426  if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
18427  physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
18428  }
18429  prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
18430 
18431  if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
18432  /* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
18433  if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
18434  availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
18435  availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
18436  } else {
18437  break;
18438  }
18439  } else {
18440  /* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
18441  if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
18442  availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
18443  } else {
18444  break;
18445  }
18446  }
18447 
18448  if (availableBytesPlayback >= (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback)) {
18449  break;
18450  }
18451 
18452  ma_sleep(waitTimeInMilliseconds);
18453  }
18454  }
18455 
18456  hr = ma_IDirectSoundBuffer_Stop((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
18457  if (FAILED(hr)) {
18458  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Stop() failed.", ma_result_from_HRESULT(hr));
18459  }
18460 
18461  ma_IDirectSoundBuffer_SetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0);
18462  }
18463 
18464  return MA_SUCCESS;
18465 }
18466 
18467 static ma_result ma_context_uninit__dsound(ma_context* pContext)
18468 {
18469  MA_ASSERT(pContext != NULL);
18470  MA_ASSERT(pContext->backend == ma_backend_dsound);
18471 
18472  ma_dlclose(pContext, pContext->dsound.hDSoundDLL);
18473 
18474  return MA_SUCCESS;
18475 }
18476 
18477 static ma_result ma_context_init__dsound(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
18478 {
18479  MA_ASSERT(pContext != NULL);
18480 
18481  (void)pConfig;
18482 
18483  pContext->dsound.hDSoundDLL = ma_dlopen(pContext, "dsound.dll");
18484  if (pContext->dsound.hDSoundDLL == NULL) {
18485  return MA_API_NOT_FOUND;
18486  }
18487 
18488  pContext->dsound.DirectSoundCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCreate");
18489  pContext->dsound.DirectSoundEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundEnumerateA");
18490  pContext->dsound.DirectSoundCaptureCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCaptureCreate");
18491  pContext->dsound.DirectSoundCaptureEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCaptureEnumerateA");
18492 
18493  pCallbacks->onContextInit = ma_context_init__dsound;
18494  pCallbacks->onContextUninit = ma_context_uninit__dsound;
18495  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__dsound;
18496  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__dsound;
18497  pCallbacks->onDeviceInit = ma_device_init__dsound;
18498  pCallbacks->onDeviceUninit = ma_device_uninit__dsound;
18499  pCallbacks->onDeviceStart = NULL; /* Not used. Started in onDeviceDataLoop. */
18500  pCallbacks->onDeviceStop = NULL; /* Not used. Stopped in onDeviceDataLoop. */
18501  pCallbacks->onDeviceRead = NULL; /* Not used. Data is read directly in onDeviceDataLoop. */
18502  pCallbacks->onDeviceWrite = NULL; /* Not used. Data is written directly in onDeviceDataLoop. */
18503  pCallbacks->onDeviceDataLoop = ma_device_data_loop__dsound;
18504 
18505  return MA_SUCCESS;
18506 }
18507 #endif
18508 
18509 
18510 
18511 /******************************************************************************
18512 
18513 WinMM Backend
18514 
18515 ******************************************************************************/
18516 #ifdef MA_HAS_WINMM
18517 
18518 /*
18519 Some older compilers don't have WAVEOUTCAPS2A and WAVEINCAPS2A, so we'll need to write this ourselves. These structures
18520 are exactly the same as the older ones but they have a few GUIDs for manufacturer/product/name identification. I'm keeping
18521 the names the same as the Win32 library for consistency, but namespaced to avoid naming conflicts with the Win32 version.
18522 */
18523 typedef struct
18524 {
18525  WORD wMid;
18526  WORD wPid;
18527  MMVERSION vDriverVersion;
18528  CHAR szPname[MAXPNAMELEN];
18529  DWORD dwFormats;
18530  WORD wChannels;
18531  WORD wReserved1;
18532  DWORD dwSupport;
18533  GUID ManufacturerGuid;
18534  GUID ProductGuid;
18535  GUID NameGuid;
18536 } MA_WAVEOUTCAPS2A;
18537 typedef struct
18538 {
18539  WORD wMid;
18540  WORD wPid;
18541  MMVERSION vDriverVersion;
18542  CHAR szPname[MAXPNAMELEN];
18543  DWORD dwFormats;
18544  WORD wChannels;
18545  WORD wReserved1;
18546  GUID ManufacturerGuid;
18547  GUID ProductGuid;
18548  GUID NameGuid;
18549 } MA_WAVEINCAPS2A;
18550 
18551 typedef UINT (WINAPI * MA_PFN_waveOutGetNumDevs)(void);
18552 typedef MMRESULT (WINAPI * MA_PFN_waveOutGetDevCapsA)(ma_uintptr uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc);
18553 typedef MMRESULT (WINAPI * MA_PFN_waveOutOpen)(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
18554 typedef MMRESULT (WINAPI * MA_PFN_waveOutClose)(HWAVEOUT hwo);
18555 typedef MMRESULT (WINAPI * MA_PFN_waveOutPrepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
18556 typedef MMRESULT (WINAPI * MA_PFN_waveOutUnprepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
18557 typedef MMRESULT (WINAPI * MA_PFN_waveOutWrite)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
18558 typedef MMRESULT (WINAPI * MA_PFN_waveOutReset)(HWAVEOUT hwo);
18559 typedef UINT (WINAPI * MA_PFN_waveInGetNumDevs)(void);
18560 typedef MMRESULT (WINAPI * MA_PFN_waveInGetDevCapsA)(ma_uintptr uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic);
18561 typedef MMRESULT (WINAPI * MA_PFN_waveInOpen)(LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
18562 typedef MMRESULT (WINAPI * MA_PFN_waveInClose)(HWAVEIN hwi);
18563 typedef MMRESULT (WINAPI * MA_PFN_waveInPrepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
18564 typedef MMRESULT (WINAPI * MA_PFN_waveInUnprepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
18565 typedef MMRESULT (WINAPI * MA_PFN_waveInAddBuffer)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
18566 typedef MMRESULT (WINAPI * MA_PFN_waveInStart)(HWAVEIN hwi);
18567 typedef MMRESULT (WINAPI * MA_PFN_waveInReset)(HWAVEIN hwi);
18568 
18569 static ma_result ma_result_from_MMRESULT(MMRESULT resultMM)
18570 {
18571  switch (resultMM) {
18572  case MMSYSERR_NOERROR: return MA_SUCCESS;
18573  case MMSYSERR_BADDEVICEID: return MA_INVALID_ARGS;
18574  case MMSYSERR_INVALHANDLE: return MA_INVALID_ARGS;
18575  case MMSYSERR_NOMEM: return MA_OUT_OF_MEMORY;
18576  case MMSYSERR_INVALFLAG: return MA_INVALID_ARGS;
18577  case MMSYSERR_INVALPARAM: return MA_INVALID_ARGS;
18578  case MMSYSERR_HANDLEBUSY: return MA_BUSY;
18579  case MMSYSERR_ERROR: return MA_ERROR;
18580  default: return MA_ERROR;
18581  }
18582 }
18583 
18584 static char* ma_find_last_character(char* str, char ch)
18585 {
18586  char* last;
18587 
18588  if (str == NULL) {
18589  return NULL;
18590  }
18591 
18592  last = NULL;
18593  while (*str != '\0') {
18594  if (*str == ch) {
18595  last = str;
18596  }
18597 
18598  str += 1;
18599  }
18600 
18601  return last;
18602 }
18603 
18604 static ma_uint32 ma_get_period_size_in_bytes(ma_uint32 periodSizeInFrames, ma_format format, ma_uint32 channels)
18605 {
18606  return periodSizeInFrames * ma_get_bytes_per_frame(format, channels);
18607 }
18608 
18609 
18610 /*
18611 Our own "WAVECAPS" structure that contains generic information shared between WAVEOUTCAPS2 and WAVEINCAPS2 so
18612 we can do things generically and typesafely. Names are being kept the same for consistency.
18613 */
18614 typedef struct
18615 {
18616  CHAR szPname[MAXPNAMELEN];
18617  DWORD dwFormats;
18618  WORD wChannels;
18619  GUID NameGuid;
18620 } MA_WAVECAPSA;
18621 
18622 static ma_result ma_get_best_info_from_formats_flags__winmm(DWORD dwFormats, WORD channels, WORD* pBitsPerSample, DWORD* pSampleRate)
18623 {
18624  WORD bitsPerSample = 0;
18625  DWORD sampleRate = 0;
18626 
18627  if (pBitsPerSample) {
18628  *pBitsPerSample = 0;
18629  }
18630  if (pSampleRate) {
18631  *pSampleRate = 0;
18632  }
18633 
18634  if (channels == 1) {
18635  bitsPerSample = 16;
18636  if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
18637  sampleRate = 48000;
18638  } else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
18639  sampleRate = 44100;
18640  } else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
18641  sampleRate = 22050;
18642  } else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
18643  sampleRate = 11025;
18644  } else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
18645  sampleRate = 96000;
18646  } else {
18647  bitsPerSample = 8;
18648  if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
18649  sampleRate = 48000;
18650  } else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
18651  sampleRate = 44100;
18652  } else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
18653  sampleRate = 22050;
18654  } else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
18655  sampleRate = 11025;
18656  } else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
18657  sampleRate = 96000;
18658  } else {
18659  return MA_FORMAT_NOT_SUPPORTED;
18660  }
18661  }
18662  } else {
18663  bitsPerSample = 16;
18664  if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
18665  sampleRate = 48000;
18666  } else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
18667  sampleRate = 44100;
18668  } else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
18669  sampleRate = 22050;
18670  } else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
18671  sampleRate = 11025;
18672  } else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
18673  sampleRate = 96000;
18674  } else {
18675  bitsPerSample = 8;
18676  if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
18677  sampleRate = 48000;
18678  } else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
18679  sampleRate = 44100;
18680  } else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
18681  sampleRate = 22050;
18682  } else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
18683  sampleRate = 11025;
18684  } else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
18685  sampleRate = 96000;
18686  } else {
18687  return MA_FORMAT_NOT_SUPPORTED;
18688  }
18689  }
18690  }
18691 
18692  if (pBitsPerSample) {
18693  *pBitsPerSample = bitsPerSample;
18694  }
18695  if (pSampleRate) {
18696  *pSampleRate = sampleRate;
18697  }
18698 
18699  return MA_SUCCESS;
18700 }
18701 
18702 static ma_result ma_formats_flags_to_WAVEFORMATEX__winmm(DWORD dwFormats, WORD channels, WAVEFORMATEX* pWF)
18703 {
18704  ma_result result;
18705 
18706  MA_ASSERT(pWF != NULL);
18707 
18708  MA_ZERO_OBJECT(pWF);
18709  pWF->cbSize = sizeof(*pWF);
18710  pWF->wFormatTag = WAVE_FORMAT_PCM;
18711  pWF->nChannels = (WORD)channels;
18712  if (pWF->nChannels > 2) {
18713  pWF->nChannels = 2;
18714  }
18715 
18716  result = ma_get_best_info_from_formats_flags__winmm(dwFormats, channels, &pWF->wBitsPerSample, &pWF->nSamplesPerSec);
18717  if (result != MA_SUCCESS) {
18718  return result;
18719  }
18720 
18721  pWF->nBlockAlign = (WORD)(pWF->nChannels * pWF->wBitsPerSample / 8);
18722  pWF->nAvgBytesPerSec = pWF->nBlockAlign * pWF->nSamplesPerSec;
18723 
18724  return MA_SUCCESS;
18725 }
18726 
18727 static ma_result ma_context_get_device_info_from_WAVECAPS(ma_context* pContext, MA_WAVECAPSA* pCaps, ma_device_info* pDeviceInfo)
18728 {
18729  WORD bitsPerSample;
18730  DWORD sampleRate;
18731  ma_result result;
18732 
18733  MA_ASSERT(pContext != NULL);
18734  MA_ASSERT(pCaps != NULL);
18735  MA_ASSERT(pDeviceInfo != NULL);
18736 
18737  /*
18738  Name / Description
18739 
18740  Unfortunately the name specified in WAVE(OUT/IN)CAPS2 is limited to 31 characters. This results in an unprofessional looking
18741  situation where the names of the devices are truncated. To help work around this, we need to look at the name GUID and try
18742  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.
18743  */
18744 
18745  /* Set the default to begin with. */
18746  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), pCaps->szPname, (size_t)-1);
18747 
18748  /*
18749  Now try the registry. There's a few things to consider here:
18750  - The name GUID can be null, in which we case we just need to stick to the original 31 characters.
18751  - If the name GUID is not present in the registry we'll also need to stick to the original 31 characters.
18752  - I like consistency, so I want the returned device names to be consistent with those returned by WASAPI and DirectSound. The
18753  problem, however is that WASAPI and DirectSound use "<component> (<name>)" format (such as "Speakers (High Definition Audio)"),
18754  but WinMM does not specificy the component name. From my admittedly limited testing, I've notice the component name seems to
18755  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
18756  name, and then concatenate the name from the registry.
18757  */
18758  if (!ma_is_guid_null(&pCaps->NameGuid)) {
18759  wchar_t guidStrW[256];
18760  if (((MA_PFN_StringFromGUID2)pContext->win32.StringFromGUID2)(&pCaps->NameGuid, guidStrW, ma_countof(guidStrW)) > 0) {
18761  char guidStr[256];
18762  char keyStr[1024];
18763  HKEY hKey;
18764 
18765  WideCharToMultiByte(CP_UTF8, 0, guidStrW, -1, guidStr, sizeof(guidStr), 0, FALSE);
18766 
18767  ma_strcpy_s(keyStr, sizeof(keyStr), "SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
18768  ma_strcat_s(keyStr, sizeof(keyStr), guidStr);
18769 
18770  if (((MA_PFN_RegOpenKeyExA)pContext->win32.RegOpenKeyExA)(HKEY_LOCAL_MACHINE, keyStr, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
18771  BYTE nameFromReg[512];
18772  DWORD nameFromRegSize = sizeof(nameFromReg);
18773  result = ((MA_PFN_RegQueryValueExA)pContext->win32.RegQueryValueExA)(hKey, "Name", 0, NULL, (LPBYTE)nameFromReg, (LPDWORD)&nameFromRegSize);
18774  ((MA_PFN_RegCloseKey)pContext->win32.RegCloseKey)(hKey);
18775 
18776  if (result == ERROR_SUCCESS) {
18777  /* We have the value from the registry, so now we need to construct the name string. */
18778  char name[1024];
18779  if (ma_strcpy_s(name, sizeof(name), pDeviceInfo->name) == 0) {
18780  char* nameBeg = ma_find_last_character(name, '(');
18781  if (nameBeg != NULL) {
18782  size_t leadingLen = (nameBeg - name);
18783  ma_strncpy_s(nameBeg + 1, sizeof(name) - leadingLen, (const char*)nameFromReg, (size_t)-1);
18784 
18785  /* The closing ")", if it can fit. */
18786  if (leadingLen + nameFromRegSize < sizeof(name)-1) {
18787  ma_strcat_s(name, sizeof(name), ")");
18788  }
18789 
18790  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), name, (size_t)-1);
18791  }
18792  }
18793  }
18794  }
18795  }
18796  }
18797 
18798 
18799  result = ma_get_best_info_from_formats_flags__winmm(pCaps->dwFormats, pCaps->wChannels, &bitsPerSample, &sampleRate);
18800  if (result != MA_SUCCESS) {
18801  return result;
18802  }
18803 
18804  if (bitsPerSample == 8) {
18805  pDeviceInfo->nativeDataFormats[0].format = ma_format_u8;
18806  } else if (bitsPerSample == 16) {
18807  pDeviceInfo->nativeDataFormats[0].format = ma_format_s16;
18808  } else if (bitsPerSample == 24) {
18809  pDeviceInfo->nativeDataFormats[0].format = ma_format_s24;
18810  } else if (bitsPerSample == 32) {
18811  pDeviceInfo->nativeDataFormats[0].format = ma_format_s32;
18812  } else {
18813  return MA_FORMAT_NOT_SUPPORTED;
18814  }
18815  pDeviceInfo->nativeDataFormats[0].channels = pCaps->wChannels;
18816  pDeviceInfo->nativeDataFormats[0].sampleRate = sampleRate;
18817  pDeviceInfo->nativeDataFormats[0].flags = 0;
18818  pDeviceInfo->nativeDataFormatCount = 1;
18819 
18820  return MA_SUCCESS;
18821 }
18822 
18823 static ma_result ma_context_get_device_info_from_WAVEOUTCAPS2(ma_context* pContext, MA_WAVEOUTCAPS2A* pCaps, ma_device_info* pDeviceInfo)
18824 {
18825  MA_WAVECAPSA caps;
18826 
18827  MA_ASSERT(pContext != NULL);
18828  MA_ASSERT(pCaps != NULL);
18829  MA_ASSERT(pDeviceInfo != NULL);
18830 
18831  MA_COPY_MEMORY(caps.szPname, pCaps->szPname, sizeof(caps.szPname));
18832  caps.dwFormats = pCaps->dwFormats;
18833  caps.wChannels = pCaps->wChannels;
18834  caps.NameGuid = pCaps->NameGuid;
18835  return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
18836 }
18837 
18838 static ma_result ma_context_get_device_info_from_WAVEINCAPS2(ma_context* pContext, MA_WAVEINCAPS2A* pCaps, ma_device_info* pDeviceInfo)
18839 {
18840  MA_WAVECAPSA caps;
18841 
18842  MA_ASSERT(pContext != NULL);
18843  MA_ASSERT(pCaps != NULL);
18844  MA_ASSERT(pDeviceInfo != NULL);
18845 
18846  MA_COPY_MEMORY(caps.szPname, pCaps->szPname, sizeof(caps.szPname));
18847  caps.dwFormats = pCaps->dwFormats;
18848  caps.wChannels = pCaps->wChannels;
18849  caps.NameGuid = pCaps->NameGuid;
18850  return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
18851 }
18852 
18853 
18854 static ma_result ma_context_enumerate_devices__winmm(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
18855 {
18856  UINT playbackDeviceCount;
18857  UINT captureDeviceCount;
18858  UINT iPlaybackDevice;
18859  UINT iCaptureDevice;
18860 
18861  MA_ASSERT(pContext != NULL);
18862  MA_ASSERT(callback != NULL);
18863 
18864  /* Playback. */
18865  playbackDeviceCount = ((MA_PFN_waveOutGetNumDevs)pContext->winmm.waveOutGetNumDevs)();
18866  for (iPlaybackDevice = 0; iPlaybackDevice < playbackDeviceCount; ++iPlaybackDevice) {
18867  MMRESULT result;
18868  MA_WAVEOUTCAPS2A caps;
18869 
18870  MA_ZERO_OBJECT(&caps);
18871 
18872  result = ((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(iPlaybackDevice, (WAVEOUTCAPSA*)&caps, sizeof(caps));
18873  if (result == MMSYSERR_NOERROR) {
18874  ma_device_info deviceInfo;
18875 
18876  MA_ZERO_OBJECT(&deviceInfo);
18877  deviceInfo.id.winmm = iPlaybackDevice;
18878 
18879  /* The first enumerated device is the default device. */
18880  if (iPlaybackDevice == 0) {
18881  deviceInfo.isDefault = MA_TRUE;
18882  }
18883 
18884  if (ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, &deviceInfo) == MA_SUCCESS) {
18885  ma_bool32 cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
18886  if (cbResult == MA_FALSE) {
18887  return MA_SUCCESS; /* Enumeration was stopped. */
18888  }
18889  }
18890  }
18891  }
18892 
18893  /* Capture. */
18894  captureDeviceCount = ((MA_PFN_waveInGetNumDevs)pContext->winmm.waveInGetNumDevs)();
18895  for (iCaptureDevice = 0; iCaptureDevice < captureDeviceCount; ++iCaptureDevice) {
18896  MMRESULT result;
18897  MA_WAVEINCAPS2A caps;
18898 
18899  MA_ZERO_OBJECT(&caps);
18900 
18901  result = ((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(iCaptureDevice, (WAVEINCAPSA*)&caps, sizeof(caps));
18902  if (result == MMSYSERR_NOERROR) {
18903  ma_device_info deviceInfo;
18904 
18905  MA_ZERO_OBJECT(&deviceInfo);
18906  deviceInfo.id.winmm = iCaptureDevice;
18907 
18908  /* The first enumerated device is the default device. */
18909  if (iCaptureDevice == 0) {
18910  deviceInfo.isDefault = MA_TRUE;
18911  }
18912 
18913  if (ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, &deviceInfo) == MA_SUCCESS) {
18914  ma_bool32 cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
18915  if (cbResult == MA_FALSE) {
18916  return MA_SUCCESS; /* Enumeration was stopped. */
18917  }
18918  }
18919  }
18920  }
18921 
18922  return MA_SUCCESS;
18923 }
18924 
18925 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)
18926 {
18927  UINT winMMDeviceID;
18928 
18929  MA_ASSERT(pContext != NULL);
18930 
18931  winMMDeviceID = 0;
18932  if (pDeviceID != NULL) {
18933  winMMDeviceID = (UINT)pDeviceID->winmm;
18934  }
18935 
18936  pDeviceInfo->id.winmm = winMMDeviceID;
18937 
18938  /* The first ID is the default device. */
18939  if (winMMDeviceID == 0) {
18940  pDeviceInfo->isDefault = MA_TRUE;
18941  }
18942 
18943  if (deviceType == ma_device_type_playback) {
18944  MMRESULT result;
18945  MA_WAVEOUTCAPS2A caps;
18946 
18947  MA_ZERO_OBJECT(&caps);
18948 
18949  result = ((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(winMMDeviceID, (WAVEOUTCAPSA*)&caps, sizeof(caps));
18950  if (result == MMSYSERR_NOERROR) {
18951  return ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, pDeviceInfo);
18952  }
18953  } else {
18954  MMRESULT result;
18955  MA_WAVEINCAPS2A caps;
18956 
18957  MA_ZERO_OBJECT(&caps);
18958 
18959  result = ((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(winMMDeviceID, (WAVEINCAPSA*)&caps, sizeof(caps));
18960  if (result == MMSYSERR_NOERROR) {
18961  return ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, pDeviceInfo);
18962  }
18963  }
18964 
18965  return MA_NO_DEVICE;
18966 }
18967 
18968 
18969 static ma_result ma_device_uninit__winmm(ma_device* pDevice)
18970 {
18971  MA_ASSERT(pDevice != NULL);
18972 
18973  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
18974  ((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
18975  CloseHandle((HANDLE)pDevice->winmm.hEventCapture);
18976  }
18977 
18978  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
18979  ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
18980  ((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
18981  CloseHandle((HANDLE)pDevice->winmm.hEventPlayback);
18982  }
18983 
18984  ma__free_from_callbacks(pDevice->winmm._pHeapData, &pDevice->pContext->allocationCallbacks);
18985 
18986  MA_ZERO_OBJECT(&pDevice->winmm); /* Safety. */
18987 
18988  return MA_SUCCESS;
18989 }
18990 
18991 static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__winmm(const ma_device_descriptor* pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
18992 {
18993  /* WinMM has a minimum period size of 40ms. */
18994  ma_uint32 minPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(40, nativeSampleRate);
18995  ma_uint32 periodSizeInFrames;
18996 
18997  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, nativeSampleRate, performanceProfile);
18998  if (periodSizeInFrames < minPeriodSizeInFrames) {
18999  periodSizeInFrames = minPeriodSizeInFrames;
19000  }
19001 
19002  return periodSizeInFrames;
19003 }
19004 
19005 static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
19006 {
19007  const char* errorMsg = "";
19008  ma_result errorCode = MA_ERROR;
19009  ma_result result = MA_SUCCESS;
19010  ma_uint32 heapSize;
19011  UINT winMMDeviceIDPlayback = 0;
19012  UINT winMMDeviceIDCapture = 0;
19013 
19014  MA_ASSERT(pDevice != NULL);
19015 
19016  MA_ZERO_OBJECT(&pDevice->winmm);
19017 
19018  if (pConfig->deviceType == ma_device_type_loopback) {
19020  }
19021 
19022  /* No exlusive mode with WinMM. */
19023  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
19024  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
19026  }
19027 
19028  if (pDescriptorPlayback->pDeviceID != NULL) {
19029  winMMDeviceIDPlayback = (UINT)pDescriptorPlayback->pDeviceID->winmm;
19030  }
19031  if (pDescriptorCapture->pDeviceID != NULL) {
19032  winMMDeviceIDCapture = (UINT)pDescriptorCapture->pDeviceID->winmm;
19033  }
19034 
19035  /* The capture device needs to be initialized first. */
19036  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
19037  WAVEINCAPSA caps;
19038  WAVEFORMATEX wf;
19039  MMRESULT resultMM;
19040 
19041  /* We use an event to know when a new fragment needs to be enqueued. */
19042  pDevice->winmm.hEventCapture = (ma_handle)CreateEventW(NULL, TRUE, TRUE, NULL);
19043  if (pDevice->winmm.hEventCapture == NULL) {
19044  errorMsg = "[WinMM] Failed to create event for fragment enqueing for the capture device.", errorCode = ma_result_from_GetLastError(GetLastError());
19045  goto on_error;
19046  }
19047 
19048  /* The format should be based on the device's actual format. */
19049  if (((MA_PFN_waveInGetDevCapsA)pDevice->pContext->winmm.waveInGetDevCapsA)(winMMDeviceIDCapture, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
19050  errorMsg = "[WinMM] Failed to retrieve internal device caps.", errorCode = MA_FORMAT_NOT_SUPPORTED;
19051  goto on_error;
19052  }
19053 
19054  result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
19055  if (result != MA_SUCCESS) {
19056  errorMsg = "[WinMM] Could not find appropriate format for internal device.", errorCode = result;
19057  goto on_error;
19058  }
19059 
19060  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);
19061  if (resultMM != MMSYSERR_NOERROR) {
19062  errorMsg = "[WinMM] Failed to open capture device.", errorCode = MA_FAILED_TO_OPEN_BACKEND_DEVICE;
19063  goto on_error;
19064  }
19065 
19066  pDescriptorCapture->format = ma_format_from_WAVEFORMATEX(&wf);
19067  pDescriptorCapture->channels = wf.nChannels;
19068  pDescriptorCapture->sampleRate = wf.nSamplesPerSec;
19069  ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
19070  pDescriptorCapture->periodCount = pDescriptorCapture->periodCount;
19071  pDescriptorCapture->periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__winmm(pDescriptorCapture, pDescriptorCapture->sampleRate, pConfig->performanceProfile);
19072  }
19073 
19074  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
19075  WAVEOUTCAPSA caps;
19076  WAVEFORMATEX wf;
19077  MMRESULT resultMM;
19078 
19079  /* We use an event to know when a new fragment needs to be enqueued. */
19080  pDevice->winmm.hEventPlayback = (ma_handle)CreateEvent(NULL, TRUE, TRUE, NULL);
19081  if (pDevice->winmm.hEventPlayback == NULL) {
19082  errorMsg = "[WinMM] Failed to create event for fragment enqueing for the playback device.", errorCode = ma_result_from_GetLastError(GetLastError());
19083  goto on_error;
19084  }
19085 
19086  /* The format should be based on the device's actual format. */
19087  if (((MA_PFN_waveOutGetDevCapsA)pDevice->pContext->winmm.waveOutGetDevCapsA)(winMMDeviceIDPlayback, &caps, sizeof(caps)) != MMSYSERR_NOERROR) {
19088  errorMsg = "[WinMM] Failed to retrieve internal device caps.", errorCode = MA_FORMAT_NOT_SUPPORTED;
19089  goto on_error;
19090  }
19091 
19092  result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
19093  if (result != MA_SUCCESS) {
19094  errorMsg = "[WinMM] Could not find appropriate format for internal device.", errorCode = result;
19095  goto on_error;
19096  }
19097 
19098  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);
19099  if (resultMM != MMSYSERR_NOERROR) {
19100  errorMsg = "[WinMM] Failed to open playback device.", errorCode = MA_FAILED_TO_OPEN_BACKEND_DEVICE;
19101  goto on_error;
19102  }
19103 
19104  pDescriptorPlayback->format = ma_format_from_WAVEFORMATEX(&wf);
19105  pDescriptorPlayback->channels = wf.nChannels;
19106  pDescriptorPlayback->sampleRate = wf.nSamplesPerSec;
19107  ma_get_standard_channel_map(ma_standard_channel_map_microsoft, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
19108  pDescriptorPlayback->periodCount = pDescriptorPlayback->periodCount;
19109  pDescriptorPlayback->periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__winmm(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
19110  }
19111 
19112  /*
19113  The heap allocated data is allocated like so:
19114 
19115  [Capture WAVEHDRs][Playback WAVEHDRs][Capture Intermediary Buffer][Playback Intermediary Buffer]
19116  */
19117  heapSize = 0;
19118  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
19119  heapSize += sizeof(WAVEHDR)*pDescriptorCapture->periodCount + (pDescriptorCapture->periodSizeInFrames * pDescriptorCapture->periodCount * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels));
19120  }
19121  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
19122  heapSize += sizeof(WAVEHDR)*pDescriptorPlayback->periodCount + (pDescriptorPlayback->periodSizeInFrames * pDescriptorPlayback->periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels));
19123  }
19124 
19125  pDevice->winmm._pHeapData = (ma_uint8*)ma__calloc_from_callbacks(heapSize, &pDevice->pContext->allocationCallbacks);
19126  if (pDevice->winmm._pHeapData == NULL) {
19127  errorMsg = "[WinMM] Failed to allocate memory for the intermediary buffer.", errorCode = MA_OUT_OF_MEMORY;
19128  goto on_error;
19129  }
19130 
19131  MA_ZERO_MEMORY(pDevice->winmm._pHeapData, heapSize);
19132 
19133  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
19134  ma_uint32 iPeriod;
19135 
19136  if (pConfig->deviceType == ma_device_type_capture) {
19137  pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
19138  pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount));
19139  } else {
19140  pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
19141  pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount + pDescriptorPlayback->periodCount));
19142  }
19143 
19144  /* Prepare headers. */
19145  for (iPeriod = 0; iPeriod < pDescriptorCapture->periodCount; ++iPeriod) {
19146  ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDescriptorCapture->periodSizeInFrames, pDescriptorCapture->format, pDescriptorCapture->channels);
19147 
19148  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferCapture + (periodSizeInBytes*iPeriod));
19149  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwBufferLength = periodSizeInBytes;
19150  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwFlags = 0L;
19151  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwLoops = 0L;
19152  ((MA_PFN_waveInPrepareHeader)pDevice->pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
19153 
19154  /*
19155  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
19156  it's unlocked and available for writing. A value of 1 means it's locked.
19157  */
19158  ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwUser = 0;
19159  }
19160  }
19161 
19162  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
19163  ma_uint32 iPeriod;
19164 
19165  if (pConfig->deviceType == ma_device_type_playback) {
19166  pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData;
19167  pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*pDescriptorPlayback->periodCount);
19168  } else {
19169  pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData + (sizeof(WAVEHDR)*(pDescriptorCapture->periodCount));
19170  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));
19171  }
19172 
19173  /* Prepare headers. */
19174  for (iPeriod = 0; iPeriod < pDescriptorPlayback->periodCount; ++iPeriod) {
19175  ma_uint32 periodSizeInBytes = ma_get_period_size_in_bytes(pDescriptorPlayback->periodSizeInFrames, pDescriptorPlayback->format, pDescriptorPlayback->channels);
19176 
19177  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferPlayback + (periodSizeInBytes*iPeriod));
19178  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwBufferLength = periodSizeInBytes;
19179  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwFlags = 0L;
19180  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwLoops = 0L;
19181  ((MA_PFN_waveOutPrepareHeader)pDevice->pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
19182 
19183  /*
19184  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
19185  it's unlocked and available for writing. A value of 1 means it's locked.
19186  */
19187  ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwUser = 0;
19188  }
19189  }
19190 
19191  return MA_SUCCESS;
19192 
19193 on_error:
19194  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
19195  if (pDevice->winmm.pWAVEHDRCapture != NULL) {
19196  ma_uint32 iPeriod;
19197  for (iPeriod = 0; iPeriod < pDescriptorCapture->periodCount; ++iPeriod) {
19198  ((MA_PFN_waveInUnprepareHeader)pDevice->pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
19199  }
19200  }
19201 
19202  ((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
19203  }
19204 
19205  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
19206  if (pDevice->winmm.pWAVEHDRCapture != NULL) {
19207  ma_uint32 iPeriod;
19208  for (iPeriod = 0; iPeriod < pDescriptorPlayback->periodCount; ++iPeriod) {
19209  ((MA_PFN_waveOutUnprepareHeader)pDevice->pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod], sizeof(WAVEHDR));
19210  }
19211  }
19212 
19213  ((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
19214  }
19215 
19216  ma__free_from_callbacks(pDevice->winmm._pHeapData, &pDevice->pContext->allocationCallbacks);
19217  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, errorMsg, errorCode);
19218 }
19219 
19220 static ma_result ma_device_start__winmm(ma_device* pDevice)
19221 {
19222  MA_ASSERT(pDevice != NULL);
19223 
19224  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
19225  MMRESULT resultMM;
19226  WAVEHDR* pWAVEHDR;
19227  ma_uint32 iPeriod;
19228 
19229  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
19230 
19231  /* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
19232  ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
19233 
19234  /* 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. */
19235  for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
19236  resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[iPeriod], sizeof(WAVEHDR));
19237  if (resultMM != MMSYSERR_NOERROR) {
19238  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));
19239  }
19240 
19241  /* Make sure all of the buffers start out locked. We don't want to access them until the backend tells us we can. */
19242  pWAVEHDR[iPeriod].dwUser = 1; /* 1 = locked. */
19243  }
19244 
19245  /* Capture devices need to be explicitly started, unlike playback devices. */
19246  resultMM = ((MA_PFN_waveInStart)pDevice->pContext->winmm.waveInStart)((HWAVEIN)pDevice->winmm.hDeviceCapture);
19247  if (resultMM != MMSYSERR_NOERROR) {
19248  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] Failed to start backend device.", ma_result_from_MMRESULT(resultMM));
19249  }
19250  }
19251 
19252  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
19253  /* Don't need to do anything for playback. It'll be started automatically in ma_device_start__winmm(). */
19254  }
19255 
19256  return MA_SUCCESS;
19257 }
19258 
19259 static ma_result ma_device_stop__winmm(ma_device* pDevice)
19260 {
19261  MMRESULT resultMM;
19262 
19263  MA_ASSERT(pDevice != NULL);
19264 
19265  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
19266  if (pDevice->winmm.hDeviceCapture == NULL) {
19267  return MA_INVALID_ARGS;
19268  }
19269 
19270  resultMM = ((MA_PFN_waveInReset)pDevice->pContext->winmm.waveInReset)((HWAVEIN)pDevice->winmm.hDeviceCapture);
19271  if (resultMM != MMSYSERR_NOERROR) {
19272  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] WARNING: Failed to reset capture device.", ma_result_from_MMRESULT(resultMM));
19273  }
19274  }
19275 
19276  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
19277  ma_uint32 iPeriod;
19278  WAVEHDR* pWAVEHDR;
19279 
19280  if (pDevice->winmm.hDevicePlayback == NULL) {
19281  return MA_INVALID_ARGS;
19282  }
19283 
19284  /* 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. */
19285  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback;
19286  for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; iPeriod += 1) {
19287  if (pWAVEHDR[iPeriod].dwUser == 1) { /* 1 = locked. */
19288  if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
19289  break; /* An error occurred so just abandon ship and stop the device without draining. */
19290  }
19291 
19292  pWAVEHDR[iPeriod].dwUser = 0;
19293  }
19294  }
19295 
19296  resultMM = ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
19297  if (resultMM != MMSYSERR_NOERROR) {
19298  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] WARNING: Failed to reset playback device.", ma_result_from_MMRESULT(resultMM));
19299  }
19300  }
19301 
19302  return MA_SUCCESS;
19303 }
19304 
19305 static ma_result ma_device_write__winmm(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
19306 {
19307  ma_result result = MA_SUCCESS;
19308  MMRESULT resultMM;
19309  ma_uint32 totalFramesWritten;
19310  WAVEHDR* pWAVEHDR;
19311 
19312  MA_ASSERT(pDevice != NULL);
19313  MA_ASSERT(pPCMFrames != NULL);
19314 
19315  if (pFramesWritten != NULL) {
19316  *pFramesWritten = 0;
19317  }
19318 
19319  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback;
19320 
19321  /* Keep processing as much data as possible. */
19322  totalFramesWritten = 0;
19323  while (totalFramesWritten < frameCount) {
19324  /* If the current header has some space available we need to write part of it. */
19325  if (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser == 0) { /* 0 = unlocked. */
19326  /*
19327  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
19328  write it out and move on to the next iteration.
19329  */
19331  ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedPlayback;
19332 
19333  ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesWritten));
19334  const void* pSrc = ma_offset_ptr(pPCMFrames, totalFramesWritten*bpf);
19335  void* pDst = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].lpData, pDevice->winmm.headerFramesConsumedPlayback*bpf);
19336  MA_COPY_MEMORY(pDst, pSrc, framesToCopy*bpf);
19337 
19338  pDevice->winmm.headerFramesConsumedPlayback += framesToCopy;
19339  totalFramesWritten += framesToCopy;
19340 
19341  /* If we've consumed the buffer entirely we need to write it out to the device. */
19342  if (pDevice->winmm.headerFramesConsumedPlayback == (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf)) {
19343  pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 1; /* 1 = locked. */
19344  pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags &= ~WHDR_DONE; /* <-- Need to make sure the WHDR_DONE flag is unset. */
19345 
19346  /* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
19347  ResetEvent((HANDLE)pDevice->winmm.hEventPlayback);
19348 
19349  /* The device will be started here. */
19350  resultMM = ((MA_PFN_waveOutWrite)pDevice->pContext->winmm.waveOutWrite)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &pWAVEHDR[pDevice->winmm.iNextHeaderPlayback], sizeof(WAVEHDR));
19351  if (resultMM != MMSYSERR_NOERROR) {
19352  result = ma_result_from_MMRESULT(resultMM);
19353  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] waveOutWrite() failed.", result);
19354  break;
19355  }
19356 
19357  /* Make sure we move to the next header. */
19358  pDevice->winmm.iNextHeaderPlayback = (pDevice->winmm.iNextHeaderPlayback + 1) % pDevice->playback.internalPeriods;
19359  pDevice->winmm.headerFramesConsumedPlayback = 0;
19360  }
19361 
19362  /* If at this point we have consumed the entire input buffer we can return. */
19363  MA_ASSERT(totalFramesWritten <= frameCount);
19364  if (totalFramesWritten == frameCount) {
19365  break;
19366  }
19367 
19368  /* Getting here means there's more to process. */
19369  continue;
19370  }
19371 
19372  /* Getting here means there isn't enough room in the buffer and we need to wait for one to become available. */
19373  if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
19374  result = MA_ERROR;
19375  break;
19376  }
19377 
19378  /* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
19379  if ((pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags & WHDR_DONE) != 0) {
19380  pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 0; /* 0 = unlocked (make it available for writing). */
19381  pDevice->winmm.headerFramesConsumedPlayback = 0;
19382  }
19383 
19384  /* If the device has been stopped we need to break. */
19385  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
19386  break;
19387  }
19388  }
19389 
19390  if (pFramesWritten != NULL) {
19391  *pFramesWritten = totalFramesWritten;
19392  }
19393 
19394  return result;
19395 }
19396 
19397 static ma_result ma_device_read__winmm(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
19398 {
19399  ma_result result = MA_SUCCESS;
19400  MMRESULT resultMM;
19401  ma_uint32 totalFramesRead;
19402  WAVEHDR* pWAVEHDR;
19403 
19404  MA_ASSERT(pDevice != NULL);
19405  MA_ASSERT(pPCMFrames != NULL);
19406 
19407  if (pFramesRead != NULL) {
19408  *pFramesRead = 0;
19409  }
19410 
19411  pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
19412 
19413  /* Keep processing as much data as possible. */
19414  totalFramesRead = 0;
19415  while (totalFramesRead < frameCount) {
19416  /* If the current header has some space available we need to write part of it. */
19417  if (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser == 0) { /* 0 = unlocked. */
19418  /* The buffer is available for reading. If we fully consume it we need to add it back to the buffer. */
19420  ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedCapture;
19421 
19422  ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesRead));
19423  const void* pSrc = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderCapture].lpData, pDevice->winmm.headerFramesConsumedCapture*bpf);
19424  void* pDst = ma_offset_ptr(pPCMFrames, totalFramesRead*bpf);
19425  MA_COPY_MEMORY(pDst, pSrc, framesToCopy*bpf);
19426 
19427  pDevice->winmm.headerFramesConsumedCapture += framesToCopy;
19428  totalFramesRead += framesToCopy;
19429 
19430  /* If we've consumed the buffer entirely we need to add it back to the device. */
19431  if (pDevice->winmm.headerFramesConsumedCapture == (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf)) {
19432  pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 1; /* 1 = locked. */
19433  pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags &= ~WHDR_DONE; /* <-- Need to make sure the WHDR_DONE flag is unset. */
19434 
19435  /* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
19436  ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
19437 
19438  /* The device will be started here. */
19439  resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[pDevice->winmm.iNextHeaderCapture], sizeof(WAVEHDR));
19440  if (resultMM != MMSYSERR_NOERROR) {
19441  result = ma_result_from_MMRESULT(resultMM);
19442  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WinMM] waveInAddBuffer() failed.", result);
19443  break;
19444  }
19445 
19446  /* Make sure we move to the next header. */
19447  pDevice->winmm.iNextHeaderCapture = (pDevice->winmm.iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
19448  pDevice->winmm.headerFramesConsumedCapture = 0;
19449  }
19450 
19451  /* If at this point we have filled the entire input buffer we can return. */
19452  MA_ASSERT(totalFramesRead <= frameCount);
19453  if (totalFramesRead == frameCount) {
19454  break;
19455  }
19456 
19457  /* Getting here means there's more to process. */
19458  continue;
19459  }
19460 
19461  /* Getting here means there isn't enough any data left to send to the client which means we need to wait for more. */
19462  if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
19463  result = MA_ERROR;
19464  break;
19465  }
19466 
19467  /* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
19468  if ((pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags & WHDR_DONE) != 0) {
19469  pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 0; /* 0 = unlocked (make it available for reading). */
19470  pDevice->winmm.headerFramesConsumedCapture = 0;
19471  }
19472 
19473  /* If the device has been stopped we need to break. */
19474  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
19475  break;
19476  }
19477  }
19478 
19479  if (pFramesRead != NULL) {
19480  *pFramesRead = totalFramesRead;
19481  }
19482 
19483  return result;
19484 }
19485 
19486 static ma_result ma_context_uninit__winmm(ma_context* pContext)
19487 {
19488  MA_ASSERT(pContext != NULL);
19489  MA_ASSERT(pContext->backend == ma_backend_winmm);
19490 
19491  ma_dlclose(pContext, pContext->winmm.hWinMM);
19492  return MA_SUCCESS;
19493 }
19494 
19495 static ma_result ma_context_init__winmm(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
19496 {
19497  MA_ASSERT(pContext != NULL);
19498 
19499  (void)pConfig;
19500 
19501  pContext->winmm.hWinMM = ma_dlopen(pContext, "winmm.dll");
19502  if (pContext->winmm.hWinMM == NULL) {
19503  return MA_NO_BACKEND;
19504  }
19505 
19506  pContext->winmm.waveOutGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutGetNumDevs");
19507  pContext->winmm.waveOutGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutGetDevCapsA");
19508  pContext->winmm.waveOutOpen = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutOpen");
19509  pContext->winmm.waveOutClose = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutClose");
19510  pContext->winmm.waveOutPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutPrepareHeader");
19511  pContext->winmm.waveOutUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutUnprepareHeader");
19512  pContext->winmm.waveOutWrite = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutWrite");
19513  pContext->winmm.waveOutReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutReset");
19514  pContext->winmm.waveInGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInGetNumDevs");
19515  pContext->winmm.waveInGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInGetDevCapsA");
19516  pContext->winmm.waveInOpen = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInOpen");
19517  pContext->winmm.waveInClose = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInClose");
19518  pContext->winmm.waveInPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInPrepareHeader");
19519  pContext->winmm.waveInUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInUnprepareHeader");
19520  pContext->winmm.waveInAddBuffer = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInAddBuffer");
19521  pContext->winmm.waveInStart = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInStart");
19522  pContext->winmm.waveInReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInReset");
19523 
19524  pCallbacks->onContextInit = ma_context_init__winmm;
19525  pCallbacks->onContextUninit = ma_context_uninit__winmm;
19526  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__winmm;
19527  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__winmm;
19528  pCallbacks->onDeviceInit = ma_device_init__winmm;
19529  pCallbacks->onDeviceUninit = ma_device_uninit__winmm;
19530  pCallbacks->onDeviceStart = ma_device_start__winmm;
19531  pCallbacks->onDeviceStop = ma_device_stop__winmm;
19532  pCallbacks->onDeviceRead = ma_device_read__winmm;
19533  pCallbacks->onDeviceWrite = ma_device_write__winmm;
19534  pCallbacks->onDeviceDataLoop = NULL; /* This is a blocking read-write API, so this can be NULL since miniaudio will manage the audio thread for us. */
19535 
19536  return MA_SUCCESS;
19537 }
19538 #endif
19539 
19540 
19541 
19542 
19543 /******************************************************************************
19544 
19545 ALSA Backend
19546 
19547 ******************************************************************************/
19548 #ifdef MA_HAS_ALSA
19549 
19550 #include <poll.h> /* poll(), struct pollfd */
19551 #include <sys/eventfd.h> /* eventfd() */
19552 
19553 #ifdef MA_NO_RUNTIME_LINKING
19554 
19555 /* asoundlib.h marks some functions with "inline" which isn't always supported. Need to emulate it. */
19556 #if !defined(__cplusplus)
19557  #if defined(__STRICT_ANSI__)
19558  #if !defined(inline)
19559  #define inline __inline__ __attribute__((always_inline))
19560  #define MA_INLINE_DEFINED
19561  #endif
19562  #endif
19563 #endif
19564 #include <alsa/asoundlib.h>
19565 #if defined(MA_INLINE_DEFINED)
19566  #undef inline
19567  #undef MA_INLINE_DEFINED
19568 #endif
19569 
19570 typedef snd_pcm_uframes_t ma_snd_pcm_uframes_t;
19571 typedef snd_pcm_sframes_t ma_snd_pcm_sframes_t;
19572 typedef snd_pcm_stream_t ma_snd_pcm_stream_t;
19573 typedef snd_pcm_format_t ma_snd_pcm_format_t;
19574 typedef snd_pcm_access_t ma_snd_pcm_access_t;
19575 typedef snd_pcm_t ma_snd_pcm_t;
19576 typedef snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
19577 typedef snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
19578 typedef snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
19579 typedef snd_pcm_info_t ma_snd_pcm_info_t;
19580 typedef snd_pcm_channel_area_t ma_snd_pcm_channel_area_t;
19581 typedef snd_pcm_chmap_t ma_snd_pcm_chmap_t;
19582 typedef snd_pcm_state_t ma_snd_pcm_state_t;
19583 
19584 /* snd_pcm_stream_t */
19585 #define MA_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK
19586 #define MA_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE
19587 
19588 /* snd_pcm_format_t */
19589 #define MA_SND_PCM_FORMAT_UNKNOWN SND_PCM_FORMAT_UNKNOWN
19590 #define MA_SND_PCM_FORMAT_U8 SND_PCM_FORMAT_U8
19591 #define MA_SND_PCM_FORMAT_S16_LE SND_PCM_FORMAT_S16_LE
19592 #define MA_SND_PCM_FORMAT_S16_BE SND_PCM_FORMAT_S16_BE
19593 #define MA_SND_PCM_FORMAT_S24_LE SND_PCM_FORMAT_S24_LE
19594 #define MA_SND_PCM_FORMAT_S24_BE SND_PCM_FORMAT_S24_BE
19595 #define MA_SND_PCM_FORMAT_S32_LE SND_PCM_FORMAT_S32_LE
19596 #define MA_SND_PCM_FORMAT_S32_BE SND_PCM_FORMAT_S32_BE
19597 #define MA_SND_PCM_FORMAT_FLOAT_LE SND_PCM_FORMAT_FLOAT_LE
19598 #define MA_SND_PCM_FORMAT_FLOAT_BE SND_PCM_FORMAT_FLOAT_BE
19599 #define MA_SND_PCM_FORMAT_FLOAT64_LE SND_PCM_FORMAT_FLOAT64_LE
19600 #define MA_SND_PCM_FORMAT_FLOAT64_BE SND_PCM_FORMAT_FLOAT64_BE
19601 #define MA_SND_PCM_FORMAT_MU_LAW SND_PCM_FORMAT_MU_LAW
19602 #define MA_SND_PCM_FORMAT_A_LAW SND_PCM_FORMAT_A_LAW
19603 #define MA_SND_PCM_FORMAT_S24_3LE SND_PCM_FORMAT_S24_3LE
19604 #define MA_SND_PCM_FORMAT_S24_3BE SND_PCM_FORMAT_S24_3BE
19605 
19606 /* ma_snd_pcm_access_t */
19607 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED SND_PCM_ACCESS_MMAP_INTERLEAVED
19608 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED SND_PCM_ACCESS_MMAP_NONINTERLEAVED
19609 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX SND_PCM_ACCESS_MMAP_COMPLEX
19610 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED SND_PCM_ACCESS_RW_INTERLEAVED
19611 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED SND_PCM_ACCESS_RW_NONINTERLEAVED
19612 
19613 /* Channel positions. */
19614 #define MA_SND_CHMAP_UNKNOWN SND_CHMAP_UNKNOWN
19615 #define MA_SND_CHMAP_NA SND_CHMAP_NA
19616 #define MA_SND_CHMAP_MONO SND_CHMAP_MONO
19617 #define MA_SND_CHMAP_FL SND_CHMAP_FL
19618 #define MA_SND_CHMAP_FR SND_CHMAP_FR
19619 #define MA_SND_CHMAP_RL SND_CHMAP_RL
19620 #define MA_SND_CHMAP_RR SND_CHMAP_RR
19621 #define MA_SND_CHMAP_FC SND_CHMAP_FC
19622 #define MA_SND_CHMAP_LFE SND_CHMAP_LFE
19623 #define MA_SND_CHMAP_SL SND_CHMAP_SL
19624 #define MA_SND_CHMAP_SR SND_CHMAP_SR
19625 #define MA_SND_CHMAP_RC SND_CHMAP_RC
19626 #define MA_SND_CHMAP_FLC SND_CHMAP_FLC
19627 #define MA_SND_CHMAP_FRC SND_CHMAP_FRC
19628 #define MA_SND_CHMAP_RLC SND_CHMAP_RLC
19629 #define MA_SND_CHMAP_RRC SND_CHMAP_RRC
19630 #define MA_SND_CHMAP_FLW SND_CHMAP_FLW
19631 #define MA_SND_CHMAP_FRW SND_CHMAP_FRW
19632 #define MA_SND_CHMAP_FLH SND_CHMAP_FLH
19633 #define MA_SND_CHMAP_FCH SND_CHMAP_FCH
19634 #define MA_SND_CHMAP_FRH SND_CHMAP_FRH
19635 #define MA_SND_CHMAP_TC SND_CHMAP_TC
19636 #define MA_SND_CHMAP_TFL SND_CHMAP_TFL
19637 #define MA_SND_CHMAP_TFR SND_CHMAP_TFR
19638 #define MA_SND_CHMAP_TFC SND_CHMAP_TFC
19639 #define MA_SND_CHMAP_TRL SND_CHMAP_TRL
19640 #define MA_SND_CHMAP_TRR SND_CHMAP_TRR
19641 #define MA_SND_CHMAP_TRC SND_CHMAP_TRC
19642 #define MA_SND_CHMAP_TFLC SND_CHMAP_TFLC
19643 #define MA_SND_CHMAP_TFRC SND_CHMAP_TFRC
19644 #define MA_SND_CHMAP_TSL SND_CHMAP_TSL
19645 #define MA_SND_CHMAP_TSR SND_CHMAP_TSR
19646 #define MA_SND_CHMAP_LLFE SND_CHMAP_LLFE
19647 #define MA_SND_CHMAP_RLFE SND_CHMAP_RLFE
19648 #define MA_SND_CHMAP_BC SND_CHMAP_BC
19649 #define MA_SND_CHMAP_BLC SND_CHMAP_BLC
19650 #define MA_SND_CHMAP_BRC SND_CHMAP_BRC
19651 
19652 /* Open mode flags. */
19653 #define MA_SND_PCM_NO_AUTO_RESAMPLE SND_PCM_NO_AUTO_RESAMPLE
19654 #define MA_SND_PCM_NO_AUTO_CHANNELS SND_PCM_NO_AUTO_CHANNELS
19655 #define MA_SND_PCM_NO_AUTO_FORMAT SND_PCM_NO_AUTO_FORMAT
19656 #else
19657 #include <errno.h> /* For EPIPE, etc. */
19658 typedef unsigned long ma_snd_pcm_uframes_t;
19659 typedef long ma_snd_pcm_sframes_t;
19660 typedef int ma_snd_pcm_stream_t;
19661 typedef int ma_snd_pcm_format_t;
19662 typedef int ma_snd_pcm_access_t;
19663 typedef int ma_snd_pcm_state_t;
19664 typedef struct ma_snd_pcm_t ma_snd_pcm_t;
19665 typedef struct ma_snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
19666 typedef struct ma_snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
19667 typedef struct ma_snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
19668 typedef struct ma_snd_pcm_info_t ma_snd_pcm_info_t;
19669 typedef struct
19670 {
19671  void* addr;
19672  unsigned int first;
19673  unsigned int step;
19674 } ma_snd_pcm_channel_area_t;
19675 typedef struct
19676 {
19677  unsigned int channels;
19678  unsigned int pos[1];
19679 } ma_snd_pcm_chmap_t;
19680 
19681 /* snd_pcm_state_t */
19682 #define MA_SND_PCM_STATE_OPEN 0
19683 #define MA_SND_PCM_STATE_SETUP 1
19684 #define MA_SND_PCM_STATE_PREPARED 2
19685 #define MA_SND_PCM_STATE_RUNNING 3
19686 #define MA_SND_PCM_STATE_XRUN 4
19687 #define MA_SND_PCM_STATE_DRAINING 5
19688 #define MA_SND_PCM_STATE_PAUSED 6
19689 #define MA_SND_PCM_STATE_SUSPENDED 7
19690 #define MA_SND_PCM_STATE_DISCONNECTED 8
19691 
19692 /* snd_pcm_stream_t */
19693 #define MA_SND_PCM_STREAM_PLAYBACK 0
19694 #define MA_SND_PCM_STREAM_CAPTURE 1
19695 
19696 /* snd_pcm_format_t */
19697 #define MA_SND_PCM_FORMAT_UNKNOWN -1
19698 #define MA_SND_PCM_FORMAT_U8 1
19699 #define MA_SND_PCM_FORMAT_S16_LE 2
19700 #define MA_SND_PCM_FORMAT_S16_BE 3
19701 #define MA_SND_PCM_FORMAT_S24_LE 6
19702 #define MA_SND_PCM_FORMAT_S24_BE 7
19703 #define MA_SND_PCM_FORMAT_S32_LE 10
19704 #define MA_SND_PCM_FORMAT_S32_BE 11
19705 #define MA_SND_PCM_FORMAT_FLOAT_LE 14
19706 #define MA_SND_PCM_FORMAT_FLOAT_BE 15
19707 #define MA_SND_PCM_FORMAT_FLOAT64_LE 16
19708 #define MA_SND_PCM_FORMAT_FLOAT64_BE 17
19709 #define MA_SND_PCM_FORMAT_MU_LAW 20
19710 #define MA_SND_PCM_FORMAT_A_LAW 21
19711 #define MA_SND_PCM_FORMAT_S24_3LE 32
19712 #define MA_SND_PCM_FORMAT_S24_3BE 33
19713 
19714 /* snd_pcm_access_t */
19715 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED 0
19716 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED 1
19717 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX 2
19718 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED 3
19719 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED 4
19720 
19721 /* Channel positions. */
19722 #define MA_SND_CHMAP_UNKNOWN 0
19723 #define MA_SND_CHMAP_NA 1
19724 #define MA_SND_CHMAP_MONO 2
19725 #define MA_SND_CHMAP_FL 3
19726 #define MA_SND_CHMAP_FR 4
19727 #define MA_SND_CHMAP_RL 5
19728 #define MA_SND_CHMAP_RR 6
19729 #define MA_SND_CHMAP_FC 7
19730 #define MA_SND_CHMAP_LFE 8
19731 #define MA_SND_CHMAP_SL 9
19732 #define MA_SND_CHMAP_SR 10
19733 #define MA_SND_CHMAP_RC 11
19734 #define MA_SND_CHMAP_FLC 12
19735 #define MA_SND_CHMAP_FRC 13
19736 #define MA_SND_CHMAP_RLC 14
19737 #define MA_SND_CHMAP_RRC 15
19738 #define MA_SND_CHMAP_FLW 16
19739 #define MA_SND_CHMAP_FRW 17
19740 #define MA_SND_CHMAP_FLH 18
19741 #define MA_SND_CHMAP_FCH 19
19742 #define MA_SND_CHMAP_FRH 20
19743 #define MA_SND_CHMAP_TC 21
19744 #define MA_SND_CHMAP_TFL 22
19745 #define MA_SND_CHMAP_TFR 23
19746 #define MA_SND_CHMAP_TFC 24
19747 #define MA_SND_CHMAP_TRL 25
19748 #define MA_SND_CHMAP_TRR 26
19749 #define MA_SND_CHMAP_TRC 27
19750 #define MA_SND_CHMAP_TFLC 28
19751 #define MA_SND_CHMAP_TFRC 29
19752 #define MA_SND_CHMAP_TSL 30
19753 #define MA_SND_CHMAP_TSR 31
19754 #define MA_SND_CHMAP_LLFE 32
19755 #define MA_SND_CHMAP_RLFE 33
19756 #define MA_SND_CHMAP_BC 34
19757 #define MA_SND_CHMAP_BLC 35
19758 #define MA_SND_CHMAP_BRC 36
19759 
19760 /* Open mode flags. */
19761 #define MA_SND_PCM_NO_AUTO_RESAMPLE 0x00010000
19762 #define MA_SND_PCM_NO_AUTO_CHANNELS 0x00020000
19763 #define MA_SND_PCM_NO_AUTO_FORMAT 0x00040000
19764 #endif
19765 
19766 typedef int (* ma_snd_pcm_open_proc) (ma_snd_pcm_t **pcm, const char *name, ma_snd_pcm_stream_t stream, int mode);
19767 typedef int (* ma_snd_pcm_close_proc) (ma_snd_pcm_t *pcm);
19768 typedef size_t (* ma_snd_pcm_hw_params_sizeof_proc) (void);
19769 typedef int (* ma_snd_pcm_hw_params_any_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params);
19770 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);
19771 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);
19772 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);
19773 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);
19774 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);
19775 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);
19776 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);
19777 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);
19778 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);
19779 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);
19780 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);
19781 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);
19782 typedef int (* ma_snd_pcm_hw_params_get_format_proc) (const ma_snd_pcm_hw_params_t *params, ma_snd_pcm_format_t *format);
19783 typedef int (* ma_snd_pcm_hw_params_get_channels_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val);
19784 typedef int (* ma_snd_pcm_hw_params_get_channels_min_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val);
19785 typedef int (* ma_snd_pcm_hw_params_get_channels_max_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val);
19786 typedef int (* ma_snd_pcm_hw_params_get_rate_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *rate, int *dir);
19787 typedef int (* ma_snd_pcm_hw_params_get_rate_min_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *rate, int *dir);
19788 typedef int (* ma_snd_pcm_hw_params_get_rate_max_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *rate, int *dir);
19789 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);
19790 typedef int (* ma_snd_pcm_hw_params_get_periods_proc) (const ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
19791 typedef int (* ma_snd_pcm_hw_params_get_access_proc) (const ma_snd_pcm_hw_params_t *params, ma_snd_pcm_access_t *_access);
19792 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);
19793 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);
19794 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);
19795 typedef int (* ma_snd_pcm_hw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params);
19796 typedef size_t (* ma_snd_pcm_sw_params_sizeof_proc) (void);
19797 typedef int (* ma_snd_pcm_sw_params_current_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params);
19798 typedef int (* ma_snd_pcm_sw_params_get_boundary_proc) (const ma_snd_pcm_sw_params_t *params, ma_snd_pcm_uframes_t* val);
19799 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);
19800 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);
19801 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);
19802 typedef int (* ma_snd_pcm_sw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *params);
19803 typedef size_t (* ma_snd_pcm_format_mask_sizeof_proc) (void);
19804 typedef int (* ma_snd_pcm_format_mask_test_proc) (const ma_snd_pcm_format_mask_t *mask, ma_snd_pcm_format_t val);
19805 typedef ma_snd_pcm_chmap_t * (* ma_snd_pcm_get_chmap_proc) (ma_snd_pcm_t *pcm);
19806 typedef ma_snd_pcm_state_t (* ma_snd_pcm_state_proc) (ma_snd_pcm_t *pcm);
19807 typedef int (* ma_snd_pcm_prepare_proc) (ma_snd_pcm_t *pcm);
19808 typedef int (* ma_snd_pcm_start_proc) (ma_snd_pcm_t *pcm);
19809 typedef int (* ma_snd_pcm_drop_proc) (ma_snd_pcm_t *pcm);
19810 typedef int (* ma_snd_pcm_drain_proc) (ma_snd_pcm_t *pcm);
19811 typedef int (* ma_snd_pcm_reset_proc) (ma_snd_pcm_t *pcm);
19812 typedef int (* ma_snd_device_name_hint_proc) (int card, const char *iface, void ***hints);
19813 typedef char * (* ma_snd_device_name_get_hint_proc) (const void *hint, const char *id);
19814 typedef int (* ma_snd_card_get_index_proc) (const char *name);
19815 typedef int (* ma_snd_device_name_free_hint_proc) (void **hints);
19816 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);
19817 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);
19818 typedef int (* ma_snd_pcm_recover_proc) (ma_snd_pcm_t *pcm, int err, int silent);
19819 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_readi_proc) (ma_snd_pcm_t *pcm, void *buffer, ma_snd_pcm_uframes_t size);
19820 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);
19821 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_proc) (ma_snd_pcm_t *pcm);
19822 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_update_proc) (ma_snd_pcm_t *pcm);
19823 typedef int (* ma_snd_pcm_wait_proc) (ma_snd_pcm_t *pcm, int timeout);
19824 typedef int (* ma_snd_pcm_nonblock_proc) (ma_snd_pcm_t *pcm, int nonblock);
19825 typedef int (* ma_snd_pcm_info_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_info_t* info);
19826 typedef size_t (* ma_snd_pcm_info_sizeof_proc) (void);
19827 typedef const char* (* ma_snd_pcm_info_get_name_proc) (const ma_snd_pcm_info_t* info);
19828 typedef int (* ma_snd_pcm_poll_descriptors_proc) (ma_snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
19829 typedef int (* ma_snd_pcm_poll_descriptors_count_proc) (ma_snd_pcm_t *pcm);
19830 typedef int (* ma_snd_pcm_poll_descriptors_revents_proc) (ma_snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
19831 typedef int (* ma_snd_config_update_free_global_proc) (void);
19832 
19833 /* This array specifies each of the common devices that can be used for both playback and capture. */
19834 static const char* g_maCommonDeviceNamesALSA[] = {
19835  "default",
19836  "null",
19837  "pulse",
19838  "jack"
19839 };
19840 
19841 /* This array allows us to blacklist specific playback devices. */
19842 static const char* g_maBlacklistedPlaybackDeviceNamesALSA[] = {
19843  ""
19844 };
19845 
19846 /* This array allows us to blacklist specific capture devices. */
19847 static const char* g_maBlacklistedCaptureDeviceNamesALSA[] = {
19848  ""
19849 };
19850 
19851 
19852 static ma_snd_pcm_format_t ma_convert_ma_format_to_alsa_format(ma_format format)
19853 {
19854  ma_snd_pcm_format_t ALSAFormats[] = {
19855  MA_SND_PCM_FORMAT_UNKNOWN, /* ma_format_unknown */
19856  MA_SND_PCM_FORMAT_U8, /* ma_format_u8 */
19857  MA_SND_PCM_FORMAT_S16_LE, /* ma_format_s16 */
19858  MA_SND_PCM_FORMAT_S24_3LE, /* ma_format_s24 */
19859  MA_SND_PCM_FORMAT_S32_LE, /* ma_format_s32 */
19860  MA_SND_PCM_FORMAT_FLOAT_LE /* ma_format_f32 */
19861  };
19862 
19863  if (ma_is_big_endian()) {
19864  ALSAFormats[0] = MA_SND_PCM_FORMAT_UNKNOWN;
19865  ALSAFormats[1] = MA_SND_PCM_FORMAT_U8;
19866  ALSAFormats[2] = MA_SND_PCM_FORMAT_S16_BE;
19867  ALSAFormats[3] = MA_SND_PCM_FORMAT_S24_3BE;
19868  ALSAFormats[4] = MA_SND_PCM_FORMAT_S32_BE;
19869  ALSAFormats[5] = MA_SND_PCM_FORMAT_FLOAT_BE;
19870  }
19871 
19872  return ALSAFormats[format];
19873 }
19874 
19875 static ma_format ma_format_from_alsa(ma_snd_pcm_format_t formatALSA)
19876 {
19877  if (ma_is_little_endian()) {
19878  switch (formatALSA) {
19879  case MA_SND_PCM_FORMAT_S16_LE: return ma_format_s16;
19880  case MA_SND_PCM_FORMAT_S24_3LE: return ma_format_s24;
19881  case MA_SND_PCM_FORMAT_S32_LE: return ma_format_s32;
19882  case MA_SND_PCM_FORMAT_FLOAT_LE: return ma_format_f32;
19883  default: break;
19884  }
19885  } else {
19886  switch (formatALSA) {
19887  case MA_SND_PCM_FORMAT_S16_BE: return ma_format_s16;
19888  case MA_SND_PCM_FORMAT_S24_3BE: return ma_format_s24;
19889  case MA_SND_PCM_FORMAT_S32_BE: return ma_format_s32;
19890  case MA_SND_PCM_FORMAT_FLOAT_BE: return ma_format_f32;
19891  default: break;
19892  }
19893  }
19894 
19895  /* Endian agnostic. */
19896  switch (formatALSA) {
19897  case MA_SND_PCM_FORMAT_U8: return ma_format_u8;
19898  default: return ma_format_unknown;
19899  }
19900 }
19901 
19902 static ma_channel ma_convert_alsa_channel_position_to_ma_channel(unsigned int alsaChannelPos)
19903 {
19904  switch (alsaChannelPos)
19905  {
19906  case MA_SND_CHMAP_MONO: return MA_CHANNEL_MONO;
19907  case MA_SND_CHMAP_FL: return MA_CHANNEL_FRONT_LEFT;
19908  case MA_SND_CHMAP_FR: return MA_CHANNEL_FRONT_RIGHT;
19909  case MA_SND_CHMAP_RL: return MA_CHANNEL_BACK_LEFT;
19910  case MA_SND_CHMAP_RR: return MA_CHANNEL_BACK_RIGHT;
19911  case MA_SND_CHMAP_FC: return MA_CHANNEL_FRONT_CENTER;
19912  case MA_SND_CHMAP_LFE: return MA_CHANNEL_LFE;
19913  case MA_SND_CHMAP_SL: return MA_CHANNEL_SIDE_LEFT;
19914  case MA_SND_CHMAP_SR: return MA_CHANNEL_SIDE_RIGHT;
19915  case MA_SND_CHMAP_RC: return MA_CHANNEL_BACK_CENTER;
19916  case MA_SND_CHMAP_FLC: return MA_CHANNEL_FRONT_LEFT_CENTER;
19917  case MA_SND_CHMAP_FRC: return MA_CHANNEL_FRONT_RIGHT_CENTER;
19918  case MA_SND_CHMAP_RLC: return 0;
19919  case MA_SND_CHMAP_RRC: return 0;
19920  case MA_SND_CHMAP_FLW: return 0;
19921  case MA_SND_CHMAP_FRW: return 0;
19922  case MA_SND_CHMAP_FLH: return 0;
19923  case MA_SND_CHMAP_FCH: return 0;
19924  case MA_SND_CHMAP_FRH: return 0;
19925  case MA_SND_CHMAP_TC: return MA_CHANNEL_TOP_CENTER;
19926  case MA_SND_CHMAP_TFL: return MA_CHANNEL_TOP_FRONT_LEFT;
19927  case MA_SND_CHMAP_TFR: return MA_CHANNEL_TOP_FRONT_RIGHT;
19928  case MA_SND_CHMAP_TFC: return MA_CHANNEL_TOP_FRONT_CENTER;
19929  case MA_SND_CHMAP_TRL: return MA_CHANNEL_TOP_BACK_LEFT;
19930  case MA_SND_CHMAP_TRR: return MA_CHANNEL_TOP_BACK_RIGHT;
19931  case MA_SND_CHMAP_TRC: return MA_CHANNEL_TOP_BACK_CENTER;
19932  default: break;
19933  }
19934 
19935  return 0;
19936 }
19937 
19938 static ma_bool32 ma_is_common_device_name__alsa(const char* name)
19939 {
19940  size_t iName;
19941  for (iName = 0; iName < ma_countof(g_maCommonDeviceNamesALSA); ++iName) {
19942  if (ma_strcmp(name, g_maCommonDeviceNamesALSA[iName]) == 0) {
19943  return MA_TRUE;
19944  }
19945  }
19946 
19947  return MA_FALSE;
19948 }
19949 
19950 
19951 static ma_bool32 ma_is_playback_device_blacklisted__alsa(const char* name)
19952 {
19953  size_t iName;
19954  for (iName = 0; iName < ma_countof(g_maBlacklistedPlaybackDeviceNamesALSA); ++iName) {
19955  if (ma_strcmp(name, g_maBlacklistedPlaybackDeviceNamesALSA[iName]) == 0) {
19956  return MA_TRUE;
19957  }
19958  }
19959 
19960  return MA_FALSE;
19961 }
19962 
19963 static ma_bool32 ma_is_capture_device_blacklisted__alsa(const char* name)
19964 {
19965  size_t iName;
19966  for (iName = 0; iName < ma_countof(g_maBlacklistedCaptureDeviceNamesALSA); ++iName) {
19967  if (ma_strcmp(name, g_maBlacklistedCaptureDeviceNamesALSA[iName]) == 0) {
19968  return MA_TRUE;
19969  }
19970  }
19971 
19972  return MA_FALSE;
19973 }
19974 
19975 static ma_bool32 ma_is_device_blacklisted__alsa(ma_device_type deviceType, const char* name)
19976 {
19977  if (deviceType == ma_device_type_playback) {
19978  return ma_is_playback_device_blacklisted__alsa(name);
19979  } else {
19980  return ma_is_capture_device_blacklisted__alsa(name);
19981  }
19982 }
19983 
19984 
19985 static const char* ma_find_char(const char* str, char c, int* index)
19986 {
19987  int i = 0;
19988  for (;;) {
19989  if (str[i] == '\0') {
19990  if (index) *index = -1;
19991  return NULL;
19992  }
19993 
19994  if (str[i] == c) {
19995  if (index) *index = i;
19996  return str + i;
19997  }
19998 
19999  i += 1;
20000  }
20001 
20002  /* Should never get here, but treat it as though the character was not found to make me feel better inside. */
20003  if (index) *index = -1;
20004  return NULL;
20005 }
20006 
20007 static ma_bool32 ma_is_device_name_in_hw_format__alsa(const char* hwid)
20008 {
20009  /* This function is just checking whether or not hwid is in "hw:%d,%d" format. */
20010 
20011  int commaPos;
20012  const char* dev;
20013  int i;
20014 
20015  if (hwid == NULL) {
20016  return MA_FALSE;
20017  }
20018 
20019  if (hwid[0] != 'h' || hwid[1] != 'w' || hwid[2] != ':') {
20020  return MA_FALSE;
20021  }
20022 
20023  hwid += 3;
20024 
20025  dev = ma_find_char(hwid, ',', &commaPos);
20026  if (dev == NULL) {
20027  return MA_FALSE;
20028  } else {
20029  dev += 1; /* Skip past the ",". */
20030  }
20031 
20032  /* Check if the part between the ":" and the "," contains only numbers. If not, return false. */
20033  for (i = 0; i < commaPos; ++i) {
20034  if (hwid[i] < '0' || hwid[i] > '9') {
20035  return MA_FALSE;
20036  }
20037  }
20038 
20039  /* Check if everything after the "," is numeric. If not, return false. */
20040  i = 0;
20041  while (dev[i] != '\0') {
20042  if (dev[i] < '0' || dev[i] > '9') {
20043  return MA_FALSE;
20044  }
20045  i += 1;
20046  }
20047 
20048  return MA_TRUE;
20049 }
20050 
20051 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. */
20052 {
20053  /* src should look something like this: "hw:CARD=I82801AAICH,DEV=0" */
20054 
20055  int colonPos;
20056  int commaPos;
20057  char card[256];
20058  const char* dev;
20059  int cardIndex;
20060 
20061  if (dst == NULL) {
20062  return -1;
20063  }
20064  if (dstSize < 7) {
20065  return -1; /* Absolute minimum size of the output buffer is 7 bytes. */
20066  }
20067 
20068  *dst = '\0'; /* Safety. */
20069  if (src == NULL) {
20070  return -1;
20071  }
20072 
20073  /* If the input name is already in "hw:%d,%d" format, just return that verbatim. */
20074  if (ma_is_device_name_in_hw_format__alsa(src)) {
20075  return ma_strcpy_s(dst, dstSize, src);
20076  }
20077 
20078  src = ma_find_char(src, ':', &colonPos);
20079  if (src == NULL) {
20080  return -1; /* Couldn't find a colon */
20081  }
20082 
20083  dev = ma_find_char(src, ',', &commaPos);
20084  if (dev == NULL) {
20085  dev = "0";
20086  ma_strncpy_s(card, sizeof(card), src+6, (size_t)-1); /* +6 = ":CARD=" */
20087  } else {
20088  dev = dev + 5; /* +5 = ",DEV=" */
20089  ma_strncpy_s(card, sizeof(card), src+6, commaPos-6); /* +6 = ":CARD=" */
20090  }
20091 
20092  cardIndex = ((ma_snd_card_get_index_proc)pContext->alsa.snd_card_get_index)(card);
20093  if (cardIndex < 0) {
20094  return -2; /* Failed to retrieve the card index. */
20095  }
20096 
20097 
20098  /* Construction. */
20099  dst[0] = 'h'; dst[1] = 'w'; dst[2] = ':';
20100  if (ma_itoa_s(cardIndex, dst+3, dstSize-3, 10) != 0) {
20101  return -3;
20102  }
20103  if (ma_strcat_s(dst, dstSize, ",") != 0) {
20104  return -3;
20105  }
20106  if (ma_strcat_s(dst, dstSize, dev) != 0) {
20107  return -3;
20108  }
20109 
20110  return 0;
20111 }
20112 
20113 static ma_bool32 ma_does_id_exist_in_list__alsa(ma_device_id* pUniqueIDs, ma_uint32 count, const char* pHWID)
20114 {
20115  ma_uint32 i;
20116 
20117  MA_ASSERT(pHWID != NULL);
20118 
20119  for (i = 0; i < count; ++i) {
20120  if (ma_strcmp(pUniqueIDs[i].alsa, pHWID) == 0) {
20121  return MA_TRUE;
20122  }
20123  }
20124 
20125  return MA_FALSE;
20126 }
20127 
20128 
20129 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)
20130 {
20131  ma_snd_pcm_t* pPCM;
20132  ma_snd_pcm_stream_t stream;
20133 
20134  MA_ASSERT(pContext != NULL);
20135  MA_ASSERT(ppPCM != NULL);
20136 
20137  *ppPCM = NULL;
20138  pPCM = NULL;
20139 
20140  stream = (deviceType == ma_device_type_playback) ? MA_SND_PCM_STREAM_PLAYBACK : MA_SND_PCM_STREAM_CAPTURE;
20141 
20142  if (pDeviceID == NULL) {
20143  ma_bool32 isDeviceOpen;
20144  size_t i;
20145 
20146  /*
20147  We're opening the default device. I don't know if trying anything other than "default" is necessary, but it makes
20148  me feel better to try as hard as we can get to get _something_ working.
20149  */
20150  const char* defaultDeviceNames[] = {
20151  "default",
20152  NULL,
20153  NULL,
20154  NULL,
20155  NULL,
20156  NULL,
20157  NULL
20158  };
20159 
20160  if (shareMode == ma_share_mode_exclusive) {
20161  defaultDeviceNames[1] = "hw";
20162  defaultDeviceNames[2] = "hw:0";
20163  defaultDeviceNames[3] = "hw:0,0";
20164  } else {
20165  if (deviceType == ma_device_type_playback) {
20166  defaultDeviceNames[1] = "dmix";
20167  defaultDeviceNames[2] = "dmix:0";
20168  defaultDeviceNames[3] = "dmix:0,0";
20169  } else {
20170  defaultDeviceNames[1] = "dsnoop";
20171  defaultDeviceNames[2] = "dsnoop:0";
20172  defaultDeviceNames[3] = "dsnoop:0,0";
20173  }
20174  defaultDeviceNames[4] = "hw";
20175  defaultDeviceNames[5] = "hw:0";
20176  defaultDeviceNames[6] = "hw:0,0";
20177  }
20178 
20179  isDeviceOpen = MA_FALSE;
20180  for (i = 0; i < ma_countof(defaultDeviceNames); ++i) {
20181  if (defaultDeviceNames[i] != NULL && defaultDeviceNames[i][0] != '\0') {
20182  if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, defaultDeviceNames[i], stream, openMode) == 0) {
20183  isDeviceOpen = MA_TRUE;
20184  break;
20185  }
20186  }
20187  }
20188 
20189  if (!isDeviceOpen) {
20190  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);
20191  }
20192  } else {
20193  /*
20194  We're trying to open a specific device. There's a few things to consider here:
20195 
20196  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
20197  an ID of this format is specified, it indicates to miniaudio that it can try different combinations of plugins ("hw", "dmix", etc.) until it
20198  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").
20199  */
20200 
20201  /* May end up needing to make small adjustments to the ID, so make a copy. */
20202  ma_device_id deviceID = *pDeviceID;
20203  int resultALSA = -ENODEV;
20204 
20205  if (deviceID.alsa[0] != ':') {
20206  /* The ID is not in ":0,0" format. Use the ID exactly as-is. */
20207  resultALSA = ((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, deviceID.alsa, stream, openMode);
20208  } else {
20209  char hwid[256];
20210 
20211  /* The ID is in ":0,0" format. Try different plugins depending on the shared mode. */
20212  if (deviceID.alsa[1] == '\0') {
20213  deviceID.alsa[0] = '\0'; /* An ID of ":" should be converted to "". */
20214  }
20215 
20216  if (shareMode == ma_share_mode_shared) {
20217  if (deviceType == ma_device_type_playback) {
20218  ma_strcpy_s(hwid, sizeof(hwid), "dmix");
20219  } else {
20220  ma_strcpy_s(hwid, sizeof(hwid), "dsnoop");
20221  }
20222 
20223  if (ma_strcat_s(hwid, sizeof(hwid), deviceID.alsa) == 0) {
20224  resultALSA = ((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid, stream, openMode);
20225  }
20226  }
20227 
20228  /* 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. */
20229  if (resultALSA != 0) {
20230  ma_strcpy_s(hwid, sizeof(hwid), "hw");
20231  if (ma_strcat_s(hwid, sizeof(hwid), deviceID.alsa) == 0) {
20232  resultALSA = ((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid, stream, openMode);
20233  }
20234  }
20235  }
20236 
20237  if (resultALSA < 0) {
20238  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_open() failed.", ma_result_from_errno(-resultALSA));
20239  }
20240  }
20241 
20242  *ppPCM = pPCM;
20243  return MA_SUCCESS;
20244 }
20245 
20246 
20247 static ma_result ma_context_enumerate_devices__alsa(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
20248 {
20249  int resultALSA;
20250  ma_bool32 cbResult = MA_TRUE;
20251  char** ppDeviceHints;
20252  ma_device_id* pUniqueIDs = NULL;
20253  ma_uint32 uniqueIDCount = 0;
20254  char** ppNextDeviceHint;
20255 
20256  MA_ASSERT(pContext != NULL);
20257  MA_ASSERT(callback != NULL);
20258 
20259  ma_mutex_lock(&pContext->alsa.internalDeviceEnumLock);
20260 
20261  resultALSA = ((ma_snd_device_name_hint_proc)pContext->alsa.snd_device_name_hint)(-1, "pcm", (void***)&ppDeviceHints);
20262  if (resultALSA < 0) {
20263  ma_mutex_unlock(&pContext->alsa.internalDeviceEnumLock);
20264  return ma_result_from_errno(-resultALSA);
20265  }
20266 
20267  ppNextDeviceHint = ppDeviceHints;
20268  while (*ppNextDeviceHint != NULL) {
20269  char* NAME = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint, "NAME");
20270  char* DESC = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint, "DESC");
20271  char* IOID = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint, "IOID");
20273  ma_bool32 stopEnumeration = MA_FALSE;
20274  char hwid[sizeof(pUniqueIDs->alsa)];
20275  ma_device_info deviceInfo;
20276 
20277  if ((IOID == NULL || ma_strcmp(IOID, "Output") == 0)) {
20278  deviceType = ma_device_type_playback;
20279  }
20280  if ((IOID != NULL && ma_strcmp(IOID, "Input" ) == 0)) {
20281  deviceType = ma_device_type_capture;
20282  }
20283 
20284  if (NAME != NULL) {
20285  if (pContext->alsa.useVerboseDeviceEnumeration) {
20286  /* Verbose mode. Use the name exactly as-is. */
20287  ma_strncpy_s(hwid, sizeof(hwid), NAME, (size_t)-1);
20288  } else {
20289  /* Simplified mode. Use ":%d,%d" format. */
20290  if (ma_convert_device_name_to_hw_format__alsa(pContext, hwid, sizeof(hwid), NAME) == 0) {
20291  /*
20292  At this point, hwid looks like "hw:0,0". In simplified enumeration mode, we actually want to strip off the
20293  plugin name so it looks like ":0,0". The reason for this is that this special format is detected at device
20294  initialization time and is used as an indicator to try and use the most appropriate plugin depending on the
20295  device type and sharing mode.
20296  */
20297  char* dst = hwid;
20298  char* src = hwid+2;
20299  while ((*dst++ = *src++));
20300  } else {
20301  /* Conversion to "hw:%d,%d" failed. Just use the name as-is. */
20302  ma_strncpy_s(hwid, sizeof(hwid), NAME, (size_t)-1);
20303  }
20304 
20305  if (ma_does_id_exist_in_list__alsa(pUniqueIDs, uniqueIDCount, hwid)) {
20306  goto next_device; /* The device has already been enumerated. Move on to the next one. */
20307  } else {
20308  /* The device has not yet been enumerated. Make sure it's added to our list so that it's not enumerated again. */
20309  size_t oldCapacity = sizeof(*pUniqueIDs) * uniqueIDCount;
20310  size_t newCapacity = sizeof(*pUniqueIDs) * (uniqueIDCount + 1);
20311  ma_device_id* pNewUniqueIDs = (ma_device_id*)ma__realloc_from_callbacks(pUniqueIDs, newCapacity, oldCapacity, &pContext->allocationCallbacks);
20312  if (pNewUniqueIDs == NULL) {
20313  goto next_device; /* Failed to allocate memory. */
20314  }
20315 
20316  pUniqueIDs = pNewUniqueIDs;
20317  MA_COPY_MEMORY(pUniqueIDs[uniqueIDCount].alsa, hwid, sizeof(hwid));
20318  uniqueIDCount += 1;
20319  }
20320  }
20321  } else {
20322  MA_ZERO_MEMORY(hwid, sizeof(hwid));
20323  }
20324 
20325  MA_ZERO_OBJECT(&deviceInfo);
20326  ma_strncpy_s(deviceInfo.id.alsa, sizeof(deviceInfo.id.alsa), hwid, (size_t)-1);
20327 
20328  /*
20329  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
20330  just use the name of "default" as the indicator.
20331  */
20332  if (ma_strcmp(deviceInfo.id.alsa, "default") == 0) {
20333  deviceInfo.isDefault = MA_TRUE;
20334  }
20335 
20336 
20337  /*
20338  DESC is the friendly name. We treat this slightly differently depending on whether or not we are using verbose
20339  device enumeration. In verbose mode we want to take the entire description so that the end-user can distinguish
20340  between the subdevices of each card/dev pair. In simplified mode, however, we only want the first part of the
20341  description.
20342 
20343  The value in DESC seems to be split into two lines, with the first line being the name of the device and the
20344  second line being a description of the device. I don't like having the description be across two lines because
20345  it makes formatting ugly and annoying. I'm therefore deciding to put it all on a single line with the second line
20346  being put into parentheses. In simplified mode I'm just stripping the second line entirely.
20347  */
20348  if (DESC != NULL) {
20349  int lfPos;
20350  const char* line2 = ma_find_char(DESC, '\n', &lfPos);
20351  if (line2 != NULL) {
20352  line2 += 1; /* Skip past the new-line character. */
20353 
20354  if (pContext->alsa.useVerboseDeviceEnumeration) {
20355  /* Verbose mode. Put the second line in brackets. */
20356  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), DESC, lfPos);
20357  ma_strcat_s (deviceInfo.name, sizeof(deviceInfo.name), " (");
20358  ma_strcat_s (deviceInfo.name, sizeof(deviceInfo.name), line2);
20359  ma_strcat_s (deviceInfo.name, sizeof(deviceInfo.name), ")");
20360  } else {
20361  /* Simplified mode. Strip the second line entirely. */
20362  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), DESC, lfPos);
20363  }
20364  } else {
20365  /* There's no second line. Just copy the whole description. */
20366  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), DESC, (size_t)-1);
20367  }
20368  }
20369 
20370  if (!ma_is_device_blacklisted__alsa(deviceType, NAME)) {
20371  cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
20372  }
20373 
20374  /*
20375  Some devices are both playback and capture, but they are only enumerated by ALSA once. We need to fire the callback
20376  again for the other device type in this case. We do this for known devices.
20377  */
20378  if (cbResult) {
20379  if (ma_is_common_device_name__alsa(NAME)) {
20380  if (deviceType == ma_device_type_playback) {
20381  if (!ma_is_capture_device_blacklisted__alsa(NAME)) {
20382  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
20383  }
20384  } else {
20385  if (!ma_is_playback_device_blacklisted__alsa(NAME)) {
20386  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
20387  }
20388  }
20389  }
20390  }
20391 
20392  if (cbResult == MA_FALSE) {
20393  stopEnumeration = MA_TRUE;
20394  }
20395 
20396  next_device:
20397  free(NAME);
20398  free(DESC);
20399  free(IOID);
20400  ppNextDeviceHint += 1;
20401 
20402  /* We need to stop enumeration if the callback returned false. */
20403  if (stopEnumeration) {
20404  break;
20405  }
20406  }
20407 
20408  ma__free_from_callbacks(pUniqueIDs, &pContext->allocationCallbacks);
20409  ((ma_snd_device_name_free_hint_proc)pContext->alsa.snd_device_name_free_hint)((void**)ppDeviceHints);
20410 
20411  ma_mutex_unlock(&pContext->alsa.internalDeviceEnumLock);
20412 
20413  return MA_SUCCESS;
20414 }
20415 
20416 
20417 typedef struct
20418 {
20419  ma_device_type deviceType;
20420  const ma_device_id* pDeviceID;
20421  ma_share_mode shareMode;
20422  ma_device_info* pDeviceInfo;
20423  ma_bool32 foundDevice;
20424 } ma_context_get_device_info_enum_callback_data__alsa;
20425 
20426 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)
20427 {
20428  ma_context_get_device_info_enum_callback_data__alsa* pData = (ma_context_get_device_info_enum_callback_data__alsa*)pUserData;
20429  MA_ASSERT(pData != NULL);
20430 
20431  (void)pContext;
20432 
20433  if (pData->pDeviceID == NULL && ma_strcmp(pDeviceInfo->id.alsa, "default") == 0) {
20434  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pDeviceInfo->name, (size_t)-1);
20435  pData->foundDevice = MA_TRUE;
20436  } else {
20437  if (pData->deviceType == deviceType && (pData->pDeviceID != NULL && ma_strcmp(pData->pDeviceID->alsa, pDeviceInfo->id.alsa) == 0)) {
20438  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pDeviceInfo->name, (size_t)-1);
20439  pData->foundDevice = MA_TRUE;
20440  }
20441  }
20442 
20443  /* Keep enumerating until we have found the device. */
20444  return !pData->foundDevice;
20445 }
20446 
20447 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)
20448 {
20449  MA_ASSERT(pPCM != NULL);
20450  MA_ASSERT(pHWParams != NULL);
20451  MA_ASSERT(pDeviceInfo != NULL);
20452 
20453  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) {
20454  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
20455  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
20456  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
20457  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = flags;
20458  pDeviceInfo->nativeDataFormatCount += 1;
20459  }
20460 }
20461 
20462 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)
20463 {
20464  ma_uint32 iSampleRate;
20465  unsigned int minSampleRate;
20466  unsigned int maxSampleRate;
20467  int sampleRateDir; /* Not used. Just passed into snd_pcm_hw_params_get_rate_min/max(). */
20468 
20469  /* There could be a range. */
20470  ((ma_snd_pcm_hw_params_get_rate_min_proc)pContext->alsa.snd_pcm_hw_params_get_rate_min)(pHWParams, &minSampleRate, &sampleRateDir);
20471  ((ma_snd_pcm_hw_params_get_rate_max_proc)pContext->alsa.snd_pcm_hw_params_get_rate_max)(pHWParams, &maxSampleRate, &sampleRateDir);
20472 
20473  /* Make sure our sample rates are clamped to sane values. Stupid devices like "pulse" will reports rates like "1" which is ridiculus. */
20474  minSampleRate = ma_clamp(minSampleRate, (unsigned int)ma_standard_sample_rate_min, (unsigned int)ma_standard_sample_rate_max);
20475  maxSampleRate = ma_clamp(maxSampleRate, (unsigned int)ma_standard_sample_rate_min, (unsigned int)ma_standard_sample_rate_max);
20476 
20477  for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); iSampleRate += 1) {
20478  ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iSampleRate];
20479 
20480  if (standardSampleRate >= minSampleRate && standardSampleRate <= maxSampleRate) {
20481  ma_context_test_rate_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, standardSampleRate, flags, pDeviceInfo);
20482  }
20483  }
20484 
20485  /* Now make sure our min and max rates are included just in case they aren't in the range of our standard rates. */
20486  if (!ma_is_standard_sample_rate(minSampleRate)) {
20487  ma_context_test_rate_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, minSampleRate, flags, pDeviceInfo);
20488  }
20489 
20490  if (!ma_is_standard_sample_rate(maxSampleRate) && maxSampleRate != minSampleRate) {
20491  ma_context_test_rate_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, maxSampleRate, flags, pDeviceInfo);
20492  }
20493 }
20494 
20495 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)
20496 {
20497  ma_context_get_device_info_enum_callback_data__alsa data;
20498  ma_result result;
20499  int resultALSA;
20500  ma_snd_pcm_t* pPCM;
20501  ma_snd_pcm_hw_params_t* pHWParams;
20502  ma_uint32 iFormat;
20503  ma_uint32 iChannel;
20504 
20505  MA_ASSERT(pContext != NULL);
20506 
20507  /* We just enumerate to find basic information about the device. */
20508  data.deviceType = deviceType;
20509  data.pDeviceID = pDeviceID;
20510  data.pDeviceInfo = pDeviceInfo;
20511  data.foundDevice = MA_FALSE;
20512  result = ma_context_enumerate_devices__alsa(pContext, ma_context_get_device_info_enum_callback__alsa, &data);
20513  if (result != MA_SUCCESS) {
20514  return result;
20515  }
20516 
20517  if (!data.foundDevice) {
20518  return MA_NO_DEVICE;
20519  }
20520 
20521  if (ma_strcmp(pDeviceInfo->id.alsa, "default") == 0) {
20522  pDeviceInfo->isDefault = MA_TRUE;
20523  }
20524 
20525  /* For detailed info we need to open the device. */
20526  result = ma_context_open_pcm__alsa(pContext, ma_share_mode_shared, deviceType, pDeviceID, 0, &pPCM);
20527  if (result != MA_SUCCESS) {
20528  return result;
20529  }
20530 
20531  /* We need to initialize a HW parameters object in order to know what formats are supported. */
20532  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);
20533  if (pHWParams == NULL) {
20534  ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
20535  return MA_OUT_OF_MEMORY;
20536  }
20537 
20538  resultALSA = ((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
20539  if (resultALSA < 0) {
20540  ma__free_from_callbacks(pHWParams, &pContext->allocationCallbacks);
20541  ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
20542  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));
20543  }
20544 
20545  /*
20546  Some ALSA devices can support many permutations of formats, channels and rates. We only support
20547  a fixed number of permutations which means we need to employ some strategies to ensure the best
20548  combinations are returned. An example is the "pulse" device which can do it's own data conversion
20549  in software and as a result can support any combination of format, channels and rate.
20550 
20551  We want to ensure the the first data formats are the best. We have a list of favored sample
20552  formats and sample rates, so these will be the basis of our iteration.
20553  */
20554 
20555  /* Formats. We just iterate over our standard formats and test them, making sure we reset the configuration space each iteration. */
20556  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); iFormat += 1) {
20557  ma_format format = g_maFormatPriorities[iFormat];
20558 
20559  /*
20560  For each format we need to make sure we reset the configuration space so we don't return
20561  channel counts and rates that aren't compatible with a format.
20562  */
20563  ((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
20564 
20565  /* Test the format first. If this fails it means the format is not supported and we can skip it. */
20566  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) {
20567  /* The format is supported. */
20568  unsigned int minChannels;
20569  unsigned int maxChannels;
20570 
20571  /*
20572  The configuration space needs to be restricted to this format so we can get an accurate
20573  picture of which sample rates and channel counts are support with this format.
20574  */
20575  ((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));
20576 
20577  /* Now we need to check for supported channels. */
20578  ((ma_snd_pcm_hw_params_get_channels_min_proc)pContext->alsa.snd_pcm_hw_params_get_channels_min)(pHWParams, &minChannels);
20579  ((ma_snd_pcm_hw_params_get_channels_max_proc)pContext->alsa.snd_pcm_hw_params_get_channels_max)(pHWParams, &maxChannels);
20580 
20581  if (minChannels > MA_MAX_CHANNELS) {
20582  continue; /* Too many channels. */
20583  }
20584  if (maxChannels < MA_MIN_CHANNELS) {
20585  continue; /* Not enough channels. */
20586  }
20587 
20588  /*
20589  Make sure the channel count is clamped. This is mainly intended for the max channels
20590  because some devices can report an unbound maximum.
20591  */
20592  minChannels = ma_clamp(minChannels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
20593  maxChannels = ma_clamp(maxChannels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
20594 
20595  if (minChannels == MA_MIN_CHANNELS && maxChannels == MA_MAX_CHANNELS) {
20596  /* 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. */
20597  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. */
20598  } else {
20599  /* The device only supports a specific set of channels. We need to iterate over all of them. */
20600  for (iChannel = minChannels; iChannel <= maxChannels; iChannel += 1) {
20601  /* Test the channel before applying it to the configuration space. */
20602  unsigned int channels = iChannel;
20603 
20604  /* Make sure our channel range is reset before testing again or else we'll always fail the test. */
20605  ((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
20606  ((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));
20607 
20608  if (((ma_snd_pcm_hw_params_test_channels_proc)pContext->alsa.snd_pcm_hw_params_test_channels)(pPCM, pHWParams, channels) == 0) {
20609  /* The channel count is supported. */
20610 
20611  /* The configuration space now needs to be restricted to the channel count before extracting the sample rate. */
20612  ((ma_snd_pcm_hw_params_set_channels_proc)pContext->alsa.snd_pcm_hw_params_set_channels)(pPCM, pHWParams, channels);
20613 
20614  /* Only after the configuration space has been restricted to the specific channel count should we iterate over our sample rates. */
20615  ma_context_iterate_rates_and_add_native_data_format__alsa(pContext, pPCM, pHWParams, format, channels, 0, pDeviceInfo);
20616  } else {
20617  /* The channel count is not supported. Skip. */
20618  }
20619  }
20620  }
20621  } else {
20622  /* The format is not supported. Skip. */
20623  }
20624  }
20625 
20626  ma__free_from_callbacks(pHWParams, &pContext->allocationCallbacks);
20627 
20628  ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
20629  return MA_SUCCESS;
20630 }
20631 
20632 static ma_result ma_device_uninit__alsa(ma_device* pDevice)
20633 {
20634  MA_ASSERT(pDevice != NULL);
20635 
20636  if ((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) {
20637  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
20638  close(pDevice->alsa.wakeupfdCapture);
20639  ma_free(pDevice->alsa.pPollDescriptorsCapture, &pDevice->pContext->allocationCallbacks);
20640  }
20641 
20642  if ((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) {
20643  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
20644  close(pDevice->alsa.wakeupfdPlayback);
20645  ma_free(pDevice->alsa.pPollDescriptorsPlayback, &pDevice->pContext->allocationCallbacks);
20646  }
20647 
20648  return MA_SUCCESS;
20649 }
20650 
20651 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)
20652 {
20653  ma_result result;
20654  int resultALSA;
20655  ma_snd_pcm_t* pPCM;
20656  ma_bool32 isUsingMMap;
20657  ma_snd_pcm_format_t formatALSA;
20658  ma_format internalFormat;
20659  ma_uint32 internalChannels;
20660  ma_uint32 internalSampleRate;
20661  ma_channel internalChannelMap[MA_MAX_CHANNELS];
20662  ma_uint32 internalPeriodSizeInFrames;
20663  ma_uint32 internalPeriods;
20664  int openMode;
20665  ma_snd_pcm_hw_params_t* pHWParams;
20666  ma_snd_pcm_sw_params_t* pSWParams;
20667  ma_snd_pcm_uframes_t bufferBoundary;
20668  int pollDescriptorCount;
20669  struct pollfd* pPollDescriptors;
20670  int wakeupfd;
20671 
20672  MA_ASSERT(pConfig != NULL);
20673  MA_ASSERT(deviceType != ma_device_type_duplex); /* This function should only be called for playback _or_ capture, never duplex. */
20674  MA_ASSERT(pDevice != NULL);
20675 
20676  formatALSA = ma_convert_ma_format_to_alsa_format(pDescriptor->format);
20677 
20678  openMode = 0;
20679  if (pConfig->alsa.noAutoResample) {
20680  openMode |= MA_SND_PCM_NO_AUTO_RESAMPLE;
20681  }
20682  if (pConfig->alsa.noAutoChannels) {
20683  openMode |= MA_SND_PCM_NO_AUTO_CHANNELS;
20684  }
20685  if (pConfig->alsa.noAutoFormat) {
20686  openMode |= MA_SND_PCM_NO_AUTO_FORMAT;
20687  }
20688 
20689  result = ma_context_open_pcm__alsa(pDevice->pContext, pDescriptor->shareMode, deviceType, pDescriptor->pDeviceID, openMode, &pPCM);
20690  if (result != MA_SUCCESS) {
20691  return result;
20692  }
20693 
20694 
20695  /* Hardware parameters. */
20696  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);
20697  if (pHWParams == NULL) {
20698  return MA_OUT_OF_MEMORY;
20699  }
20700 
20701  resultALSA = ((ma_snd_pcm_hw_params_any_proc)pDevice->pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams);
20702  if (resultALSA < 0) {
20703  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20704  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20705  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));
20706  }
20707 
20708  /* MMAP Mode. Try using interleaved MMAP access. If this fails, fall back to standard readi/writei. */
20709  isUsingMMap = MA_FALSE;
20710 #if 0 /* NOTE: MMAP mode temporarily disabled. */
20711  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. */
20712  if (!pConfig->alsa.noMMap && ma_device__is_async(pDevice)) {
20713  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) {
20714  pDevice->alsa.isUsingMMap = MA_TRUE;
20715  }
20716  }
20717  }
20718 #endif
20719 
20720  if (!isUsingMMap) {
20721  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);
20722  if (resultALSA < 0) {
20723  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20724  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20725  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));
20726  }
20727  }
20728 
20729  /*
20730  Most important properties first. The documentation for OSS (yes, I know this is ALSA!) recommends format, channels, then sample rate. I can't
20731  find any documentation for ALSA specifically, so I'm going to copy the recommendation for OSS.
20732  */
20733 
20734  /* Format. */
20735  {
20736  /*
20737  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
20738  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.
20739  */
20740  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) {
20741  /* We're either requesting the native format or the specified format is not supported. */
20742  size_t iFormat;
20743 
20744  formatALSA = MA_SND_PCM_FORMAT_UNKNOWN;
20745  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); ++iFormat) {
20746  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) {
20747  formatALSA = ma_convert_ma_format_to_alsa_format(g_maFormatPriorities[iFormat]);
20748  break;
20749  }
20750  }
20751 
20752  if (formatALSA == MA_SND_PCM_FORMAT_UNKNOWN) {
20753  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20754  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20755  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);
20756  }
20757  }
20758 
20759  resultALSA = ((ma_snd_pcm_hw_params_set_format_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_format)(pPCM, pHWParams, formatALSA);
20760  if (resultALSA < 0) {
20761  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20762  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20763  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));
20764  }
20765 
20766  internalFormat = ma_format_from_alsa(formatALSA);
20767  if (internalFormat == ma_format_unknown) {
20768  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20769  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20770  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] The chosen format is not supported by miniaudio.", MA_FORMAT_NOT_SUPPORTED);
20771  }
20772  }
20773 
20774  /* Channels. */
20775  {
20776  unsigned int channels = pDescriptor->channels;
20777  if (channels == 0) {
20778  channels = MA_DEFAULT_CHANNELS;
20779  }
20780 
20781  resultALSA = ((ma_snd_pcm_hw_params_set_channels_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_channels_near)(pPCM, pHWParams, &channels);
20782  if (resultALSA < 0) {
20783  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20784  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20785  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));
20786  }
20787 
20788  internalChannels = (ma_uint32)channels;
20789  }
20790 
20791  /* Sample Rate */
20792  {
20793  unsigned int sampleRate;
20794 
20795  /*
20796  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
20797  problems with some device configurations when used in conjunction with MMAP access mode. To fix this problem we need to disable
20798  resampling.
20799 
20800  To reproduce this problem, open the "plug:dmix" device, and set the sample rate to 44100. Internally, it looks like dmix uses a
20801  sample rate of 48000. The hardware parameters will get set correctly with no errors, but it looks like the 44100 -> 48000 resampling
20802  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
20803  faster rate.
20804 
20805  miniaudio has built-in support for sample rate conversion (albeit low quality at the moment), so disabling resampling should be fine
20806  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
20807  good quality until I get a chance to improve the quality of miniaudio's software sample rate conversion.
20808 
20809  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
20810  this error with. In the future, we may want to restrict the disabling of resampling to only known bad plugins.
20811  */
20812  ((ma_snd_pcm_hw_params_set_rate_resample_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_rate_resample)(pPCM, pHWParams, 0);
20813 
20814  sampleRate = pDescriptor->sampleRate;
20815  if (sampleRate == 0) {
20816  sampleRate = MA_DEFAULT_SAMPLE_RATE;
20817  }
20818 
20819  resultALSA = ((ma_snd_pcm_hw_params_set_rate_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_rate_near)(pPCM, pHWParams, &sampleRate, 0);
20820  if (resultALSA < 0) {
20821  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20822  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20823  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));
20824  }
20825 
20826  internalSampleRate = (ma_uint32)sampleRate;
20827  }
20828 
20829  /* Periods. */
20830  {
20831  ma_uint32 periods = pDescriptor->periodCount;
20832 
20833  resultALSA = ((ma_snd_pcm_hw_params_set_periods_near_proc)pDevice->pContext->alsa.snd_pcm_hw_params_set_periods_near)(pPCM, pHWParams, &periods, NULL);
20834  if (resultALSA < 0) {
20835  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20836  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20837  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));
20838  }
20839 
20840  internalPeriods = periods;
20841  }
20842 
20843  /* Buffer Size */
20844  {
20845  ma_snd_pcm_uframes_t actualBufferSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, internalSampleRate, pConfig->performanceProfile) * internalPeriods;
20846 
20847  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);
20848  if (resultALSA < 0) {
20849  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20850  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20851  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));
20852  }
20853 
20854  internalPeriodSizeInFrames = actualBufferSizeInFrames / internalPeriods;
20855  }
20856 
20857  /* Apply hardware parameters. */
20858  resultALSA = ((ma_snd_pcm_hw_params_proc)pDevice->pContext->alsa.snd_pcm_hw_params)(pPCM, pHWParams);
20859  if (resultALSA < 0) {
20860  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20861  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20862  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));
20863  }
20864 
20865  ma__free_from_callbacks(pHWParams, &pDevice->pContext->allocationCallbacks);
20866  pHWParams = NULL;
20867 
20868 
20869  /* Software parameters. */
20870  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);
20871  if (pSWParams == NULL) {
20872  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20873  return MA_OUT_OF_MEMORY;
20874  }
20875 
20876  resultALSA = ((ma_snd_pcm_sw_params_current_proc)pDevice->pContext->alsa.snd_pcm_sw_params_current)(pPCM, pSWParams);
20877  if (resultALSA < 0) {
20878  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
20879  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20880  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));
20881  }
20882 
20883  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));
20884  if (resultALSA < 0) {
20885  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
20886  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20887  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_sw_params_set_avail_min() failed.", ma_result_from_errno(-resultALSA));
20888  }
20889 
20890  resultALSA = ((ma_snd_pcm_sw_params_get_boundary_proc)pDevice->pContext->alsa.snd_pcm_sw_params_get_boundary)(pSWParams, &bufferBoundary);
20891  if (resultALSA < 0) {
20892  bufferBoundary = internalPeriodSizeInFrames * internalPeriods;
20893  }
20894 
20895  if (deviceType == ma_device_type_playback && !isUsingMMap) { /* Only playback devices in writei/readi mode need a start threshold. */
20896  /*
20897  Subtle detail here with the start threshold. When in playback-only mode (no full-duplex) we can set the start threshold to
20898  the size of a period. But for full-duplex we need to set it such that it is at least two periods.
20899  */
20900  resultALSA = ((ma_snd_pcm_sw_params_set_start_threshold_proc)pDevice->pContext->alsa.snd_pcm_sw_params_set_start_threshold)(pPCM, pSWParams, internalPeriodSizeInFrames*2);
20901  if (resultALSA < 0) {
20902  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
20903  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20904  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));
20905  }
20906 
20907  resultALSA = ((ma_snd_pcm_sw_params_set_stop_threshold_proc)pDevice->pContext->alsa.snd_pcm_sw_params_set_stop_threshold)(pPCM, pSWParams, bufferBoundary);
20908  if (resultALSA < 0) { /* Set to boundary to loop instead of stop in the event of an xrun. */
20909  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
20910  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20911  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));
20912  }
20913  }
20914 
20915  resultALSA = ((ma_snd_pcm_sw_params_proc)pDevice->pContext->alsa.snd_pcm_sw_params)(pPCM, pSWParams);
20916  if (resultALSA < 0) {
20917  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
20918  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20919  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));
20920  }
20921 
20922  ma__free_from_callbacks(pSWParams, &pDevice->pContext->allocationCallbacks);
20923  pSWParams = NULL;
20924 
20925 
20926  /* 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. */
20927  {
20928  ma_snd_pcm_chmap_t* pChmap = ((ma_snd_pcm_get_chmap_proc)pDevice->pContext->alsa.snd_pcm_get_chmap)(pPCM);
20929  if (pChmap != NULL) {
20930  ma_uint32 iChannel;
20931 
20932  /* 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(). */
20933  if (pChmap->channels >= internalChannels) {
20934  /* Drop excess channels. */
20935  for (iChannel = 0; iChannel < internalChannels; ++iChannel) {
20936  internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
20937  }
20938  } else {
20939  ma_uint32 i;
20940 
20941  /*
20942  Excess channels use defaults. Do an initial fill with defaults, overwrite the first pChmap->channels, validate to ensure there are no duplicate
20943  channels. If validation fails, fall back to defaults.
20944  */
20945  ma_bool32 isValid = MA_TRUE;
20946 
20947  /* Fill with defaults. */
20948  ma_get_standard_channel_map(ma_standard_channel_map_alsa, internalChannels, internalChannelMap);
20949 
20950  /* Overwrite first pChmap->channels channels. */
20951  for (iChannel = 0; iChannel < pChmap->channels; ++iChannel) {
20952  internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
20953  }
20954 
20955  /* Validate. */
20956  for (i = 0; i < internalChannels && isValid; ++i) {
20957  ma_uint32 j;
20958  for (j = i+1; j < internalChannels; ++j) {
20959  if (internalChannelMap[i] == internalChannelMap[j]) {
20960  isValid = MA_FALSE;
20961  break;
20962  }
20963  }
20964  }
20965 
20966  /* If our channel map is invalid, fall back to defaults. */
20967  if (!isValid) {
20968  ma_get_standard_channel_map(ma_standard_channel_map_alsa, internalChannels, internalChannelMap);
20969  }
20970  }
20971 
20972  free(pChmap);
20973  pChmap = NULL;
20974  } else {
20975  /* Could not retrieve the channel map. Fall back to a hard-coded assumption. */
20976  ma_get_standard_channel_map(ma_standard_channel_map_alsa, internalChannels, internalChannelMap);
20977  }
20978  }
20979 
20980 
20981  /*
20982  We need to retrieve the poll descriptors so we can use poll() to wait for data to become
20983  available for reading or writing. There's no well defined maximum for this so we're just going
20984  to allocate this on the heap.
20985  */
20986  pollDescriptorCount = ((ma_snd_pcm_poll_descriptors_count_proc)pDevice->pContext->alsa.snd_pcm_poll_descriptors_count)(pPCM);
20987  if (pollDescriptorCount <= 0) {
20988  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20989  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to retrieve poll descriptors count.", MA_ERROR);
20990  }
20991 
20992  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. */
20993  if (pPollDescriptors == NULL) {
20994  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
20995  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to allocate memory for poll descriptors.", MA_OUT_OF_MEMORY);
20996  }
20997 
20998  /*
20999  We need an eventfd to wakeup from poll() and avoid a deadlock in situations where the driver
21000  never returns from writei() and readi(). This has been observed with the "pulse" device.
21001  */
21002  wakeupfd = eventfd(0, 0);
21003  if (wakeupfd < 0) {
21004  ma_free(pPollDescriptors, &pDevice->pContext->allocationCallbacks);
21005  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
21006  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to create eventfd for poll wakeup.", ma_result_from_errno(errno));
21007  }
21008 
21009  /* We'll place the wakeup fd at the start of the buffer. */
21010  pPollDescriptors[0].fd = wakeupfd;
21011  pPollDescriptors[0].events = POLLIN; /* We only care about waiting to read from the wakeup file descriptor. */
21012  pPollDescriptors[0].revents = 0;
21013 
21014  /* We can now extract the PCM poll descriptors which we place after the wakeup descriptor. */
21015  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. */
21016  if (pollDescriptorCount <= 0) {
21017  close(wakeupfd);
21018  ma_free(pPollDescriptors, &pDevice->pContext->allocationCallbacks);
21019  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
21020  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to retrieve poll descriptors.", MA_ERROR);
21021  }
21022 
21023  if (deviceType == ma_device_type_capture) {
21024  pDevice->alsa.pollDescriptorCountCapture = pollDescriptorCount;
21025  pDevice->alsa.pPollDescriptorsCapture = pPollDescriptors;
21026  pDevice->alsa.wakeupfdCapture = wakeupfd;
21027  } else {
21028  pDevice->alsa.pollDescriptorCountPlayback = pollDescriptorCount;
21029  pDevice->alsa.pPollDescriptorsPlayback = pPollDescriptors;
21030  pDevice->alsa.wakeupfdPlayback = wakeupfd;
21031  }
21032 
21033 
21034  /* We're done. Prepare the device. */
21035  resultALSA = ((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)(pPCM);
21036  if (resultALSA < 0) {
21037  close(wakeupfd);
21038  ma_free(pPollDescriptors, &pDevice->pContext->allocationCallbacks);
21039  ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
21040  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to prepare device.", ma_result_from_errno(-resultALSA));
21041  }
21042 
21043 
21044  if (deviceType == ma_device_type_capture) {
21045  pDevice->alsa.pPCMCapture = (ma_ptr)pPCM;
21046  pDevice->alsa.isUsingMMapCapture = isUsingMMap;
21047  } else {
21048  pDevice->alsa.pPCMPlayback = (ma_ptr)pPCM;
21049  pDevice->alsa.isUsingMMapPlayback = isUsingMMap;
21050  }
21051 
21052  pDescriptor->format = internalFormat;
21053  pDescriptor->channels = internalChannels;
21054  pDescriptor->sampleRate = internalSampleRate;
21055  ma_channel_map_copy(pDescriptor->channelMap, internalChannelMap, ma_min(internalChannels, MA_MAX_CHANNELS));
21056  pDescriptor->periodSizeInFrames = internalPeriodSizeInFrames;
21057  pDescriptor->periodCount = internalPeriods;
21058 
21059  return MA_SUCCESS;
21060 }
21061 
21062 static ma_result ma_device_init__alsa(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
21063 {
21064  MA_ASSERT(pDevice != NULL);
21065 
21066  MA_ZERO_OBJECT(&pDevice->alsa);
21067 
21068  if (pConfig->deviceType == ma_device_type_loopback) {
21070  }
21071 
21072  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
21073  ma_result result = ma_device_init_by_type__alsa(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
21074  if (result != MA_SUCCESS) {
21075  return result;
21076  }
21077  }
21078 
21079  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
21080  ma_result result = ma_device_init_by_type__alsa(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
21081  if (result != MA_SUCCESS) {
21082  return result;
21083  }
21084  }
21085 
21086  return MA_SUCCESS;
21087 }
21088 
21089 static ma_result ma_device_start__alsa(ma_device* pDevice)
21090 {
21091  int resultALSA;
21092 
21093  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
21094  resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
21095  if (resultALSA < 0) {
21096  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start capture device.", ma_result_from_errno(-resultALSA));
21097  }
21098  }
21099 
21100  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
21101  /* Don't need to do anything for playback because it'll be started automatically when enough data has been written. */
21102  }
21103 
21104  return MA_SUCCESS;
21105 }
21106 
21107 static ma_result ma_device_stop__alsa(ma_device* pDevice)
21108 {
21109  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
21110  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device... ");
21111  ((ma_snd_pcm_drop_proc)pDevice->pContext->alsa.snd_pcm_drop)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
21112  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
21113 
21114  /* We need to prepare the device again, otherwise we won't be able to restart the device. */
21115  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device... ");
21116  if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
21117  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Failed\n");
21118  } else {
21119  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
21120  }
21121  }
21122 
21123  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
21124  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping playback device... ");
21125  ((ma_snd_pcm_drop_proc)pDevice->pContext->alsa.snd_pcm_drop)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
21126  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
21127 
21128  /* We need to prepare the device again, otherwise we won't be able to restart the device. */
21129  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing playback device... ");
21130  if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) < 0) {
21131  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Failed\n");
21132  } else {
21133  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
21134  }
21135  }
21136 
21137  return MA_SUCCESS;
21138 }
21139 
21140 static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, struct pollfd* pPollDescriptors, int pollDescriptorCount, short requiredEvent)
21141 {
21142  for (;;) {
21143  unsigned short revents;
21144  int resultALSA;
21145  int resultPoll = poll(pPollDescriptors, pollDescriptorCount, -1);
21146  if (resultPoll < 0) {
21147  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] poll() failed.", ma_result_from_errno(errno));
21148  }
21149 
21150  /*
21151  Before checking the ALSA poll descriptor flag we need to check if the wakeup descriptor
21152  has had it's POLLIN flag set. If so, we need to actually read the data and then exit
21153  function. The wakeup descriptor will be the first item in the descriptors buffer.
21154  */
21155  if ((pPollDescriptors[0].revents & POLLIN) != 0) {
21156  ma_uint64 t;
21157  read(pPollDescriptors[0].fd, &t, sizeof(t)); /* <-- Important that we read here so that the next write() does not block. */
21158 
21159  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] POLLIN set for wakeupfd\n");
21160 
21161  return MA_DEVICE_NOT_STARTED;
21162  }
21163 
21164  /*
21165  Getting here means that some data should be able to be read. We need to use ALSA to
21166  translate the revents flags for us.
21167  */
21168  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. */
21169  if (resultALSA < 0) {
21170  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_poll_descriptors_revents() failed.", ma_result_from_errno(-resultALSA));
21171  }
21172 
21173  if ((revents & POLLERR) != 0) {
21174  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] POLLERR detected.", ma_result_from_errno(errno));
21175  }
21176 
21177  if ((revents & requiredEvent) == requiredEvent) {
21178  break; /* We're done. Data available for reading or writing. */
21179  }
21180  }
21181 
21182  return MA_SUCCESS;
21183 }
21184 
21185 static ma_result ma_device_wait_read__alsa(ma_device* pDevice)
21186 {
21187  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. */
21188 }
21189 
21190 static ma_result ma_device_wait_write__alsa(ma_device* pDevice)
21191 {
21192  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. */
21193 }
21194 
21195 static ma_result ma_device_read__alsa(ma_device* pDevice, void* pFramesOut, ma_uint32 frameCount, ma_uint32* pFramesRead)
21196 {
21197  ma_snd_pcm_sframes_t resultALSA;
21198 
21199  MA_ASSERT(pDevice != NULL);
21200  MA_ASSERT(pFramesOut != NULL);
21201 
21202  if (pFramesRead != NULL) {
21203  *pFramesRead = 0;
21204  }
21205 
21206  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
21207  ma_result result;
21208 
21209  /* 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. */
21210  result = ma_device_wait_read__alsa(pDevice);
21211  if (result != MA_SUCCESS) {
21212  return result;
21213  }
21214 
21215  /* Getting here means we should have data available. */
21216  resultALSA = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, pFramesOut, frameCount);
21217  if (resultALSA >= 0) {
21218  break; /* Success. */
21219  } else {
21220  if (resultALSA == -EAGAIN) {
21221  /*ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EGAIN (read)\n");*/
21222  continue; /* Try again. */
21223  } else if (resultALSA == -EPIPE) {
21224  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EPIPE (read)\n");
21225 
21226  /* Overrun. Recover and try again. If this fails we need to return an error. */
21227  resultALSA = ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, resultALSA, MA_TRUE);
21228  if (resultALSA < 0) {
21229  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to recover device after overrun.", ma_result_from_errno((int)-resultALSA));
21230  }
21231 
21232  resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
21233  if (resultALSA < 0) {
21234  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start device after underrun.", ma_result_from_errno((int)-resultALSA));
21235  }
21236 
21237  continue; /* Try reading again. */
21238  }
21239  }
21240  }
21241 
21242  if (pFramesRead != NULL) {
21243  *pFramesRead = resultALSA;
21244  }
21245 
21246  return MA_SUCCESS;
21247 }
21248 
21249 static ma_result ma_device_write__alsa(ma_device* pDevice, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
21250 {
21251  ma_snd_pcm_sframes_t resultALSA;
21252 
21253  MA_ASSERT(pDevice != NULL);
21254  MA_ASSERT(pFrames != NULL);
21255 
21256  if (pFramesWritten != NULL) {
21257  *pFramesWritten = 0;
21258  }
21259 
21260  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
21261  ma_result result;
21262 
21263  /* 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. */
21264  result = ma_device_wait_write__alsa(pDevice);
21265  if (result != MA_SUCCESS) {
21266  return result;
21267  }
21268 
21269  resultALSA = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, pFrames, frameCount);
21270  if (resultALSA >= 0) {
21271  break; /* Success. */
21272  } else {
21273  if (resultALSA == -EAGAIN) {
21274  /*ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EGAIN (write)\n");*/
21275  continue; /* Try again. */
21276  } else if (resultALSA == -EPIPE) {
21277  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "TRACE: EPIPE (write)\n");
21278 
21279  /* Underrun. Recover and try again. If this fails we need to return an error. */
21280  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). */
21281  if (resultALSA < 0) {
21282  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to recover device after underrun.", ma_result_from_errno((int)-resultALSA));
21283  }
21284 
21285  /*
21286  In my testing I have had a situation where writei() does not automatically restart the device even though I've set it
21287  up as such in the software parameters. What will happen is writei() will block indefinitely even though the number of
21288  frames is well beyond the auto-start threshold. To work around this I've needed to add an explicit start here. Not sure
21289  if this is me just being stupid and not recovering the device properly, but this definitely feels like something isn't
21290  quite right here.
21291  */
21292  resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
21293  if (resultALSA < 0) {
21294  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start device after underrun.", ma_result_from_errno((int)-resultALSA));
21295  }
21296 
21297  continue; /* Try writing again. */
21298  }
21299  }
21300  }
21301 
21302  if (pFramesWritten != NULL) {
21303  *pFramesWritten = resultALSA;
21304  }
21305 
21306  return MA_SUCCESS;
21307 }
21308 
21309 static ma_result ma_device_data_loop_wakeup__alsa(ma_device* pDevice)
21310 {
21311  ma_uint64 t = 1;
21312 
21313  MA_ASSERT(pDevice != NULL);
21314 
21315  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Waking up... ");
21316 
21317  /* Write to an eventfd to trigger a wakeup from poll() and abort any reading or writing. */
21318  if (pDevice->alsa.pPollDescriptorsCapture != NULL) {
21319  write(pDevice->alsa.wakeupfdCapture, &t, sizeof(t));
21320  }
21321  if (pDevice->alsa.pPollDescriptorsPlayback != NULL) {
21322  write(pDevice->alsa.wakeupfdPlayback, &t, sizeof(t));
21323  }
21324 
21325  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Done\n");
21326 
21327  return MA_SUCCESS;
21328 }
21329 
21330 static ma_result ma_context_uninit__alsa(ma_context* pContext)
21331 {
21332  MA_ASSERT(pContext != NULL);
21333  MA_ASSERT(pContext->backend == ma_backend_alsa);
21334 
21335  /* Clean up memory for memory leak checkers. */
21336  ((ma_snd_config_update_free_global_proc)pContext->alsa.snd_config_update_free_global)();
21337 
21338 #ifndef MA_NO_RUNTIME_LINKING
21339  ma_dlclose(pContext, pContext->alsa.asoundSO);
21340 #endif
21341 
21342  ma_mutex_uninit(&pContext->alsa.internalDeviceEnumLock);
21343 
21344  return MA_SUCCESS;
21345 }
21346 
21347 static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
21348 {
21349 #ifndef MA_NO_RUNTIME_LINKING
21350  const char* libasoundNames[] = {
21351  "libasound.so.2",
21352  "libasound.so"
21353  };
21354  size_t i;
21355 
21356  for (i = 0; i < ma_countof(libasoundNames); ++i) {
21357  pContext->alsa.asoundSO = ma_dlopen(pContext, libasoundNames[i]);
21358  if (pContext->alsa.asoundSO != NULL) {
21359  break;
21360  }
21361  }
21362 
21363  if (pContext->alsa.asoundSO == NULL) {
21364  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to open shared object.\n");
21365  return MA_NO_BACKEND;
21366  }
21367 
21368  pContext->alsa.snd_pcm_open = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_open");
21369  pContext->alsa.snd_pcm_close = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_close");
21370  pContext->alsa.snd_pcm_hw_params_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_sizeof");
21371  pContext->alsa.snd_pcm_hw_params_any = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_any");
21372  pContext->alsa.snd_pcm_hw_params_set_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_format");
21373  pContext->alsa.snd_pcm_hw_params_set_format_first = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_format_first");
21374  pContext->alsa.snd_pcm_hw_params_get_format_mask = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_format_mask");
21375  pContext->alsa.snd_pcm_hw_params_set_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels");
21376  pContext->alsa.snd_pcm_hw_params_set_channels_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels_near");
21377  pContext->alsa.snd_pcm_hw_params_set_channels_minmax = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels_minmax");
21378  pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate_resample");
21379  pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate");
21380  pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate_near");
21381  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");
21382  pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_periods_near");
21383  pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_access");
21384  pContext->alsa.snd_pcm_hw_params_get_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_format");
21385  pContext->alsa.snd_pcm_hw_params_get_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels");
21386  pContext->alsa.snd_pcm_hw_params_get_channels_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels_min");
21387  pContext->alsa.snd_pcm_hw_params_get_channels_max = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels_max");
21388  pContext->alsa.snd_pcm_hw_params_get_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate");
21389  pContext->alsa.snd_pcm_hw_params_get_rate_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate_min");
21390  pContext->alsa.snd_pcm_hw_params_get_rate_max = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate_max");
21391  pContext->alsa.snd_pcm_hw_params_get_buffer_size = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_buffer_size");
21392  pContext->alsa.snd_pcm_hw_params_get_periods = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_periods");
21393  pContext->alsa.snd_pcm_hw_params_get_access = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_access");
21394  pContext->alsa.snd_pcm_hw_params_test_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_format");
21395  pContext->alsa.snd_pcm_hw_params_test_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_channels");
21396  pContext->alsa.snd_pcm_hw_params_test_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_rate");
21397  pContext->alsa.snd_pcm_hw_params = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params");
21398  pContext->alsa.snd_pcm_sw_params_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_sizeof");
21399  pContext->alsa.snd_pcm_sw_params_current = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_current");
21400  pContext->alsa.snd_pcm_sw_params_get_boundary = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_get_boundary");
21401  pContext->alsa.snd_pcm_sw_params_set_avail_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_avail_min");
21402  pContext->alsa.snd_pcm_sw_params_set_start_threshold = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_start_threshold");
21403  pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_stop_threshold");
21404  pContext->alsa.snd_pcm_sw_params = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params");
21405  pContext->alsa.snd_pcm_format_mask_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_format_mask_sizeof");
21406  pContext->alsa.snd_pcm_format_mask_test = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_format_mask_test");
21407  pContext->alsa.snd_pcm_get_chmap = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_get_chmap");
21408  pContext->alsa.snd_pcm_state = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_state");
21409  pContext->alsa.snd_pcm_prepare = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_prepare");
21410  pContext->alsa.snd_pcm_start = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_start");
21411  pContext->alsa.snd_pcm_drop = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_drop");
21412  pContext->alsa.snd_pcm_drain = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_drain");
21413  pContext->alsa.snd_pcm_reset = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_reset");
21414  pContext->alsa.snd_device_name_hint = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_device_name_hint");
21415  pContext->alsa.snd_device_name_get_hint = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_device_name_get_hint");
21416  pContext->alsa.snd_card_get_index = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_card_get_index");
21417  pContext->alsa.snd_device_name_free_hint = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_device_name_free_hint");
21418  pContext->alsa.snd_pcm_mmap_begin = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_mmap_begin");
21419  pContext->alsa.snd_pcm_mmap_commit = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_mmap_commit");
21420  pContext->alsa.snd_pcm_recover = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_recover");
21421  pContext->alsa.snd_pcm_readi = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_readi");
21422  pContext->alsa.snd_pcm_writei = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_writei");
21423  pContext->alsa.snd_pcm_avail = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_avail");
21424  pContext->alsa.snd_pcm_avail_update = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_avail_update");
21425  pContext->alsa.snd_pcm_wait = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_wait");
21426  pContext->alsa.snd_pcm_nonblock = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_nonblock");
21427  pContext->alsa.snd_pcm_info = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_info");
21428  pContext->alsa.snd_pcm_info_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_info_sizeof");
21429  pContext->alsa.snd_pcm_info_get_name = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_info_get_name");
21430  pContext->alsa.snd_pcm_poll_descriptors = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_poll_descriptors");
21431  pContext->alsa.snd_pcm_poll_descriptors_count = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_poll_descriptors_count");
21432  pContext->alsa.snd_pcm_poll_descriptors_revents = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_poll_descriptors_revents");
21433  pContext->alsa.snd_config_update_free_global = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_config_update_free_global");
21434 #else
21435  /* The system below is just for type safety. */
21436  ma_snd_pcm_open_proc _snd_pcm_open = snd_pcm_open;
21437  ma_snd_pcm_close_proc _snd_pcm_close = snd_pcm_close;
21438  ma_snd_pcm_hw_params_sizeof_proc _snd_pcm_hw_params_sizeof = snd_pcm_hw_params_sizeof;
21439  ma_snd_pcm_hw_params_any_proc _snd_pcm_hw_params_any = snd_pcm_hw_params_any;
21440  ma_snd_pcm_hw_params_set_format_proc _snd_pcm_hw_params_set_format = snd_pcm_hw_params_set_format;
21441  ma_snd_pcm_hw_params_set_format_first_proc _snd_pcm_hw_params_set_format_first = snd_pcm_hw_params_set_format_first;
21442  ma_snd_pcm_hw_params_get_format_mask_proc _snd_pcm_hw_params_get_format_mask = snd_pcm_hw_params_get_format_mask;
21443  ma_snd_pcm_hw_params_set_channels_proc _snd_pcm_hw_params_set_channels = snd_pcm_hw_params_set_channels;
21444  ma_snd_pcm_hw_params_set_channels_near_proc _snd_pcm_hw_params_set_channels_near = snd_pcm_hw_params_set_channels_near;
21445  ma_snd_pcm_hw_params_set_rate_resample_proc _snd_pcm_hw_params_set_rate_resample = snd_pcm_hw_params_set_rate_resample;
21446  ma_snd_pcm_hw_params_set_rate_near _snd_pcm_hw_params_set_rate = snd_pcm_hw_params_set_rate;
21447  ma_snd_pcm_hw_params_set_rate_near_proc _snd_pcm_hw_params_set_rate_near = snd_pcm_hw_params_set_rate_near;
21448  ma_snd_pcm_hw_params_set_rate_minmax_proc _snd_pcm_hw_params_set_rate_minmax = snd_pcm_hw_params_set_rate_minmax;
21449  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;
21450  ma_snd_pcm_hw_params_set_periods_near_proc _snd_pcm_hw_params_set_periods_near = snd_pcm_hw_params_set_periods_near;
21451  ma_snd_pcm_hw_params_set_access_proc _snd_pcm_hw_params_set_access = snd_pcm_hw_params_set_access;
21452  ma_snd_pcm_hw_params_get_format_proc _snd_pcm_hw_params_get_format = snd_pcm_hw_params_get_format;
21453  ma_snd_pcm_hw_params_get_channels_proc _snd_pcm_hw_params_get_channels = snd_pcm_hw_params_get_channels;
21454  ma_snd_pcm_hw_params_get_channels_min_proc _snd_pcm_hw_params_get_channels_min = snd_pcm_hw_params_get_channels_min;
21455  ma_snd_pcm_hw_params_get_channels_max_proc _snd_pcm_hw_params_get_channels_max = snd_pcm_hw_params_get_channels_max;
21456  ma_snd_pcm_hw_params_get_rate_proc _snd_pcm_hw_params_get_rate = snd_pcm_hw_params_get_rate;
21457  ma_snd_pcm_hw_params_get_rate_min_proc _snd_pcm_hw_params_get_rate_min = snd_pcm_hw_params_get_rate_min;
21458  ma_snd_pcm_hw_params_get_rate_max_proc _snd_pcm_hw_params_get_rate_max = snd_pcm_hw_params_get_rate_max;
21459  ma_snd_pcm_hw_params_get_buffer_size_proc _snd_pcm_hw_params_get_buffer_size = snd_pcm_hw_params_get_buffer_size;
21460  ma_snd_pcm_hw_params_get_periods_proc _snd_pcm_hw_params_get_periods = snd_pcm_hw_params_get_periods;
21461  ma_snd_pcm_hw_params_get_access_proc _snd_pcm_hw_params_get_access = snd_pcm_hw_params_get_access;
21462  ma_snd_pcm_hw_params_test_format_proc _snd_pcm_hw_params_test_format = snd_pcm_hw_params_test_format;
21463  ma_snd_pcm_hw_params_test_channels_proc _snd_pcm_hw_params_test_channels = snd_pcm_hw_params_test_channels;
21464  ma_snd_pcm_hw_params_test_rate_proc _snd_pcm_hw_params_test_rate = snd_pcm_hw_params_test_rate;
21465  ma_snd_pcm_hw_params_proc _snd_pcm_hw_params = snd_pcm_hw_params;
21466  ma_snd_pcm_sw_params_sizeof_proc _snd_pcm_sw_params_sizeof = snd_pcm_sw_params_sizeof;
21467  ma_snd_pcm_sw_params_current_proc _snd_pcm_sw_params_current = snd_pcm_sw_params_current;
21468  ma_snd_pcm_sw_params_get_boundary_proc _snd_pcm_sw_params_get_boundary = snd_pcm_sw_params_get_boundary;
21469  ma_snd_pcm_sw_params_set_avail_min_proc _snd_pcm_sw_params_set_avail_min = snd_pcm_sw_params_set_avail_min;
21470  ma_snd_pcm_sw_params_set_start_threshold_proc _snd_pcm_sw_params_set_start_threshold = snd_pcm_sw_params_set_start_threshold;
21471  ma_snd_pcm_sw_params_set_stop_threshold_proc _snd_pcm_sw_params_set_stop_threshold = snd_pcm_sw_params_set_stop_threshold;
21472  ma_snd_pcm_sw_params_proc _snd_pcm_sw_params = snd_pcm_sw_params;
21473  ma_snd_pcm_format_mask_sizeof_proc _snd_pcm_format_mask_sizeof = snd_pcm_format_mask_sizeof;
21474  ma_snd_pcm_format_mask_test_proc _snd_pcm_format_mask_test = snd_pcm_format_mask_test;
21475  ma_snd_pcm_get_chmap_proc _snd_pcm_get_chmap = snd_pcm_get_chmap;
21476  ma_snd_pcm_state_proc _snd_pcm_state = snd_pcm_state;
21477  ma_snd_pcm_prepare_proc _snd_pcm_prepare = snd_pcm_prepare;
21478  ma_snd_pcm_start_proc _snd_pcm_start = snd_pcm_start;
21479  ma_snd_pcm_drop_proc _snd_pcm_drop = snd_pcm_drop;
21480  ma_snd_pcm_drain_proc _snd_pcm_drain = snd_pcm_drain;
21481  ma_snd_pcm_reset_proc _snd_pcm_reset = snd_pcm_reset;
21482  ma_snd_device_name_hint_proc _snd_device_name_hint = snd_device_name_hint;
21483  ma_snd_device_name_get_hint_proc _snd_device_name_get_hint = snd_device_name_get_hint;
21484  ma_snd_card_get_index_proc _snd_card_get_index = snd_card_get_index;
21485  ma_snd_device_name_free_hint_proc _snd_device_name_free_hint = snd_device_name_free_hint;
21486  ma_snd_pcm_mmap_begin_proc _snd_pcm_mmap_begin = snd_pcm_mmap_begin;
21487  ma_snd_pcm_mmap_commit_proc _snd_pcm_mmap_commit = snd_pcm_mmap_commit;
21488  ma_snd_pcm_recover_proc _snd_pcm_recover = snd_pcm_recover;
21489  ma_snd_pcm_readi_proc _snd_pcm_readi = snd_pcm_readi;
21490  ma_snd_pcm_writei_proc _snd_pcm_writei = snd_pcm_writei;
21491  ma_snd_pcm_avail_proc _snd_pcm_avail = snd_pcm_avail;
21492  ma_snd_pcm_avail_update_proc _snd_pcm_avail_update = snd_pcm_avail_update;
21493  ma_snd_pcm_wait_proc _snd_pcm_wait = snd_pcm_wait;
21494  ma_snd_pcm_nonblock_proc _snd_pcm_nonblock = snd_pcm_nonblock;
21495  ma_snd_pcm_info_proc _snd_pcm_info = snd_pcm_info;
21496  ma_snd_pcm_info_sizeof_proc _snd_pcm_info_sizeof = snd_pcm_info_sizeof;
21497  ma_snd_pcm_info_get_name_proc _snd_pcm_info_get_name = snd_pcm_info_get_name;
21498  ma_snd_pcm_poll_descriptors _snd_pcm_poll_descriptors = snd_pcm_poll_descriptors;
21499  ma_snd_pcm_poll_descriptors_count _snd_pcm_poll_descriptors_count = snd_pcm_poll_descriptors_count;
21500  ma_snd_pcm_poll_descriptors_revents _snd_pcm_poll_descriptors_revents = snd_pcm_poll_descriptors_revents;
21501  ma_snd_config_update_free_global_proc _snd_config_update_free_global = snd_config_update_free_global;
21502 
21503  pContext->alsa.snd_pcm_open = (ma_proc)_snd_pcm_open;
21504  pContext->alsa.snd_pcm_close = (ma_proc)_snd_pcm_close;
21505  pContext->alsa.snd_pcm_hw_params_sizeof = (ma_proc)_snd_pcm_hw_params_sizeof;
21506  pContext->alsa.snd_pcm_hw_params_any = (ma_proc)_snd_pcm_hw_params_any;
21507  pContext->alsa.snd_pcm_hw_params_set_format = (ma_proc)_snd_pcm_hw_params_set_format;
21508  pContext->alsa.snd_pcm_hw_params_set_format_first = (ma_proc)_snd_pcm_hw_params_set_format_first;
21509  pContext->alsa.snd_pcm_hw_params_get_format_mask = (ma_proc)_snd_pcm_hw_params_get_format_mask;
21510  pContext->alsa.snd_pcm_hw_params_set_channels = (ma_proc)_snd_pcm_hw_params_set_channels;
21511  pContext->alsa.snd_pcm_hw_params_set_channels_near = (ma_proc)_snd_pcm_hw_params_set_channels_near;
21512  pContext->alsa.snd_pcm_hw_params_set_channels_minmax = (ma_proc)_snd_pcm_hw_params_set_channels_minmax;
21513  pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)_snd_pcm_hw_params_set_rate_resample;
21514  pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)_snd_pcm_hw_params_set_rate;
21515  pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)_snd_pcm_hw_params_set_rate_near;
21516  pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (ma_proc)_snd_pcm_hw_params_set_buffer_size_near;
21517  pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)_snd_pcm_hw_params_set_periods_near;
21518  pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)_snd_pcm_hw_params_set_access;
21519  pContext->alsa.snd_pcm_hw_params_get_format = (ma_proc)_snd_pcm_hw_params_get_format;
21520  pContext->alsa.snd_pcm_hw_params_get_channels = (ma_proc)_snd_pcm_hw_params_get_channels;
21521  pContext->alsa.snd_pcm_hw_params_get_channels_min = (ma_proc)_snd_pcm_hw_params_get_channels_min;
21522  pContext->alsa.snd_pcm_hw_params_get_channels_max = (ma_proc)_snd_pcm_hw_params_get_channels_max;
21523  pContext->alsa.snd_pcm_hw_params_get_rate = (ma_proc)_snd_pcm_hw_params_get_rate;
21524  pContext->alsa.snd_pcm_hw_params_get_rate_min = (ma_proc)_snd_pcm_hw_params_get_rate_min;
21525  pContext->alsa.snd_pcm_hw_params_get_rate_max = (ma_proc)_snd_pcm_hw_params_get_rate_max;
21526  pContext->alsa.snd_pcm_hw_params_get_buffer_size = (ma_proc)_snd_pcm_hw_params_get_buffer_size;
21527  pContext->alsa.snd_pcm_hw_params_get_periods = (ma_proc)_snd_pcm_hw_params_get_periods;
21528  pContext->alsa.snd_pcm_hw_params_get_access = (ma_proc)_snd_pcm_hw_params_get_access;
21529  pContext->alsa.snd_pcm_hw_params_test_format = (ma_proc)_snd_pcm_hw_params_test_format;
21530  pContext->alsa.snd_pcm_hw_params_test_channels = (ma_proc)_snd_pcm_hw_params_test_channels;
21531  pContext->alsa.snd_pcm_hw_params_test_rate = (ma_proc)_snd_pcm_hw_params_test_rate;
21532  pContext->alsa.snd_pcm_hw_params = (ma_proc)_snd_pcm_hw_params;
21533  pContext->alsa.snd_pcm_sw_params_sizeof = (ma_proc)_snd_pcm_sw_params_sizeof;
21534  pContext->alsa.snd_pcm_sw_params_current = (ma_proc)_snd_pcm_sw_params_current;
21535  pContext->alsa.snd_pcm_sw_params_get_boundary = (ma_proc)_snd_pcm_sw_params_get_boundary;
21536  pContext->alsa.snd_pcm_sw_params_set_avail_min = (ma_proc)_snd_pcm_sw_params_set_avail_min;
21537  pContext->alsa.snd_pcm_sw_params_set_start_threshold = (ma_proc)_snd_pcm_sw_params_set_start_threshold;
21538  pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (ma_proc)_snd_pcm_sw_params_set_stop_threshold;
21539  pContext->alsa.snd_pcm_sw_params = (ma_proc)_snd_pcm_sw_params;
21540  pContext->alsa.snd_pcm_format_mask_sizeof = (ma_proc)_snd_pcm_format_mask_sizeof;
21541  pContext->alsa.snd_pcm_format_mask_test = (ma_proc)_snd_pcm_format_mask_test;
21542  pContext->alsa.snd_pcm_get_chmap = (ma_proc)_snd_pcm_get_chmap;
21543  pContext->alsa.snd_pcm_state = (ma_proc)_snd_pcm_state;
21544  pContext->alsa.snd_pcm_prepare = (ma_proc)_snd_pcm_prepare;
21545  pContext->alsa.snd_pcm_start = (ma_proc)_snd_pcm_start;
21546  pContext->alsa.snd_pcm_drop = (ma_proc)_snd_pcm_drop;
21547  pContext->alsa.snd_pcm_drain = (ma_proc)_snd_pcm_drain;
21548  pContext->alsa.snd_pcm_reset = (ma_proc)_snd_pcm_reset;
21549  pContext->alsa.snd_device_name_hint = (ma_proc)_snd_device_name_hint;
21550  pContext->alsa.snd_device_name_get_hint = (ma_proc)_snd_device_name_get_hint;
21551  pContext->alsa.snd_card_get_index = (ma_proc)_snd_card_get_index;
21552  pContext->alsa.snd_device_name_free_hint = (ma_proc)_snd_device_name_free_hint;
21553  pContext->alsa.snd_pcm_mmap_begin = (ma_proc)_snd_pcm_mmap_begin;
21554  pContext->alsa.snd_pcm_mmap_commit = (ma_proc)_snd_pcm_mmap_commit;
21555  pContext->alsa.snd_pcm_recover = (ma_proc)_snd_pcm_recover;
21556  pContext->alsa.snd_pcm_readi = (ma_proc)_snd_pcm_readi;
21557  pContext->alsa.snd_pcm_writei = (ma_proc)_snd_pcm_writei;
21558  pContext->alsa.snd_pcm_avail = (ma_proc)_snd_pcm_avail;
21559  pContext->alsa.snd_pcm_avail_update = (ma_proc)_snd_pcm_avail_update;
21560  pContext->alsa.snd_pcm_wait = (ma_proc)_snd_pcm_wait;
21561  pContext->alsa.snd_pcm_nonblock = (ma_proc)_snd_pcm_nonblock;
21562  pContext->alsa.snd_pcm_info = (ma_proc)_snd_pcm_info;
21563  pContext->alsa.snd_pcm_info_sizeof = (ma_proc)_snd_pcm_info_sizeof;
21564  pContext->alsa.snd_pcm_info_get_name = (ma_proc)_snd_pcm_info_get_name;
21565  pContext->alsa.snd_pcm_poll_descriptors = (ma_proc)_snd_pcm_poll_descriptors;
21566  pContext->alsa.snd_pcm_poll_descriptors_count = (ma_proc)_snd_pcm_poll_descriptors_count;
21567  pContext->alsa.snd_pcm_poll_descriptors_revents = (ma_proc)_snd_pcm_poll_descriptors_revents;
21568  pContext->alsa.snd_config_update_free_global = (ma_proc)_snd_config_update_free_global;
21569 #endif
21570 
21571  pContext->alsa.useVerboseDeviceEnumeration = pConfig->alsa.useVerboseDeviceEnumeration;
21572 
21573  if (ma_mutex_init(&pContext->alsa.internalDeviceEnumLock) != MA_SUCCESS) {
21574  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[ALSA] WARNING: Failed to initialize mutex for internal device enumeration.", MA_ERROR);
21575  }
21576 
21577  pCallbacks->onContextInit = ma_context_init__alsa;
21578  pCallbacks->onContextUninit = ma_context_uninit__alsa;
21579  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__alsa;
21580  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__alsa;
21581  pCallbacks->onDeviceInit = ma_device_init__alsa;
21582  pCallbacks->onDeviceUninit = ma_device_uninit__alsa;
21583  pCallbacks->onDeviceStart = ma_device_start__alsa;
21584  pCallbacks->onDeviceStop = ma_device_stop__alsa;
21585  pCallbacks->onDeviceRead = ma_device_read__alsa;
21586  pCallbacks->onDeviceWrite = ma_device_write__alsa;
21587  pCallbacks->onDeviceDataLoop = NULL;
21588  pCallbacks->onDeviceDataLoopWakeup = ma_device_data_loop_wakeup__alsa;
21589 
21590  return MA_SUCCESS;
21591 }
21592 #endif /* ALSA */
21593 
21594 
21595 
21596 /******************************************************************************
21597 
21598 PulseAudio Backend
21599 
21600 ******************************************************************************/
21601 #ifdef MA_HAS_PULSEAUDIO
21602 /*
21603 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
21604 in the PulseAudio backend. I apologize if this gets a bit ranty for your liking - you might want to skip this discussion.
21605 
21606 PulseAudio has something they call the "Simple API", which unfortunately isn't suitable for miniaudio. I've not seen anywhere where it
21607 allows you to enumerate over devices, nor does it seem to support the ability to stop and start streams. Looking at the documentation, it
21608 appears as though the stream is constantly running and you prevent sound from being emitted or captured by simply not calling the read or
21609 write functions. This is not a professional solution as it would be much better to *actually* stop the underlying stream. Perhaps the
21610 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
21611 when you want to have multiple streams to a single context. For these reasons, miniaudio is not using the simple API.
21612 
21613 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
21614 get fun, and I don't mean that in a good way...
21615 
21616 The problems start with the very name of the API - "asynchronous". Yes, this is an asynchronous oriented API which means your commands
21617 don't immediately take effect. You instead need to issue your commands, and then wait for them to complete. The waiting mechanism is
21618 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
21619 all of PulseAudio's problems stem from.
21620 
21621 When you first initialize PulseAudio you need an object referred to as "main loop". You can implement this yourself by defining your own
21622 vtable, but it's much easier to just use one of the built-in main loop implementations. There's two generic implementations called
21623 pa_mainloop and pa_threaded_mainloop, and another implementation specific to GLib called pa_glib_mainloop. We're using pa_threaded_mainloop
21624 because it simplifies management of the worker thread. The idea of the main loop object is pretty self explanatory - you're supposed to use
21625 it to implement a worker thread which runs in a loop. The main loop is where operations are actually executed.
21626 
21627 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
21628 to the vtable with `pa_threaded_mainloop_get_api()` (the main loop vtable is called `pa_mainloop_api`). Again, you can bypass the threaded
21629 main loop object entirely and just implement `pa_mainloop_api` directly, but there's no need for it unless you're doing something extremely
21630 specialized such as if you want to integrate it into your application's existing main loop infrastructure.
21631 
21632 (EDIT 2021-01-26: miniaudio is no longer using `pa_threaded_mainloop` due to this issue: https://github.com/mackron/miniaudio/issues/262.
21633 It is now using `pa_mainloop` which turns out to be a simpler solution anyway. The rest of this rant still applies, however.)
21634 
21635 Once you have your main loop vtable (the `pa_mainloop_api` object) you can create the PulseAudio context. This is very similar to
21636 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
21637 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
21638 is done with `pa_context_new()`, it's not actually connected to anything. When you connect, you call `pa_context_connect()`. However, if
21639 you remember, PulseAudio is an asynchronous API. That means you cannot just assume the context is connected after `pa_context_context()`
21640 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
21641 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.
21642 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.
21643 This waiting loop is therefore unavoidable. In order for the waiting to ever complete, however, the main loop needs to be running. Before
21644 attempting to connect the context, the main loop needs to be started with `pa_threaded_mainloop_start()`.
21645 
21646 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
21647 internet connection. However, the *VAST* majority of cases don't involve this at all - they just connect to a local "server" running on the
21648 host machine. The fact that this would be the default rather than making `pa_context_connect()` synchronous tends to boggle the mind.
21649 
21650 Once the context has been created and connected you can start creating a stream. A PulseAudio stream is analogous to miniaudio's device.
21651 The initialization of a stream is fairly standard - you configure some attributes (analogous to miniaudio's device config) and then call
21652 `pa_stream_new()` to actually create it. Here is where we start to get into "operations". When configuring the stream, you can get
21653 information about the source (such as sample format, sample rate, etc.), however it's not synchronous. Instead, a `pa_operation` object
21654 is returned from `pa_context_get_source_info_by_name()` (capture) or `pa_context_get_sink_info_by_name()` (playback). Then, you need to
21655 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
21656 context. Then, as an added bonus, you need to decrement the reference counter of the `pa_operation` object to ensure memory is cleaned up.
21657 All of that just to retrieve basic information about a device!
21658 
21659 Once the basic information about the device has been retrieved, miniaudio can now create the stream with `ma_stream_new()`. Like the
21660 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
21661 choices in PulseAudio.
21662 
21663 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
21664 because PulseAudio takes it literally, specifically the "can be". You would think these callbacks would be appropriate as the place for
21665 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
21666 set a flag that tells PulseAudio to not start the stream automatically. This is required because miniaudio does not auto-start devices
21667 straight after initialization - you need to call `ma_device_start()` manually. The problem is that even when this flag is specified,
21668 PulseAudio will immediately fire it's write or read callback. This is *technically* correct (based on the wording in the documentation)
21669 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
21670 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
21671 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
21672 that point (it may still need to load files or whatnot). Instead, this callback should only be fired when the application requests the
21673 stream be started which is how it works with literally *every* other callback-based audio API. Since miniaudio forbids firing of the data
21674 callback until the device has been started (as it should be with *all* callback based APIs), logic needs to be added to ensure miniaudio
21675 doesn't just blindly fire the application-defined data callback from within the PulseAudio callback before the stream has actually been
21676 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
21677 callback is not fired.
21678 
21679 This, unfortunately, is not the end of the problems with the PulseAudio write callback. Any normal callback based audio API will
21680 continuously fire the callback at regular intervals based on the size of the internal buffer. This will only ever be fired when the device
21681 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
21682 PulseAudio. In PulseAudio, the data callback will *only* be called if you wrote something to it previously. That means, if you don't call
21683 `pa_stream_write()`, the callback will not get fired. On the surface you wouldn't think this would matter because you should be always
21684 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
21685 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
21686 *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
21687 important? Because that's how we've defined stopping to work in miniaudio. In miniaudio, stopping the device requires it to be drained
21688 before returning from ma_device_stop(). So we've stopped the device, which requires us to drain, but draining requires us to *not* write
21689 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!
21690 
21691 This becomes a problem when stopping and then restarting the device. When the device is stopped, it's drained, which requires us to *not*
21692 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
21693 resume the stream naively. This means that starting the stream requires us to write data to the stream from outside the callback. This
21694 disconnect is something PulseAudio has got seriously wrong - there should only ever be a single source of data delivery, that being the
21695 callback. (I have tried using `pa_stream_flush()` to trigger the write callback to fire, but this just doesn't work for some reason.)
21696 
21697 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,
21698 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
21699 "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
21700 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
21701 guessed it, asynchronous. This means you'll need our waiting loop as usual. Again, why this asynchronous design is the default is
21702 absolutely beyond me. Would it really be that hard to just make it run synchronously?
21703 
21704 Teardown is pretty simple (what?!). It's just a matter of calling the relevant `_unref()` function on each object in reverse order that
21705 they were initialized in.
21706 
21707 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
21708 embarrassingly unpractical. The main loop thing is an easy fix - have synchronous versions of all APIs. If an application wants these to
21709 run asynchronously, they can execute them in a separate thread themselves. The desire to run these asynchronously is such a niche
21710 requirement - it makes no sense to make it the default. The stream write callback needs to be change, or an alternative provided, that is
21711 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
21712 parameter which the program just writes to directly rather than having to call `pa_stream_writable_size()` and `pa_stream_write()`. These
21713 changes alone will change PulseAudio from one of the worst audio APIs to one of the best.
21714 */
21715 
21716 
21717 /*
21718 It is assumed pulseaudio.h is available when linking at compile time. When linking at compile time, we use the declarations in the header
21719 to check for type safety. We cannot do this when linking at run time because the header might not be available.
21720 */
21721 #ifdef MA_NO_RUNTIME_LINKING
21722 
21723 /* pulseaudio.h marks some functions with "inline" which isn't always supported. Need to emulate it. */
21724 #if !defined(__cplusplus)
21725  #if defined(__STRICT_ANSI__)
21726  #if !defined(inline)
21727  #define inline __inline__ __attribute__((always_inline))
21728  #define MA_INLINE_DEFINED
21729  #endif
21730  #endif
21731 #endif
21732 #include <pulse/pulseaudio.h>
21733 #if defined(MA_INLINE_DEFINED)
21734  #undef inline
21735  #undef MA_INLINE_DEFINED
21736 #endif
21737 
21738 #define MA_PA_OK PA_OK
21739 #define MA_PA_ERR_ACCESS PA_ERR_ACCESS
21740 #define MA_PA_ERR_INVALID PA_ERR_INVALID
21741 #define MA_PA_ERR_NOENTITY PA_ERR_NOENTITY
21742 #define MA_PA_ERR_NOTSUPPORTED PA_ERR_NOTSUPPORTED
21743 
21744 #define MA_PA_CHANNELS_MAX PA_CHANNELS_MAX
21745 #define MA_PA_RATE_MAX PA_RATE_MAX
21746 
21747 typedef pa_context_flags_t ma_pa_context_flags_t;
21748 #define MA_PA_CONTEXT_NOFLAGS PA_CONTEXT_NOFLAGS
21749 #define MA_PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN
21750 #define MA_PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL
21751 
21752 typedef pa_stream_flags_t ma_pa_stream_flags_t;
21753 #define MA_PA_STREAM_NOFLAGS PA_STREAM_NOFLAGS
21754 #define MA_PA_STREAM_START_CORKED PA_STREAM_START_CORKED
21755 #define MA_PA_STREAM_INTERPOLATE_TIMING PA_STREAM_INTERPOLATE_TIMING
21756 #define MA_PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONIC
21757 #define MA_PA_STREAM_AUTO_TIMING_UPDATE PA_STREAM_AUTO_TIMING_UPDATE
21758 #define MA_PA_STREAM_NO_REMAP_CHANNELS PA_STREAM_NO_REMAP_CHANNELS
21759 #define MA_PA_STREAM_NO_REMIX_CHANNELS PA_STREAM_NO_REMIX_CHANNELS
21760 #define MA_PA_STREAM_FIX_FORMAT PA_STREAM_FIX_FORMAT
21761 #define MA_PA_STREAM_FIX_RATE PA_STREAM_FIX_RATE
21762 #define MA_PA_STREAM_FIX_CHANNELS PA_STREAM_FIX_CHANNELS
21763 #define MA_PA_STREAM_DONT_MOVE PA_STREAM_DONT_MOVE
21764 #define MA_PA_STREAM_VARIABLE_RATE PA_STREAM_VARIABLE_RATE
21765 #define MA_PA_STREAM_PEAK_DETECT PA_STREAM_PEAK_DETECT
21766 #define MA_PA_STREAM_START_MUTED PA_STREAM_START_MUTED
21767 #define MA_PA_STREAM_ADJUST_LATENCY PA_STREAM_ADJUST_LATENCY
21768 #define MA_PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS
21769 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
21770 #define MA_PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
21771 #define MA_PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
21772 #define MA_PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
21773 #define MA_PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH
21774 
21775 typedef pa_sink_flags_t ma_pa_sink_flags_t;
21776 #define MA_PA_SINK_NOFLAGS PA_SINK_NOFLAGS
21777 #define MA_PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL
21778 #define MA_PA_SINK_LATENCY PA_SINK_LATENCY
21779 #define MA_PA_SINK_HARDWARE PA_SINK_HARDWARE
21780 #define MA_PA_SINK_NETWORK PA_SINK_NETWORK
21781 #define MA_PA_SINK_HW_MUTE_CTRL PA_SINK_HW_MUTE_CTRL
21782 #define MA_PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME
21783 #define MA_PA_SINK_FLAT_VOLUME PA_SINK_FLAT_VOLUME
21784 #define MA_PA_SINK_DYNAMIC_LATENCY PA_SINK_DYNAMIC_LATENCY
21785 #define MA_PA_SINK_SET_FORMATS PA_SINK_SET_FORMATS
21786 
21787 typedef pa_source_flags_t ma_pa_source_flags_t;
21788 #define MA_PA_SOURCE_NOFLAGS PA_SOURCE_NOFLAGS
21789 #define MA_PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL
21790 #define MA_PA_SOURCE_LATENCY PA_SOURCE_LATENCY
21791 #define MA_PA_SOURCE_HARDWARE PA_SOURCE_HARDWARE
21792 #define MA_PA_SOURCE_NETWORK PA_SOURCE_NETWORK
21793 #define MA_PA_SOURCE_HW_MUTE_CTRL PA_SOURCE_HW_MUTE_CTRL
21794 #define MA_PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME
21795 #define MA_PA_SOURCE_DYNAMIC_LATENCY PA_SOURCE_DYNAMIC_LATENCY
21796 #define MA_PA_SOURCE_FLAT_VOLUME PA_SOURCE_FLAT_VOLUME
21797 
21798 typedef pa_context_state_t ma_pa_context_state_t;
21799 #define MA_PA_CONTEXT_UNCONNECTED PA_CONTEXT_UNCONNECTED
21800 #define MA_PA_CONTEXT_CONNECTING PA_CONTEXT_CONNECTING
21801 #define MA_PA_CONTEXT_AUTHORIZING PA_CONTEXT_AUTHORIZING
21802 #define MA_PA_CONTEXT_SETTING_NAME PA_CONTEXT_SETTING_NAME
21803 #define MA_PA_CONTEXT_READY PA_CONTEXT_READY
21804 #define MA_PA_CONTEXT_FAILED PA_CONTEXT_FAILED
21805 #define MA_PA_CONTEXT_TERMINATED PA_CONTEXT_TERMINATED
21806 
21807 typedef pa_stream_state_t ma_pa_stream_state_t;
21808 #define MA_PA_STREAM_UNCONNECTED PA_STREAM_UNCONNECTED
21809 #define MA_PA_STREAM_CREATING PA_STREAM_CREATING
21810 #define MA_PA_STREAM_READY PA_STREAM_READY
21811 #define MA_PA_STREAM_FAILED PA_STREAM_FAILED
21812 #define MA_PA_STREAM_TERMINATED PA_STREAM_TERMINATED
21813 
21814 typedef pa_operation_state_t ma_pa_operation_state_t;
21815 #define MA_PA_OPERATION_RUNNING PA_OPERATION_RUNNING
21816 #define MA_PA_OPERATION_DONE PA_OPERATION_DONE
21817 #define MA_PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
21818 
21819 typedef pa_sink_state_t ma_pa_sink_state_t;
21820 #define MA_PA_SINK_INVALID_STATE PA_SINK_INVALID_STATE
21821 #define MA_PA_SINK_RUNNING PA_SINK_RUNNING
21822 #define MA_PA_SINK_IDLE PA_SINK_IDLE
21823 #define MA_PA_SINK_SUSPENDED PA_SINK_SUSPENDED
21824 
21825 typedef pa_source_state_t ma_pa_source_state_t;
21826 #define MA_PA_SOURCE_INVALID_STATE PA_SOURCE_INVALID_STATE
21827 #define MA_PA_SOURCE_RUNNING PA_SOURCE_RUNNING
21828 #define MA_PA_SOURCE_IDLE PA_SOURCE_IDLE
21829 #define MA_PA_SOURCE_SUSPENDED PA_SOURCE_SUSPENDED
21830 
21831 typedef pa_seek_mode_t ma_pa_seek_mode_t;
21832 #define MA_PA_SEEK_RELATIVE PA_SEEK_RELATIVE
21833 #define MA_PA_SEEK_ABSOLUTE PA_SEEK_ABSOLUTE
21834 #define MA_PA_SEEK_RELATIVE_ON_READ PA_SEEK_RELATIVE_ON_READ
21835 #define MA_PA_SEEK_RELATIVE_END PA_SEEK_RELATIVE_END
21836 
21837 typedef pa_channel_position_t ma_pa_channel_position_t;
21838 #define MA_PA_CHANNEL_POSITION_INVALID PA_CHANNEL_POSITION_INVALID
21839 #define MA_PA_CHANNEL_POSITION_MONO PA_CHANNEL_POSITION_MONO
21840 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT PA_CHANNEL_POSITION_FRONT_LEFT
21841 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT PA_CHANNEL_POSITION_FRONT_RIGHT
21842 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER PA_CHANNEL_POSITION_FRONT_CENTER
21843 #define MA_PA_CHANNEL_POSITION_REAR_CENTER PA_CHANNEL_POSITION_REAR_CENTER
21844 #define MA_PA_CHANNEL_POSITION_REAR_LEFT PA_CHANNEL_POSITION_REAR_LEFT
21845 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT PA_CHANNEL_POSITION_REAR_RIGHT
21846 #define MA_PA_CHANNEL_POSITION_LFE PA_CHANNEL_POSITION_LFE
21847 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
21848 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
21849 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT PA_CHANNEL_POSITION_SIDE_LEFT
21850 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT PA_CHANNEL_POSITION_SIDE_RIGHT
21851 #define MA_PA_CHANNEL_POSITION_AUX0 PA_CHANNEL_POSITION_AUX0
21852 #define MA_PA_CHANNEL_POSITION_AUX1 PA_CHANNEL_POSITION_AUX1
21853 #define MA_PA_CHANNEL_POSITION_AUX2 PA_CHANNEL_POSITION_AUX2
21854 #define MA_PA_CHANNEL_POSITION_AUX3 PA_CHANNEL_POSITION_AUX3
21855 #define MA_PA_CHANNEL_POSITION_AUX4 PA_CHANNEL_POSITION_AUX4
21856 #define MA_PA_CHANNEL_POSITION_AUX5 PA_CHANNEL_POSITION_AUX5
21857 #define MA_PA_CHANNEL_POSITION_AUX6 PA_CHANNEL_POSITION_AUX6
21858 #define MA_PA_CHANNEL_POSITION_AUX7 PA_CHANNEL_POSITION_AUX7
21859 #define MA_PA_CHANNEL_POSITION_AUX8 PA_CHANNEL_POSITION_AUX8
21860 #define MA_PA_CHANNEL_POSITION_AUX9 PA_CHANNEL_POSITION_AUX9
21861 #define MA_PA_CHANNEL_POSITION_AUX10 PA_CHANNEL_POSITION_AUX10
21862 #define MA_PA_CHANNEL_POSITION_AUX11 PA_CHANNEL_POSITION_AUX11
21863 #define MA_PA_CHANNEL_POSITION_AUX12 PA_CHANNEL_POSITION_AUX12
21864 #define MA_PA_CHANNEL_POSITION_AUX13 PA_CHANNEL_POSITION_AUX13
21865 #define MA_PA_CHANNEL_POSITION_AUX14 PA_CHANNEL_POSITION_AUX14
21866 #define MA_PA_CHANNEL_POSITION_AUX15 PA_CHANNEL_POSITION_AUX15
21867 #define MA_PA_CHANNEL_POSITION_AUX16 PA_CHANNEL_POSITION_AUX16
21868 #define MA_PA_CHANNEL_POSITION_AUX17 PA_CHANNEL_POSITION_AUX17
21869 #define MA_PA_CHANNEL_POSITION_AUX18 PA_CHANNEL_POSITION_AUX18
21870 #define MA_PA_CHANNEL_POSITION_AUX19 PA_CHANNEL_POSITION_AUX19
21871 #define MA_PA_CHANNEL_POSITION_AUX20 PA_CHANNEL_POSITION_AUX20
21872 #define MA_PA_CHANNEL_POSITION_AUX21 PA_CHANNEL_POSITION_AUX21
21873 #define MA_PA_CHANNEL_POSITION_AUX22 PA_CHANNEL_POSITION_AUX22
21874 #define MA_PA_CHANNEL_POSITION_AUX23 PA_CHANNEL_POSITION_AUX23
21875 #define MA_PA_CHANNEL_POSITION_AUX24 PA_CHANNEL_POSITION_AUX24
21876 #define MA_PA_CHANNEL_POSITION_AUX25 PA_CHANNEL_POSITION_AUX25
21877 #define MA_PA_CHANNEL_POSITION_AUX26 PA_CHANNEL_POSITION_AUX26
21878 #define MA_PA_CHANNEL_POSITION_AUX27 PA_CHANNEL_POSITION_AUX27
21879 #define MA_PA_CHANNEL_POSITION_AUX28 PA_CHANNEL_POSITION_AUX28
21880 #define MA_PA_CHANNEL_POSITION_AUX29 PA_CHANNEL_POSITION_AUX29
21881 #define MA_PA_CHANNEL_POSITION_AUX30 PA_CHANNEL_POSITION_AUX30
21882 #define MA_PA_CHANNEL_POSITION_AUX31 PA_CHANNEL_POSITION_AUX31
21883 #define MA_PA_CHANNEL_POSITION_TOP_CENTER PA_CHANNEL_POSITION_TOP_CENTER
21884 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT PA_CHANNEL_POSITION_TOP_FRONT_LEFT
21885 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
21886 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER PA_CHANNEL_POSITION_TOP_FRONT_CENTER
21887 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT PA_CHANNEL_POSITION_TOP_REAR_LEFT
21888 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT PA_CHANNEL_POSITION_TOP_REAR_RIGHT
21889 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER PA_CHANNEL_POSITION_TOP_REAR_CENTER
21890 #define MA_PA_CHANNEL_POSITION_LEFT PA_CHANNEL_POSITION_LEFT
21891 #define MA_PA_CHANNEL_POSITION_RIGHT PA_CHANNEL_POSITION_RIGHT
21892 #define MA_PA_CHANNEL_POSITION_CENTER PA_CHANNEL_POSITION_CENTER
21893 #define MA_PA_CHANNEL_POSITION_SUBWOOFER PA_CHANNEL_POSITION_SUBWOOFER
21894 
21895 typedef pa_channel_map_def_t ma_pa_channel_map_def_t;
21896 #define MA_PA_CHANNEL_MAP_AIFF PA_CHANNEL_MAP_AIFF
21897 #define MA_PA_CHANNEL_MAP_ALSA PA_CHANNEL_MAP_ALSA
21898 #define MA_PA_CHANNEL_MAP_AUX PA_CHANNEL_MAP_AUX
21899 #define MA_PA_CHANNEL_MAP_WAVEEX PA_CHANNEL_MAP_WAVEEX
21900 #define MA_PA_CHANNEL_MAP_OSS PA_CHANNEL_MAP_OSS
21901 #define MA_PA_CHANNEL_MAP_DEFAULT PA_CHANNEL_MAP_DEFAULT
21902 
21903 typedef pa_sample_format_t ma_pa_sample_format_t;
21904 #define MA_PA_SAMPLE_INVALID PA_SAMPLE_INVALID
21905 #define MA_PA_SAMPLE_U8 PA_SAMPLE_U8
21906 #define MA_PA_SAMPLE_ALAW PA_SAMPLE_ALAW
21907 #define MA_PA_SAMPLE_ULAW PA_SAMPLE_ULAW
21908 #define MA_PA_SAMPLE_S16LE PA_SAMPLE_S16LE
21909 #define MA_PA_SAMPLE_S16BE PA_SAMPLE_S16BE
21910 #define MA_PA_SAMPLE_FLOAT32LE PA_SAMPLE_FLOAT32LE
21911 #define MA_PA_SAMPLE_FLOAT32BE PA_SAMPLE_FLOAT32BE
21912 #define MA_PA_SAMPLE_S32LE PA_SAMPLE_S32LE
21913 #define MA_PA_SAMPLE_S32BE PA_SAMPLE_S32BE
21914 #define MA_PA_SAMPLE_S24LE PA_SAMPLE_S24LE
21915 #define MA_PA_SAMPLE_S24BE PA_SAMPLE_S24BE
21916 #define MA_PA_SAMPLE_S24_32LE PA_SAMPLE_S24_32LE
21917 #define MA_PA_SAMPLE_S24_32BE PA_SAMPLE_S24_32BE
21918 
21919 typedef pa_mainloop ma_pa_mainloop;
21920 typedef pa_threaded_mainloop ma_pa_threaded_mainloop;
21921 typedef pa_mainloop_api ma_pa_mainloop_api;
21922 typedef pa_context ma_pa_context;
21923 typedef pa_operation ma_pa_operation;
21924 typedef pa_stream ma_pa_stream;
21925 typedef pa_spawn_api ma_pa_spawn_api;
21926 typedef pa_buffer_attr ma_pa_buffer_attr;
21927 typedef pa_channel_map ma_pa_channel_map;
21928 typedef pa_cvolume ma_pa_cvolume;
21929 typedef pa_sample_spec ma_pa_sample_spec;
21930 typedef pa_sink_info ma_pa_sink_info;
21931 typedef pa_source_info ma_pa_source_info;
21932 
21933 typedef pa_context_notify_cb_t ma_pa_context_notify_cb_t;
21934 typedef pa_sink_info_cb_t ma_pa_sink_info_cb_t;
21935 typedef pa_source_info_cb_t ma_pa_source_info_cb_t;
21936 typedef pa_stream_success_cb_t ma_pa_stream_success_cb_t;
21937 typedef pa_stream_request_cb_t ma_pa_stream_request_cb_t;
21938 typedef pa_stream_notify_cb_t ma_pa_stream_notify_cb_t;
21939 typedef pa_free_cb_t ma_pa_free_cb_t;
21940 #else
21941 #define MA_PA_OK 0
21942 #define MA_PA_ERR_ACCESS 1
21943 #define MA_PA_ERR_INVALID 2
21944 #define MA_PA_ERR_NOENTITY 5
21945 #define MA_PA_ERR_NOTSUPPORTED 19
21946 
21947 #define MA_PA_CHANNELS_MAX 32
21948 #define MA_PA_RATE_MAX 384000
21949 
21950 typedef int ma_pa_context_flags_t;
21951 #define MA_PA_CONTEXT_NOFLAGS 0x00000000
21952 #define MA_PA_CONTEXT_NOAUTOSPAWN 0x00000001
21953 #define MA_PA_CONTEXT_NOFAIL 0x00000002
21954 
21955 typedef int ma_pa_stream_flags_t;
21956 #define MA_PA_STREAM_NOFLAGS 0x00000000
21957 #define MA_PA_STREAM_START_CORKED 0x00000001
21958 #define MA_PA_STREAM_INTERPOLATE_TIMING 0x00000002
21959 #define MA_PA_STREAM_NOT_MONOTONIC 0x00000004
21960 #define MA_PA_STREAM_AUTO_TIMING_UPDATE 0x00000008
21961 #define MA_PA_STREAM_NO_REMAP_CHANNELS 0x00000010
21962 #define MA_PA_STREAM_NO_REMIX_CHANNELS 0x00000020
21963 #define MA_PA_STREAM_FIX_FORMAT 0x00000040
21964 #define MA_PA_STREAM_FIX_RATE 0x00000080
21965 #define MA_PA_STREAM_FIX_CHANNELS 0x00000100
21966 #define MA_PA_STREAM_DONT_MOVE 0x00000200
21967 #define MA_PA_STREAM_VARIABLE_RATE 0x00000400
21968 #define MA_PA_STREAM_PEAK_DETECT 0x00000800
21969 #define MA_PA_STREAM_START_MUTED 0x00001000
21970 #define MA_PA_STREAM_ADJUST_LATENCY 0x00002000
21971 #define MA_PA_STREAM_EARLY_REQUESTS 0x00004000
21972 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND 0x00008000
21973 #define MA_PA_STREAM_START_UNMUTED 0x00010000
21974 #define MA_PA_STREAM_FAIL_ON_SUSPEND 0x00020000
21975 #define MA_PA_STREAM_RELATIVE_VOLUME 0x00040000
21976 #define MA_PA_STREAM_PASSTHROUGH 0x00080000
21977 
21978 typedef int ma_pa_sink_flags_t;
21979 #define MA_PA_SINK_NOFLAGS 0x00000000
21980 #define MA_PA_SINK_HW_VOLUME_CTRL 0x00000001
21981 #define MA_PA_SINK_LATENCY 0x00000002
21982 #define MA_PA_SINK_HARDWARE 0x00000004
21983 #define MA_PA_SINK_NETWORK 0x00000008
21984 #define MA_PA_SINK_HW_MUTE_CTRL 0x00000010
21985 #define MA_PA_SINK_DECIBEL_VOLUME 0x00000020
21986 #define MA_PA_SINK_FLAT_VOLUME 0x00000040
21987 #define MA_PA_SINK_DYNAMIC_LATENCY 0x00000080
21988 #define MA_PA_SINK_SET_FORMATS 0x00000100
21989 
21990 typedef int ma_pa_source_flags_t;
21991 #define MA_PA_SOURCE_NOFLAGS 0x00000000
21992 #define MA_PA_SOURCE_HW_VOLUME_CTRL 0x00000001
21993 #define MA_PA_SOURCE_LATENCY 0x00000002
21994 #define MA_PA_SOURCE_HARDWARE 0x00000004
21995 #define MA_PA_SOURCE_NETWORK 0x00000008
21996 #define MA_PA_SOURCE_HW_MUTE_CTRL 0x00000010
21997 #define MA_PA_SOURCE_DECIBEL_VOLUME 0x00000020
21998 #define MA_PA_SOURCE_DYNAMIC_LATENCY 0x00000040
21999 #define MA_PA_SOURCE_FLAT_VOLUME 0x00000080
22000 
22001 typedef int ma_pa_context_state_t;
22002 #define MA_PA_CONTEXT_UNCONNECTED 0
22003 #define MA_PA_CONTEXT_CONNECTING 1
22004 #define MA_PA_CONTEXT_AUTHORIZING 2
22005 #define MA_PA_CONTEXT_SETTING_NAME 3
22006 #define MA_PA_CONTEXT_READY 4
22007 #define MA_PA_CONTEXT_FAILED 5
22008 #define MA_PA_CONTEXT_TERMINATED 6
22009 
22010 typedef int ma_pa_stream_state_t;
22011 #define MA_PA_STREAM_UNCONNECTED 0
22012 #define MA_PA_STREAM_CREATING 1
22013 #define MA_PA_STREAM_READY 2
22014 #define MA_PA_STREAM_FAILED 3
22015 #define MA_PA_STREAM_TERMINATED 4
22016 
22017 typedef int ma_pa_operation_state_t;
22018 #define MA_PA_OPERATION_RUNNING 0
22019 #define MA_PA_OPERATION_DONE 1
22020 #define MA_PA_OPERATION_CANCELLED 2
22021 
22022 typedef int ma_pa_sink_state_t;
22023 #define MA_PA_SINK_INVALID_STATE -1
22024 #define MA_PA_SINK_RUNNING 0
22025 #define MA_PA_SINK_IDLE 1
22026 #define MA_PA_SINK_SUSPENDED 2
22027 
22028 typedef int ma_pa_source_state_t;
22029 #define MA_PA_SOURCE_INVALID_STATE -1
22030 #define MA_PA_SOURCE_RUNNING 0
22031 #define MA_PA_SOURCE_IDLE 1
22032 #define MA_PA_SOURCE_SUSPENDED 2
22033 
22034 typedef int ma_pa_seek_mode_t;
22035 #define MA_PA_SEEK_RELATIVE 0
22036 #define MA_PA_SEEK_ABSOLUTE 1
22037 #define MA_PA_SEEK_RELATIVE_ON_READ 2
22038 #define MA_PA_SEEK_RELATIVE_END 3
22039 
22040 typedef int ma_pa_channel_position_t;
22041 #define MA_PA_CHANNEL_POSITION_INVALID -1
22042 #define MA_PA_CHANNEL_POSITION_MONO 0
22043 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT 1
22044 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT 2
22045 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER 3
22046 #define MA_PA_CHANNEL_POSITION_REAR_CENTER 4
22047 #define MA_PA_CHANNEL_POSITION_REAR_LEFT 5
22048 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT 6
22049 #define MA_PA_CHANNEL_POSITION_LFE 7
22050 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER 8
22051 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER 9
22052 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT 10
22053 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT 11
22054 #define MA_PA_CHANNEL_POSITION_AUX0 12
22055 #define MA_PA_CHANNEL_POSITION_AUX1 13
22056 #define MA_PA_CHANNEL_POSITION_AUX2 14
22057 #define MA_PA_CHANNEL_POSITION_AUX3 15
22058 #define MA_PA_CHANNEL_POSITION_AUX4 16
22059 #define MA_PA_CHANNEL_POSITION_AUX5 17
22060 #define MA_PA_CHANNEL_POSITION_AUX6 18
22061 #define MA_PA_CHANNEL_POSITION_AUX7 19
22062 #define MA_PA_CHANNEL_POSITION_AUX8 20
22063 #define MA_PA_CHANNEL_POSITION_AUX9 21
22064 #define MA_PA_CHANNEL_POSITION_AUX10 22
22065 #define MA_PA_CHANNEL_POSITION_AUX11 23
22066 #define MA_PA_CHANNEL_POSITION_AUX12 24
22067 #define MA_PA_CHANNEL_POSITION_AUX13 25
22068 #define MA_PA_CHANNEL_POSITION_AUX14 26
22069 #define MA_PA_CHANNEL_POSITION_AUX15 27
22070 #define MA_PA_CHANNEL_POSITION_AUX16 28
22071 #define MA_PA_CHANNEL_POSITION_AUX17 29
22072 #define MA_PA_CHANNEL_POSITION_AUX18 30
22073 #define MA_PA_CHANNEL_POSITION_AUX19 31
22074 #define MA_PA_CHANNEL_POSITION_AUX20 32
22075 #define MA_PA_CHANNEL_POSITION_AUX21 33
22076 #define MA_PA_CHANNEL_POSITION_AUX22 34
22077 #define MA_PA_CHANNEL_POSITION_AUX23 35
22078 #define MA_PA_CHANNEL_POSITION_AUX24 36
22079 #define MA_PA_CHANNEL_POSITION_AUX25 37
22080 #define MA_PA_CHANNEL_POSITION_AUX26 38
22081 #define MA_PA_CHANNEL_POSITION_AUX27 39
22082 #define MA_PA_CHANNEL_POSITION_AUX28 40
22083 #define MA_PA_CHANNEL_POSITION_AUX29 41
22084 #define MA_PA_CHANNEL_POSITION_AUX30 42
22085 #define MA_PA_CHANNEL_POSITION_AUX31 43
22086 #define MA_PA_CHANNEL_POSITION_TOP_CENTER 44
22087 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT 45
22088 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT 46
22089 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER 47
22090 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT 48
22091 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT 49
22092 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER 50
22093 #define MA_PA_CHANNEL_POSITION_LEFT MA_PA_CHANNEL_POSITION_FRONT_LEFT
22094 #define MA_PA_CHANNEL_POSITION_RIGHT MA_PA_CHANNEL_POSITION_FRONT_RIGHT
22095 #define MA_PA_CHANNEL_POSITION_CENTER MA_PA_CHANNEL_POSITION_FRONT_CENTER
22096 #define MA_PA_CHANNEL_POSITION_SUBWOOFER MA_PA_CHANNEL_POSITION_LFE
22097 
22098 typedef int ma_pa_channel_map_def_t;
22099 #define MA_PA_CHANNEL_MAP_AIFF 0
22100 #define MA_PA_CHANNEL_MAP_ALSA 1
22101 #define MA_PA_CHANNEL_MAP_AUX 2
22102 #define MA_PA_CHANNEL_MAP_WAVEEX 3
22103 #define MA_PA_CHANNEL_MAP_OSS 4
22104 #define MA_PA_CHANNEL_MAP_DEFAULT MA_PA_CHANNEL_MAP_AIFF
22105 
22106 typedef int ma_pa_sample_format_t;
22107 #define MA_PA_SAMPLE_INVALID -1
22108 #define MA_PA_SAMPLE_U8 0
22109 #define MA_PA_SAMPLE_ALAW 1
22110 #define MA_PA_SAMPLE_ULAW 2
22111 #define MA_PA_SAMPLE_S16LE 3
22112 #define MA_PA_SAMPLE_S16BE 4
22113 #define MA_PA_SAMPLE_FLOAT32LE 5
22114 #define MA_PA_SAMPLE_FLOAT32BE 6
22115 #define MA_PA_SAMPLE_S32LE 7
22116 #define MA_PA_SAMPLE_S32BE 8
22117 #define MA_PA_SAMPLE_S24LE 9
22118 #define MA_PA_SAMPLE_S24BE 10
22119 #define MA_PA_SAMPLE_S24_32LE 11
22120 #define MA_PA_SAMPLE_S24_32BE 12
22121 
22122 typedef struct ma_pa_mainloop ma_pa_mainloop;
22123 typedef struct ma_pa_threaded_mainloop ma_pa_threaded_mainloop;
22124 typedef struct ma_pa_mainloop_api ma_pa_mainloop_api;
22125 typedef struct ma_pa_context ma_pa_context;
22126 typedef struct ma_pa_operation ma_pa_operation;
22127 typedef struct ma_pa_stream ma_pa_stream;
22128 typedef struct ma_pa_spawn_api ma_pa_spawn_api;
22129 
22130 typedef struct
22131 {
22132  ma_uint32 maxlength;
22133  ma_uint32 tlength;
22134  ma_uint32 prebuf;
22135  ma_uint32 minreq;
22136  ma_uint32 fragsize;
22137 } ma_pa_buffer_attr;
22138 
22139 typedef struct
22140 {
22141  ma_uint8 channels;
22142  ma_pa_channel_position_t map[MA_PA_CHANNELS_MAX];
22143 } ma_pa_channel_map;
22144 
22145 typedef struct
22146 {
22147  ma_uint8 channels;
22148  ma_uint32 values[MA_PA_CHANNELS_MAX];
22149 } ma_pa_cvolume;
22150 
22151 typedef struct
22152 {
22153  ma_pa_sample_format_t format;
22154  ma_uint32 rate;
22155  ma_uint8 channels;
22156 } ma_pa_sample_spec;
22157 
22158 typedef struct
22159 {
22160  const char* name;
22161  ma_uint32 index;
22162  const char* description;
22163  ma_pa_sample_spec sample_spec;
22164  ma_pa_channel_map channel_map;
22165  ma_uint32 owner_module;
22166  ma_pa_cvolume volume;
22167  int mute;
22168  ma_uint32 monitor_source;
22169  const char* monitor_source_name;
22170  ma_uint64 latency;
22171  const char* driver;
22172  ma_pa_sink_flags_t flags;
22173  void* proplist;
22174  ma_uint64 configured_latency;
22175  ma_uint32 base_volume;
22176  ma_pa_sink_state_t state;
22177  ma_uint32 n_volume_steps;
22178  ma_uint32 card;
22179  ma_uint32 n_ports;
22180  void** ports;
22181  void* active_port;
22182  ma_uint8 n_formats;
22183  void** formats;
22184 } ma_pa_sink_info;
22185 
22186 typedef struct
22187 {
22188  const char *name;
22189  ma_uint32 index;
22190  const char *description;
22191  ma_pa_sample_spec sample_spec;
22192  ma_pa_channel_map channel_map;
22193  ma_uint32 owner_module;
22194  ma_pa_cvolume volume;
22195  int mute;
22196  ma_uint32 monitor_of_sink;
22197  const char *monitor_of_sink_name;
22198  ma_uint64 latency;
22199  const char *driver;
22200  ma_pa_source_flags_t flags;
22201  void* proplist;
22202  ma_uint64 configured_latency;
22203  ma_uint32 base_volume;
22204  ma_pa_source_state_t state;
22205  ma_uint32 n_volume_steps;
22206  ma_uint32 card;
22207  ma_uint32 n_ports;
22208  void** ports;
22209  void* active_port;
22210  ma_uint8 n_formats;
22211  void** formats;
22212 } ma_pa_source_info;
22213 
22214 typedef void (* ma_pa_context_notify_cb_t)(ma_pa_context* c, void* userdata);
22215 typedef void (* ma_pa_sink_info_cb_t) (ma_pa_context* c, const ma_pa_sink_info* i, int eol, void* userdata);
22216 typedef void (* ma_pa_source_info_cb_t) (ma_pa_context* c, const ma_pa_source_info* i, int eol, void* userdata);
22217 typedef void (* ma_pa_stream_success_cb_t)(ma_pa_stream* s, int success, void* userdata);
22218 typedef void (* ma_pa_stream_request_cb_t)(ma_pa_stream* s, size_t nbytes, void* userdata);
22219 typedef void (* ma_pa_stream_notify_cb_t) (ma_pa_stream* s, void* userdata);
22220 typedef void (* ma_pa_free_cb_t) (void* p);
22221 #endif
22222 
22223 
22224 typedef ma_pa_mainloop* (* ma_pa_mainloop_new_proc) (void);
22225 typedef void (* ma_pa_mainloop_free_proc) (ma_pa_mainloop* m);
22226 typedef void (* ma_pa_mainloop_quit_proc) (ma_pa_mainloop* m, int retval);
22227 typedef ma_pa_mainloop_api* (* ma_pa_mainloop_get_api_proc) (ma_pa_mainloop* m);
22228 typedef int (* ma_pa_mainloop_iterate_proc) (ma_pa_mainloop* m, int block, int* retval);
22229 typedef void (* ma_pa_mainloop_wakeup_proc) (ma_pa_mainloop* m);
22230 typedef ma_pa_threaded_mainloop* (* ma_pa_threaded_mainloop_new_proc) (void);
22231 typedef void (* ma_pa_threaded_mainloop_free_proc) (ma_pa_threaded_mainloop* m);
22232 typedef int (* ma_pa_threaded_mainloop_start_proc) (ma_pa_threaded_mainloop* m);
22233 typedef void (* ma_pa_threaded_mainloop_stop_proc) (ma_pa_threaded_mainloop* m);
22234 typedef void (* ma_pa_threaded_mainloop_lock_proc) (ma_pa_threaded_mainloop* m);
22235 typedef void (* ma_pa_threaded_mainloop_unlock_proc) (ma_pa_threaded_mainloop* m);
22236 typedef void (* ma_pa_threaded_mainloop_wait_proc) (ma_pa_threaded_mainloop* m);
22237 typedef void (* ma_pa_threaded_mainloop_signal_proc) (ma_pa_threaded_mainloop* m, int wait_for_accept);
22238 typedef void (* ma_pa_threaded_mainloop_accept_proc) (ma_pa_threaded_mainloop* m);
22239 typedef int (* ma_pa_threaded_mainloop_get_retval_proc) (ma_pa_threaded_mainloop* m);
22240 typedef ma_pa_mainloop_api* (* ma_pa_threaded_mainloop_get_api_proc) (ma_pa_threaded_mainloop* m);
22241 typedef int (* ma_pa_threaded_mainloop_in_thread_proc) (ma_pa_threaded_mainloop* m);
22242 typedef void (* ma_pa_threaded_mainloop_set_name_proc) (ma_pa_threaded_mainloop* m, const char* name);
22243 typedef ma_pa_context* (* ma_pa_context_new_proc) (ma_pa_mainloop_api* mainloop, const char* name);
22244 typedef void (* ma_pa_context_unref_proc) (ma_pa_context* c);
22245 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);
22246 typedef void (* ma_pa_context_disconnect_proc) (ma_pa_context* c);
22247 typedef void (* ma_pa_context_set_state_callback_proc) (ma_pa_context* c, ma_pa_context_notify_cb_t cb, void* userdata);
22248 typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (ma_pa_context* c);
22249 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);
22250 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);
22251 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);
22252 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);
22253 typedef void (* ma_pa_operation_unref_proc) (ma_pa_operation* o);
22254 typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (ma_pa_operation* o);
22255 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);
22256 typedef int (* ma_pa_channel_map_valid_proc) (const ma_pa_channel_map* m);
22257 typedef int (* ma_pa_channel_map_compatible_proc) (const ma_pa_channel_map* m, const ma_pa_sample_spec* ss);
22258 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);
22259 typedef void (* ma_pa_stream_unref_proc) (ma_pa_stream* s);
22260 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);
22261 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);
22262 typedef int (* ma_pa_stream_disconnect_proc) (ma_pa_stream* s);
22263 typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (ma_pa_stream* s);
22264 typedef const ma_pa_sample_spec* (* ma_pa_stream_get_sample_spec_proc) (ma_pa_stream* s);
22265 typedef const ma_pa_channel_map* (* ma_pa_stream_get_channel_map_proc) (ma_pa_stream* s);
22266 typedef const ma_pa_buffer_attr* (* ma_pa_stream_get_buffer_attr_proc) (ma_pa_stream* s);
22267 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);
22268 typedef const char* (* ma_pa_stream_get_device_name_proc) (ma_pa_stream* s);
22269 typedef void (* ma_pa_stream_set_write_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata);
22270 typedef void (* ma_pa_stream_set_read_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata);
22271 typedef void (* ma_pa_stream_set_suspended_callback_proc) (ma_pa_stream* s, ma_pa_stream_notify_cb_t cb, void* userdata);
22272 typedef int (* ma_pa_stream_is_suspended_proc) (const ma_pa_stream* s);
22273 typedef ma_pa_operation* (* ma_pa_stream_flush_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
22274 typedef ma_pa_operation* (* ma_pa_stream_drain_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
22275 typedef int (* ma_pa_stream_is_corked_proc) (ma_pa_stream* s);
22276 typedef ma_pa_operation* (* ma_pa_stream_cork_proc) (ma_pa_stream* s, int b, ma_pa_stream_success_cb_t cb, void* userdata);
22277 typedef ma_pa_operation* (* ma_pa_stream_trigger_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
22278 typedef int (* ma_pa_stream_begin_write_proc) (ma_pa_stream* s, void** data, size_t* nbytes);
22279 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);
22280 typedef int (* ma_pa_stream_peek_proc) (ma_pa_stream* s, const void** data, size_t* nbytes);
22281 typedef int (* ma_pa_stream_drop_proc) (ma_pa_stream* s);
22282 typedef size_t (* ma_pa_stream_writable_size_proc) (ma_pa_stream* s);
22283 typedef size_t (* ma_pa_stream_readable_size_proc) (ma_pa_stream* s);
22284 
22285 typedef struct
22286 {
22287  ma_uint32 count;
22288  ma_uint32 capacity;
22289  ma_device_info* pInfo;
22290 } ma_pulse_device_enum_data;
22291 
22292 static ma_result ma_result_from_pulse(int result)
22293 {
22294  if (result < 0) {
22295  return MA_ERROR;
22296  }
22297 
22298  switch (result) {
22299  case MA_PA_OK: return MA_SUCCESS;
22300  case MA_PA_ERR_ACCESS: return MA_ACCESS_DENIED;
22301  case MA_PA_ERR_INVALID: return MA_INVALID_ARGS;
22302  case MA_PA_ERR_NOENTITY: return MA_NO_DEVICE;
22303  default: return MA_ERROR;
22304  }
22305 }
22306 
22307 #if 0
22308 static ma_pa_sample_format_t ma_format_to_pulse(ma_format format)
22309 {
22310  if (ma_is_little_endian()) {
22311  switch (format) {
22312  case ma_format_s16: return MA_PA_SAMPLE_S16LE;
22313  case ma_format_s24: return MA_PA_SAMPLE_S24LE;
22314  case ma_format_s32: return MA_PA_SAMPLE_S32LE;
22315  case ma_format_f32: return MA_PA_SAMPLE_FLOAT32LE;
22316  default: break;
22317  }
22318  } else {
22319  switch (format) {
22320  case ma_format_s16: return MA_PA_SAMPLE_S16BE;
22321  case ma_format_s24: return MA_PA_SAMPLE_S24BE;
22322  case ma_format_s32: return MA_PA_SAMPLE_S32BE;
22323  case ma_format_f32: return MA_PA_SAMPLE_FLOAT32BE;
22324  default: break;
22325  }
22326  }
22327 
22328  /* Endian agnostic. */
22329  switch (format) {
22330  case ma_format_u8: return MA_PA_SAMPLE_U8;
22331  default: return MA_PA_SAMPLE_INVALID;
22332  }
22333 }
22334 #endif
22335 
22336 static ma_format ma_format_from_pulse(ma_pa_sample_format_t format)
22337 {
22338  if (ma_is_little_endian()) {
22339  switch (format) {
22340  case MA_PA_SAMPLE_S16LE: return ma_format_s16;
22341  case MA_PA_SAMPLE_S24LE: return ma_format_s24;
22342  case MA_PA_SAMPLE_S32LE: return ma_format_s32;
22343  case MA_PA_SAMPLE_FLOAT32LE: return ma_format_f32;
22344  default: break;
22345  }
22346  } else {
22347  switch (format) {
22348  case MA_PA_SAMPLE_S16BE: return ma_format_s16;
22349  case MA_PA_SAMPLE_S24BE: return ma_format_s24;
22350  case MA_PA_SAMPLE_S32BE: return ma_format_s32;
22351  case MA_PA_SAMPLE_FLOAT32BE: return ma_format_f32;
22352  default: break;
22353  }
22354  }
22355 
22356  /* Endian agnostic. */
22357  switch (format) {
22358  case MA_PA_SAMPLE_U8: return ma_format_u8;
22359  default: return ma_format_unknown;
22360  }
22361 }
22362 
22363 static ma_channel ma_channel_position_from_pulse(ma_pa_channel_position_t position)
22364 {
22365  switch (position)
22366  {
22367  case MA_PA_CHANNEL_POSITION_INVALID: return MA_CHANNEL_NONE;
22368  case MA_PA_CHANNEL_POSITION_MONO: return MA_CHANNEL_MONO;
22369  case MA_PA_CHANNEL_POSITION_FRONT_LEFT: return MA_CHANNEL_FRONT_LEFT;
22370  case MA_PA_CHANNEL_POSITION_FRONT_RIGHT: return MA_CHANNEL_FRONT_RIGHT;
22371  case MA_PA_CHANNEL_POSITION_FRONT_CENTER: return MA_CHANNEL_FRONT_CENTER;
22372  case MA_PA_CHANNEL_POSITION_REAR_CENTER: return MA_CHANNEL_BACK_CENTER;
22373  case MA_PA_CHANNEL_POSITION_REAR_LEFT: return MA_CHANNEL_BACK_LEFT;
22374  case MA_PA_CHANNEL_POSITION_REAR_RIGHT: return MA_CHANNEL_BACK_RIGHT;
22375  case MA_PA_CHANNEL_POSITION_LFE: return MA_CHANNEL_LFE;
22376  case MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: return MA_CHANNEL_FRONT_LEFT_CENTER;
22377  case MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return MA_CHANNEL_FRONT_RIGHT_CENTER;
22378  case MA_PA_CHANNEL_POSITION_SIDE_LEFT: return MA_CHANNEL_SIDE_LEFT;
22379  case MA_PA_CHANNEL_POSITION_SIDE_RIGHT: return MA_CHANNEL_SIDE_RIGHT;
22380  case MA_PA_CHANNEL_POSITION_AUX0: return MA_CHANNEL_AUX_0;
22381  case MA_PA_CHANNEL_POSITION_AUX1: return MA_CHANNEL_AUX_1;
22382  case MA_PA_CHANNEL_POSITION_AUX2: return MA_CHANNEL_AUX_2;
22383  case MA_PA_CHANNEL_POSITION_AUX3: return MA_CHANNEL_AUX_3;
22384  case MA_PA_CHANNEL_POSITION_AUX4: return MA_CHANNEL_AUX_4;
22385  case MA_PA_CHANNEL_POSITION_AUX5: return MA_CHANNEL_AUX_5;
22386  case MA_PA_CHANNEL_POSITION_AUX6: return MA_CHANNEL_AUX_6;
22387  case MA_PA_CHANNEL_POSITION_AUX7: return MA_CHANNEL_AUX_7;
22388  case MA_PA_CHANNEL_POSITION_AUX8: return MA_CHANNEL_AUX_8;
22389  case MA_PA_CHANNEL_POSITION_AUX9: return MA_CHANNEL_AUX_9;
22390  case MA_PA_CHANNEL_POSITION_AUX10: return MA_CHANNEL_AUX_10;
22391  case MA_PA_CHANNEL_POSITION_AUX11: return MA_CHANNEL_AUX_11;
22392  case MA_PA_CHANNEL_POSITION_AUX12: return MA_CHANNEL_AUX_12;
22393  case MA_PA_CHANNEL_POSITION_AUX13: return MA_CHANNEL_AUX_13;
22394  case MA_PA_CHANNEL_POSITION_AUX14: return MA_CHANNEL_AUX_14;
22395  case MA_PA_CHANNEL_POSITION_AUX15: return MA_CHANNEL_AUX_15;
22396  case MA_PA_CHANNEL_POSITION_AUX16: return MA_CHANNEL_AUX_16;
22397  case MA_PA_CHANNEL_POSITION_AUX17: return MA_CHANNEL_AUX_17;
22398  case MA_PA_CHANNEL_POSITION_AUX18: return MA_CHANNEL_AUX_18;
22399  case MA_PA_CHANNEL_POSITION_AUX19: return MA_CHANNEL_AUX_19;
22400  case MA_PA_CHANNEL_POSITION_AUX20: return MA_CHANNEL_AUX_20;
22401  case MA_PA_CHANNEL_POSITION_AUX21: return MA_CHANNEL_AUX_21;
22402  case MA_PA_CHANNEL_POSITION_AUX22: return MA_CHANNEL_AUX_22;
22403  case MA_PA_CHANNEL_POSITION_AUX23: return MA_CHANNEL_AUX_23;
22404  case MA_PA_CHANNEL_POSITION_AUX24: return MA_CHANNEL_AUX_24;
22405  case MA_PA_CHANNEL_POSITION_AUX25: return MA_CHANNEL_AUX_25;
22406  case MA_PA_CHANNEL_POSITION_AUX26: return MA_CHANNEL_AUX_26;
22407  case MA_PA_CHANNEL_POSITION_AUX27: return MA_CHANNEL_AUX_27;
22408  case MA_PA_CHANNEL_POSITION_AUX28: return MA_CHANNEL_AUX_28;
22409  case MA_PA_CHANNEL_POSITION_AUX29: return MA_CHANNEL_AUX_29;
22410  case MA_PA_CHANNEL_POSITION_AUX30: return MA_CHANNEL_AUX_30;
22411  case MA_PA_CHANNEL_POSITION_AUX31: return MA_CHANNEL_AUX_31;
22412  case MA_PA_CHANNEL_POSITION_TOP_CENTER: return MA_CHANNEL_TOP_CENTER;
22413  case MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT: return MA_CHANNEL_TOP_FRONT_LEFT;
22414  case MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: return MA_CHANNEL_TOP_FRONT_RIGHT;
22415  case MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER: return MA_CHANNEL_TOP_FRONT_CENTER;
22416  case MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT: return MA_CHANNEL_TOP_BACK_LEFT;
22417  case MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT: return MA_CHANNEL_TOP_BACK_RIGHT;
22418  case MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER: return MA_CHANNEL_TOP_BACK_CENTER;
22419  default: return MA_CHANNEL_NONE;
22420  }
22421 }
22422 
22423 #if 0
22424 static ma_pa_channel_position_t ma_channel_position_to_pulse(ma_channel position)
22425 {
22426  switch (position)
22427  {
22428  case MA_CHANNEL_NONE: return MA_PA_CHANNEL_POSITION_INVALID;
22429  case MA_CHANNEL_FRONT_LEFT: return MA_PA_CHANNEL_POSITION_FRONT_LEFT;
22430  case MA_CHANNEL_FRONT_RIGHT: return MA_PA_CHANNEL_POSITION_FRONT_RIGHT;
22431  case MA_CHANNEL_FRONT_CENTER: return MA_PA_CHANNEL_POSITION_FRONT_CENTER;
22432  case MA_CHANNEL_LFE: return MA_PA_CHANNEL_POSITION_LFE;
22433  case MA_CHANNEL_BACK_LEFT: return MA_PA_CHANNEL_POSITION_REAR_LEFT;
22434  case MA_CHANNEL_BACK_RIGHT: return MA_PA_CHANNEL_POSITION_REAR_RIGHT;
22435  case MA_CHANNEL_FRONT_LEFT_CENTER: return MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
22436  case MA_CHANNEL_FRONT_RIGHT_CENTER: return MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
22437  case MA_CHANNEL_BACK_CENTER: return MA_PA_CHANNEL_POSITION_REAR_CENTER;
22438  case MA_CHANNEL_SIDE_LEFT: return MA_PA_CHANNEL_POSITION_SIDE_LEFT;
22439  case MA_CHANNEL_SIDE_RIGHT: return MA_PA_CHANNEL_POSITION_SIDE_RIGHT;
22440  case MA_CHANNEL_TOP_CENTER: return MA_PA_CHANNEL_POSITION_TOP_CENTER;
22441  case MA_CHANNEL_TOP_FRONT_LEFT: return MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
22442  case MA_CHANNEL_TOP_FRONT_CENTER: return MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
22443  case MA_CHANNEL_TOP_FRONT_RIGHT: return MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
22444  case MA_CHANNEL_TOP_BACK_LEFT: return MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT;
22445  case MA_CHANNEL_TOP_BACK_CENTER: return MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER;
22446  case MA_CHANNEL_TOP_BACK_RIGHT: return MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
22447  case MA_CHANNEL_19: return MA_PA_CHANNEL_POSITION_AUX18;
22448  case MA_CHANNEL_20: return MA_PA_CHANNEL_POSITION_AUX19;
22449  case MA_CHANNEL_21: return MA_PA_CHANNEL_POSITION_AUX20;
22450  case MA_CHANNEL_22: return MA_PA_CHANNEL_POSITION_AUX21;
22451  case MA_CHANNEL_23: return MA_PA_CHANNEL_POSITION_AUX22;
22452  case MA_CHANNEL_24: return MA_PA_CHANNEL_POSITION_AUX23;
22453  case MA_CHANNEL_25: return MA_PA_CHANNEL_POSITION_AUX24;
22454  case MA_CHANNEL_26: return MA_PA_CHANNEL_POSITION_AUX25;
22455  case MA_CHANNEL_27: return MA_PA_CHANNEL_POSITION_AUX26;
22456  case MA_CHANNEL_28: return MA_PA_CHANNEL_POSITION_AUX27;
22457  case MA_CHANNEL_29: return MA_PA_CHANNEL_POSITION_AUX28;
22458  case MA_CHANNEL_30: return MA_PA_CHANNEL_POSITION_AUX29;
22459  case MA_CHANNEL_31: return MA_PA_CHANNEL_POSITION_AUX30;
22460  case MA_CHANNEL_32: return MA_PA_CHANNEL_POSITION_AUX31;
22461  default: return (ma_pa_channel_position_t)position;
22462  }
22463 }
22464 #endif
22465 
22466 static ma_result ma_wait_for_operation__pulse(ma_context* pContext, ma_pa_operation* pOP)
22467 {
22468  int resultPA;
22469  ma_pa_operation_state_t state;
22470 
22471  MA_ASSERT(pContext != NULL);
22472  MA_ASSERT(pOP != NULL);
22473 
22474  for (;;) {
22475  state = ((ma_pa_operation_get_state_proc)pContext->pulse.pa_operation_get_state)(pOP);
22476  if (state != MA_PA_OPERATION_RUNNING) {
22477  break; /* Done. */
22478  }
22479 
22480  resultPA = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pContext->pulse.pMainLoop, 1, NULL);
22481  if (resultPA < 0) {
22482  return ma_result_from_pulse(resultPA);
22483  }
22484  }
22485 
22486  return MA_SUCCESS;
22487 }
22488 
22489 static ma_result ma_wait_for_operation_and_unref__pulse(ma_context* pContext, ma_pa_operation* pOP)
22490 {
22491  ma_result result;
22492 
22493  if (pOP == NULL) {
22494  return MA_INVALID_ARGS;
22495  }
22496 
22497  result = ma_wait_for_operation__pulse(pContext, pOP);
22498  ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
22499 
22500  return result;
22501 }
22502 
22503 static ma_result ma_context_wait_for_pa_context_to_connect__pulse(ma_context* pContext)
22504 {
22505  int resultPA;
22506  ma_pa_context_state_t state;
22507 
22508  for (;;) {
22509  state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)((ma_pa_context*)pContext->pulse.pPulseContext);
22510  if (state == MA_PA_CONTEXT_READY) {
22511  break; /* Done. */
22512  }
22513 
22514  if (state == MA_PA_CONTEXT_FAILED || state == MA_PA_CONTEXT_TERMINATED) {
22515  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] An error occurred while connecting the PulseAudio context.", MA_ERROR);
22516  }
22517 
22518  resultPA = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pContext->pulse.pMainLoop, 1, NULL);
22519  if (resultPA < 0) {
22520  return ma_result_from_pulse(resultPA);
22521  }
22522  }
22523 
22524  /* Should never get here. */
22525  return MA_SUCCESS;
22526 }
22527 
22528 static ma_result ma_context_wait_for_pa_stream_to_connect__pulse(ma_context* pContext, ma_pa_stream* pStream)
22529 {
22530  int resultPA;
22531  ma_pa_stream_state_t state;
22532 
22533  for (;;) {
22534  state = ((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)(pStream);
22535  if (state == MA_PA_STREAM_READY) {
22536  break; /* Done. */
22537  }
22538 
22539  if (state == MA_PA_STREAM_FAILED || state == MA_PA_STREAM_TERMINATED) {
22540  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] An error occurred while connecting the PulseAudio stream.", MA_ERROR);
22541  }
22542 
22543  resultPA = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pContext->pulse.pMainLoop, 1, NULL);
22544  if (resultPA < 0) {
22545  return ma_result_from_pulse(resultPA);
22546  }
22547  }
22548 
22549  return MA_SUCCESS;
22550 }
22551 
22552 
22553 static void ma_device_sink_info_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
22554 {
22555  ma_pa_sink_info* pInfoOut;
22556 
22557  if (endOfList > 0) {
22558  return;
22559  }
22560 
22561  pInfoOut = (ma_pa_sink_info*)pUserData;
22562  MA_ASSERT(pInfoOut != NULL);
22563 
22564  *pInfoOut = *pInfo;
22565 
22566  (void)pPulseContext; /* Unused. */
22567 }
22568 
22569 static void ma_device_source_info_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
22570 {
22571  ma_pa_source_info* pInfoOut;
22572 
22573  if (endOfList > 0) {
22574  return;
22575  }
22576 
22577  pInfoOut = (ma_pa_source_info*)pUserData;
22578  MA_ASSERT(pInfoOut != NULL);
22579 
22580  *pInfoOut = *pInfo;
22581 
22582  (void)pPulseContext; /* Unused. */
22583 }
22584 
22585 static void ma_device_sink_name_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
22586 {
22587  ma_device* pDevice;
22588 
22589  if (endOfList > 0) {
22590  return;
22591  }
22592 
22593  pDevice = (ma_device*)pUserData;
22594  MA_ASSERT(pDevice != NULL);
22595 
22596  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), pInfo->description, (size_t)-1);
22597 
22598  (void)pPulseContext; /* Unused. */
22599 }
22600 
22601 static void ma_device_source_name_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
22602 {
22603  ma_device* pDevice;
22604 
22605  if (endOfList > 0) {
22606  return;
22607  }
22608 
22609  pDevice = (ma_device*)pUserData;
22610  MA_ASSERT(pDevice != NULL);
22611 
22612  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), pInfo->description, (size_t)-1);
22613 
22614  (void)pPulseContext; /* Unused. */
22615 }
22616 
22617 
22618 static ma_result ma_context_get_sink_info__pulse(ma_context* pContext, const char* pDeviceName, ma_pa_sink_info* pSinkInfo)
22619 {
22620  ma_pa_operation* pOP;
22621 
22622  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);
22623  if (pOP == NULL) {
22624  return MA_ERROR;
22625  }
22626 
22627  return ma_wait_for_operation_and_unref__pulse(pContext, pOP);
22628 }
22629 
22630 static ma_result ma_context_get_source_info__pulse(ma_context* pContext, const char* pDeviceName, ma_pa_source_info* pSourceInfo)
22631 {
22632  ma_pa_operation* pOP;
22633 
22634  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);
22635  if (pOP == NULL) {
22636  return MA_ERROR;
22637  }
22638 
22639  return ma_wait_for_operation_and_unref__pulse(pContext, pOP);;
22640 }
22641 
22642 static ma_result ma_context_get_default_device_index__pulse(ma_context* pContext, ma_device_type deviceType, ma_uint32* pIndex)
22643 {
22644  ma_result result;
22645 
22646  MA_ASSERT(pContext != NULL);
22647  MA_ASSERT(pIndex != NULL);
22648 
22649  if (pIndex != NULL) {
22650  *pIndex = (ma_uint32)-1;
22651  }
22652 
22653  if (deviceType == ma_device_type_playback) {
22654  ma_pa_sink_info sinkInfo;
22655  result = ma_context_get_sink_info__pulse(pContext, NULL, &sinkInfo);
22656  if (result != MA_SUCCESS) {
22657  return result;
22658  }
22659 
22660  if (pIndex != NULL) {
22661  *pIndex = sinkInfo.index;
22662  }
22663  }
22664 
22665  if (deviceType == ma_device_type_capture) {
22666  ma_pa_source_info sourceInfo;
22667  result = ma_context_get_source_info__pulse(pContext, NULL, &sourceInfo);
22668  if (result != MA_SUCCESS) {
22669  return result;
22670  }
22671 
22672  if (pIndex != NULL) {
22673  *pIndex = sourceInfo.index;
22674  }
22675  }
22676 
22677  return MA_SUCCESS;
22678 }
22679 
22680 
22681 typedef struct
22682 {
22683  ma_context* pContext;
22685  void* pUserData;
22686  ma_bool32 isTerminated;
22687  ma_uint32 defaultDeviceIndexPlayback;
22688  ma_uint32 defaultDeviceIndexCapture;
22689 } ma_context_enumerate_devices_callback_data__pulse;
22690 
22691 static void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_sink_info* pSinkInfo, int endOfList, void* pUserData)
22692 {
22693  ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
22694  ma_device_info deviceInfo;
22695 
22696  MA_ASSERT(pData != NULL);
22697 
22698  if (endOfList || pData->isTerminated) {
22699  return;
22700  }
22701 
22702  MA_ZERO_OBJECT(&deviceInfo);
22703 
22704  /* The name from PulseAudio is the ID for miniaudio. */
22705  if (pSinkInfo->name != NULL) {
22706  ma_strncpy_s(deviceInfo.id.pulse, sizeof(deviceInfo.id.pulse), pSinkInfo->name, (size_t)-1);
22707  }
22708 
22709  /* The description from PulseAudio is the name for miniaudio. */
22710  if (pSinkInfo->description != NULL) {
22711  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSinkInfo->description, (size_t)-1);
22712  }
22713 
22714  if (pSinkInfo->index == pData->defaultDeviceIndexPlayback) {
22715  deviceInfo.isDefault = MA_TRUE;
22716  }
22717 
22718  pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_playback, &deviceInfo, pData->pUserData);
22719 
22720  (void)pPulseContext; /* Unused. */
22721 }
22722 
22723 static void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_source_info* pSourceInfo, int endOfList, void* pUserData)
22724 {
22725  ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
22726  ma_device_info deviceInfo;
22727 
22728  MA_ASSERT(pData != NULL);
22729 
22730  if (endOfList || pData->isTerminated) {
22731  return;
22732  }
22733 
22734  MA_ZERO_OBJECT(&deviceInfo);
22735 
22736  /* The name from PulseAudio is the ID for miniaudio. */
22737  if (pSourceInfo->name != NULL) {
22738  ma_strncpy_s(deviceInfo.id.pulse, sizeof(deviceInfo.id.pulse), pSourceInfo->name, (size_t)-1);
22739  }
22740 
22741  /* The description from PulseAudio is the name for miniaudio. */
22742  if (pSourceInfo->description != NULL) {
22743  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSourceInfo->description, (size_t)-1);
22744  }
22745 
22746  if (pSourceInfo->index == pData->defaultDeviceIndexCapture) {
22747  deviceInfo.isDefault = MA_TRUE;
22748  }
22749 
22750  pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_capture, &deviceInfo, pData->pUserData);
22751 
22752  (void)pPulseContext; /* Unused. */
22753 }
22754 
22755 static ma_result ma_context_enumerate_devices__pulse(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
22756 {
22757  ma_result result = MA_SUCCESS;
22758  ma_context_enumerate_devices_callback_data__pulse callbackData;
22759  ma_pa_operation* pOP = NULL;
22760 
22761  MA_ASSERT(pContext != NULL);
22762  MA_ASSERT(callback != NULL);
22763 
22764  callbackData.pContext = pContext;
22765  callbackData.callback = callback;
22766  callbackData.pUserData = pUserData;
22767  callbackData.isTerminated = MA_FALSE;
22768  callbackData.defaultDeviceIndexPlayback = (ma_uint32)-1;
22769  callbackData.defaultDeviceIndexCapture = (ma_uint32)-1;
22770 
22771  /* We need to get the index of the default devices. */
22772  ma_context_get_default_device_index__pulse(pContext, ma_device_type_playback, &callbackData.defaultDeviceIndexPlayback);
22773  ma_context_get_default_device_index__pulse(pContext, ma_device_type_capture, &callbackData.defaultDeviceIndexCapture);
22774 
22775  /* Playback. */
22776  if (!callbackData.isTerminated) {
22777  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);
22778  if (pOP == NULL) {
22779  result = MA_ERROR;
22780  goto done;
22781  }
22782 
22783  result = ma_wait_for_operation__pulse(pContext, pOP);
22784  ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
22785 
22786  if (result != MA_SUCCESS) {
22787  goto done;
22788  }
22789  }
22790 
22791 
22792  /* Capture. */
22793  if (!callbackData.isTerminated) {
22794  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);
22795  if (pOP == NULL) {
22796  result = MA_ERROR;
22797  goto done;
22798  }
22799 
22800  result = ma_wait_for_operation__pulse(pContext, pOP);
22801  ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
22802 
22803  if (result != MA_SUCCESS) {
22804  goto done;
22805  }
22806  }
22807 
22808 done:
22809  return result;
22810 }
22811 
22812 
22813 typedef struct
22814 {
22815  ma_device_info* pDeviceInfo;
22816  ma_uint32 defaultDeviceIndex;
22817  ma_bool32 foundDevice;
22818 } ma_context_get_device_info_callback_data__pulse;
22819 
22820 static void ma_context_get_device_info_sink_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
22821 {
22822  ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
22823 
22824  if (endOfList > 0) {
22825  return;
22826  }
22827 
22828  MA_ASSERT(pData != NULL);
22829  pData->foundDevice = MA_TRUE;
22830 
22831  if (pInfo->name != NULL) {
22832  ma_strncpy_s(pData->pDeviceInfo->id.pulse, sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (size_t)-1);
22833  }
22834 
22835  if (pInfo->description != NULL) {
22836  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pInfo->description, (size_t)-1);
22837  }
22838 
22839  /*
22840  We're just reporting a single data format here. I think technically PulseAudio might support
22841  all formats, but I don't trust that PulseAudio will do *anything* right, so I'm just going to
22842  report the "native" device format.
22843  */
22844  pData->pDeviceInfo->nativeDataFormats[0].format = ma_format_from_pulse(pInfo->sample_spec.format);
22845  pData->pDeviceInfo->nativeDataFormats[0].channels = pInfo->sample_spec.channels;
22846  pData->pDeviceInfo->nativeDataFormats[0].sampleRate = pInfo->sample_spec.rate;
22847  pData->pDeviceInfo->nativeDataFormats[0].flags = 0;
22848  pData->pDeviceInfo->nativeDataFormatCount = 1;
22849 
22850  if (pData->defaultDeviceIndex == pInfo->index) {
22851  pData->pDeviceInfo->isDefault = MA_TRUE;
22852  }
22853 
22854  (void)pPulseContext; /* Unused. */
22855 }
22856 
22857 static void ma_context_get_device_info_source_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
22858 {
22859  ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
22860 
22861  if (endOfList > 0) {
22862  return;
22863  }
22864 
22865  MA_ASSERT(pData != NULL);
22866  pData->foundDevice = MA_TRUE;
22867 
22868  if (pInfo->name != NULL) {
22869  ma_strncpy_s(pData->pDeviceInfo->id.pulse, sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (size_t)-1);
22870  }
22871 
22872  if (pInfo->description != NULL) {
22873  ma_strncpy_s(pData->pDeviceInfo->name, sizeof(pData->pDeviceInfo->name), pInfo->description, (size_t)-1);
22874  }
22875 
22876  /*
22877  We're just reporting a single data format here. I think technically PulseAudio might support
22878  all formats, but I don't trust that PulseAudio will do *anything* right, so I'm just going to
22879  report the "native" device format.
22880  */
22881  pData->pDeviceInfo->nativeDataFormats[0].format = ma_format_from_pulse(pInfo->sample_spec.format);
22882  pData->pDeviceInfo->nativeDataFormats[0].channels = pInfo->sample_spec.channels;
22883  pData->pDeviceInfo->nativeDataFormats[0].sampleRate = pInfo->sample_spec.rate;
22884  pData->pDeviceInfo->nativeDataFormats[0].flags = 0;
22885  pData->pDeviceInfo->nativeDataFormatCount = 1;
22886 
22887  if (pData->defaultDeviceIndex == pInfo->index) {
22888  pData->pDeviceInfo->isDefault = MA_TRUE;
22889  }
22890 
22891  (void)pPulseContext; /* Unused. */
22892 }
22893 
22894 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)
22895 {
22896  ma_result result = MA_SUCCESS;
22897  ma_context_get_device_info_callback_data__pulse callbackData;
22898  ma_pa_operation* pOP = NULL;
22899  const char* pDeviceName = NULL;
22900 
22901  MA_ASSERT(pContext != NULL);
22902 
22903  callbackData.pDeviceInfo = pDeviceInfo;
22904  callbackData.foundDevice = MA_FALSE;
22905 
22906  if (pDeviceID != NULL) {
22907  pDeviceName = pDeviceID->pulse;
22908  } else {
22909  pDeviceName = NULL;
22910  }
22911 
22912  result = ma_context_get_default_device_index__pulse(pContext, deviceType, &callbackData.defaultDeviceIndex);
22913 
22914  if (deviceType == ma_device_type_playback) {
22915  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);
22916  } else {
22917  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);
22918  }
22919 
22920  if (pOP != NULL) {
22921  ma_wait_for_operation_and_unref__pulse(pContext, pOP);
22922  } else {
22923  result = MA_ERROR;
22924  goto done;
22925  }
22926 
22927  if (!callbackData.foundDevice) {
22928  result = MA_NO_DEVICE;
22929  goto done;
22930  }
22931 
22932 done:
22933  return result;
22934 }
22935 
22936 static ma_result ma_device_uninit__pulse(ma_device* pDevice)
22937 {
22938  ma_context* pContext;
22939 
22940  MA_ASSERT(pDevice != NULL);
22941 
22942  pContext = pDevice->pContext;
22943  MA_ASSERT(pContext != NULL);
22944 
22945  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
22946  ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
22947  ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
22948  }
22949 
22950  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
22951  ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
22952  ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
22953  }
22954 
22955  if (pDevice->type == ma_device_type_duplex) {
22956  ma_duplex_rb_uninit(&pDevice->duplexRB);
22957  }
22958 
22959  return MA_SUCCESS;
22960 }
22961 
22962 static ma_pa_buffer_attr ma_device__pa_buffer_attr_new(ma_uint32 periodSizeInFrames, ma_uint32 periods, const ma_pa_sample_spec* ss)
22963 {
22964  ma_pa_buffer_attr attr;
22965  attr.maxlength = periodSizeInFrames * periods * ma_get_bytes_per_frame(ma_format_from_pulse(ss->format), ss->channels);
22966  attr.tlength = attr.maxlength / periods;
22967  attr.prebuf = (ma_uint32)-1;
22968  attr.minreq = (ma_uint32)-1;
22969  attr.fragsize = attr.maxlength / periods;
22970 
22971  return attr;
22972 }
22973 
22974 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)
22975 {
22976  static int g_StreamCounter = 0;
22977  char actualStreamName[256];
22978 
22979  if (pStreamName != NULL) {
22980  ma_strncpy_s(actualStreamName, sizeof(actualStreamName), pStreamName, (size_t)-1);
22981  } else {
22982  ma_strcpy_s(actualStreamName, sizeof(actualStreamName), "miniaudio:");
22983  ma_itoa_s(g_StreamCounter, actualStreamName + 8, sizeof(actualStreamName)-8, 10); /* 8 = strlen("miniaudio:") */
22984  }
22985  g_StreamCounter += 1;
22986 
22987  return ((ma_pa_stream_new_proc)pContext->pulse.pa_stream_new)((ma_pa_context*)pContext->pulse.pPulseContext, actualStreamName, ss, cmap);
22988 }
22989 
22990 
22991 static void ma_device_on_read__pulse(ma_pa_stream* pStream, size_t byteCount, void* pUserData)
22992 {
22993  ma_device* pDevice = (ma_device*)pUserData;
22994  ma_uint32 bpf;
22995  ma_uint32 deviceState;
22996  ma_uint64 frameCount;
22997  ma_uint64 framesProcessed;
22998 
22999  MA_ASSERT(pDevice != NULL);
23000 
23001  /*
23002  Don't do anything if the device isn't initialized yet. Yes, this can happen because PulseAudio
23003  can fire this callback before the stream has even started. Ridiculous.
23004  */
23005  deviceState = ma_device_get_state(pDevice);
23006  if (deviceState != MA_STATE_STARTING && deviceState != MA_STATE_STARTED) {
23007  return;
23008  }
23009 
23011  MA_ASSERT(bpf > 0);
23012 
23013  frameCount = byteCount / bpf;
23014  framesProcessed = 0;
23015 
23016  while (ma_device_get_state(pDevice) == MA_STATE_STARTED && framesProcessed < frameCount) {
23017  const void* pMappedPCMFrames;
23018  size_t bytesMapped;
23019  ma_uint64 framesMapped;
23020 
23021  int pulseResult = ((ma_pa_stream_peek_proc)pDevice->pContext->pulse.pa_stream_peek)(pStream, &pMappedPCMFrames, &bytesMapped);
23022  if (pulseResult < 0) {
23023  break; /* Failed to map. Abort. */
23024  }
23025 
23026  framesMapped = bytesMapped / bpf;
23027  if (framesMapped > 0) {
23028  if (pMappedPCMFrames != NULL) {
23029  ma_device_handle_backend_data_callback(pDevice, NULL, pMappedPCMFrames, framesMapped);
23030  } else {
23031  /* It's a hole. */
23032  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] ma_device_on_read__pulse: Hole.\n");
23033  }
23034 
23035  pulseResult = ((ma_pa_stream_drop_proc)pDevice->pContext->pulse.pa_stream_drop)(pStream);
23036  if (pulseResult < 0) {
23037  break; /* Failed to drop the buffer. */
23038  }
23039 
23040  framesProcessed += framesMapped;
23041 
23042  } else {
23043  /* Nothing was mapped. Just abort. */
23044  break;
23045  }
23046  }
23047 }
23048 
23049 static ma_result ma_device_write_to_stream__pulse(ma_device* pDevice, ma_pa_stream* pStream, ma_uint64* pFramesProcessed)
23050 {
23051  ma_result result = MA_SUCCESS;
23052  ma_uint64 framesProcessed = 0;
23053  size_t bytesMapped;
23054  ma_uint32 bpf;
23055  ma_uint32 deviceState;
23056 
23057  MA_ASSERT(pDevice != NULL);
23058  MA_ASSERT(pStream != NULL);
23059 
23061  MA_ASSERT(bpf > 0);
23062 
23063  deviceState = ma_device_get_state(pDevice);
23064 
23065  bytesMapped = ((ma_pa_stream_writable_size_proc)pDevice->pContext->pulse.pa_stream_writable_size)(pStream);
23066  if (bytesMapped != (size_t)-1) {
23067  if (bytesMapped > 0) {
23068  ma_uint64 framesMapped;
23069  void* pMappedPCMFrames;
23070  int pulseResult = ((ma_pa_stream_begin_write_proc)pDevice->pContext->pulse.pa_stream_begin_write)(pStream, &pMappedPCMFrames, &bytesMapped);
23071  if (pulseResult < 0) {
23072  result = ma_result_from_pulse(pulseResult);
23073  goto done;
23074  }
23075 
23076  framesMapped = bytesMapped / bpf;
23077 
23078  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. */
23079  ma_device_handle_backend_data_callback(pDevice, pMappedPCMFrames, NULL, framesMapped);
23080  } else {
23081  /* Device is not started. Write silence. */
23082  ma_silence_pcm_frames(pMappedPCMFrames, framesMapped, pDevice->playback.format, pDevice->playback.channels);
23083  }
23084 
23085  pulseResult = ((ma_pa_stream_write_proc)pDevice->pContext->pulse.pa_stream_write)(pStream, pMappedPCMFrames, bytesMapped, NULL, 0, MA_PA_SEEK_RELATIVE);
23086  if (pulseResult < 0) {
23087  result = ma_result_from_pulse(pulseResult);
23088  goto done; /* Failed to write data to stream. */
23089  }
23090 
23091  framesProcessed += framesMapped;
23092  } else {
23093  result = MA_ERROR; /* No data available. Abort. */
23094  goto done;
23095  }
23096  } else {
23097  result = MA_ERROR; /* Failed to retrieve the writable size. Abort. */
23098  goto done;
23099  }
23100 
23101 done:
23102  if (pFramesProcessed != NULL) {
23103  *pFramesProcessed = framesProcessed;
23104  }
23105 
23106  return result;
23107 }
23108 
23109 static void ma_device_on_write__pulse(ma_pa_stream* pStream, size_t byteCount, void* pUserData)
23110 {
23111  ma_device* pDevice = (ma_device*)pUserData;
23112  ma_uint32 bpf;
23113  ma_uint64 frameCount;
23114  ma_uint64 framesProcessed;
23115  ma_uint32 deviceState;
23116  ma_result result;
23117 
23118  MA_ASSERT(pDevice != NULL);
23119 
23120  /*
23121  Don't do anything if the device isn't initialized yet. Yes, this can happen because PulseAudio
23122  can fire this callback before the stream has even started. Ridiculous.
23123  */
23124  deviceState = ma_device_get_state(pDevice);
23125  if (deviceState != MA_STATE_STARTING && deviceState != MA_STATE_STARTED) {
23126  return;
23127  }
23128 
23130  MA_ASSERT(bpf > 0);
23131 
23132  frameCount = byteCount / bpf;
23133  framesProcessed = 0;
23134 
23135  while (framesProcessed < frameCount) {
23136  ma_uint64 framesProcessedThisIteration;
23137 
23138  /* Don't keep trying to process frames if the device isn't started. */
23139  deviceState = ma_device_get_state(pDevice);
23140  if (deviceState != MA_STATE_STARTING && deviceState != MA_STATE_STARTED) {
23141  break;
23142  }
23143 
23144  result = ma_device_write_to_stream__pulse(pDevice, pStream, &framesProcessedThisIteration);
23145  if (result != MA_SUCCESS) {
23146  break;
23147  }
23148 
23149  framesProcessed += framesProcessedThisIteration;
23150  }
23151 }
23152 
23153 static void ma_device_on_suspended__pulse(ma_pa_stream* pStream, void* pUserData)
23154 {
23155  ma_device* pDevice = (ma_device*)pUserData;
23156  int suspended;
23157 
23158  (void)pStream;
23159 
23160  suspended = ((ma_pa_stream_is_suspended_proc)pDevice->pContext->pulse.pa_stream_is_suspended)(pStream);
23161  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);
23162 
23163  if (suspended < 0) {
23164  return;
23165  }
23166 
23167  if (suspended == 1) {
23168  ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[Pulse] Device suspended state changed. Suspended.\n");
23169 
23170  if (pDevice->onStop) {
23171  pDevice->onStop(pDevice);
23172  }
23173  } else {
23174  ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[Pulse] Device suspended state changed. Resumed.\n");
23175  }
23176 }
23177 
23178 static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
23179 {
23180  /*
23181  Notes for PulseAudio:
23182 
23183  - We're always using native format/channels/rate regardless of whether or not PulseAudio
23184  supports the format directly through their own data conversion system. I'm doing this to
23185  reduce as much variability from the PulseAudio side as possible because it's seems to be
23186  extremely unreliable at everything it does.
23187 
23188  - When both the period size in frames and milliseconds are 0, we default to miniaudio's
23189  default buffer sizes rather than leaving it up to PulseAudio because I don't trust
23190  PulseAudio to give us any kind of reasonable latency by default.
23191 
23192  - Do not ever, *ever* forget to use MA_PA_STREAM_ADJUST_LATENCY. If you don't specify this
23193  flag, capture mode will just not work properly until you open another PulseAudio app.
23194  */
23195 
23196  ma_result result = MA_SUCCESS;
23197  int error = 0;
23198  const char* devPlayback = NULL;
23199  const char* devCapture = NULL;
23200  ma_format format = ma_format_unknown;
23201  ma_uint32 channels = 0;
23202  ma_uint32 sampleRate = 0;
23203  ma_pa_sink_info sinkInfo;
23204  ma_pa_source_info sourceInfo;
23205  ma_pa_sample_spec ss;
23206  ma_pa_channel_map cmap;
23207  ma_pa_buffer_attr attr;
23208  const ma_pa_sample_spec* pActualSS = NULL;
23209  const ma_pa_channel_map* pActualCMap = NULL;
23210  const ma_pa_buffer_attr* pActualAttr = NULL;
23211  ma_uint32 iChannel;
23212  ma_pa_stream_flags_t streamFlags;
23213 
23214  MA_ASSERT(pDevice != NULL);
23215  MA_ZERO_OBJECT(&pDevice->pulse);
23216 
23217  if (pConfig->deviceType == ma_device_type_loopback) {
23219  }
23220 
23221  /* No exclusive mode with the PulseAudio backend. */
23225  }
23226 
23227  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
23228  if (pDescriptorPlayback->pDeviceID != NULL) {
23229  devPlayback = pDescriptorPlayback->pDeviceID->pulse;
23230  }
23231 
23232  format = pDescriptorPlayback->format;
23233  channels = pDescriptorPlayback->channels;
23234  sampleRate = pDescriptorPlayback->sampleRate;
23235  }
23236 
23237  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
23238  if (pDescriptorCapture->pDeviceID != NULL) {
23239  devCapture = pDescriptorCapture->pDeviceID->pulse;
23240  }
23241 
23242  format = pDescriptorCapture->format;
23243  channels = pDescriptorCapture->channels;
23244  sampleRate = pDescriptorCapture->sampleRate;
23245  }
23246 
23247  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
23248  result = ma_context_get_source_info__pulse(pDevice->pContext, devCapture, &sourceInfo);
23249  if (result != MA_SUCCESS) {
23250  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve source info for capture device.", result);
23251  goto on_error0;
23252  }
23253 
23254  ss = sourceInfo.sample_spec;
23255  cmap = sourceInfo.channel_map;
23256 
23257  if (ma_format_from_pulse(ss.format) == ma_format_unknown) {
23258  if (ma_is_little_endian()) {
23259  ss.format = MA_PA_SAMPLE_FLOAT32LE;
23260  } else {
23261  ss.format = MA_PA_SAMPLE_FLOAT32BE;
23262  }
23263  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");
23264  }
23265  if (ss.rate == 0) {
23266  ss.rate = MA_DEFAULT_SAMPLE_RATE;
23267  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.rate = 0. Defaulting to %d\n", ss.rate);
23268  }
23269  if (ss.channels == 0) {
23270  ss.channels = MA_DEFAULT_CHANNELS;
23271  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.channels = 0. Defaulting to %d\n", ss.channels);
23272  }
23273 
23274  /* We now have enough information to calculate our actual period size in frames. */
23275  pDescriptorCapture->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorCapture, ss.rate, pConfig->performanceProfile);
23276 
23277  attr = ma_device__pa_buffer_attr_new(pDescriptorCapture->periodSizeInFrames, pDescriptorCapture->periodCount, &ss);
23278  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);
23279 
23280  pDevice->pulse.pStreamCapture = ma_context__pa_stream_new__pulse(pDevice->pContext, pConfig->pulse.pStreamNameCapture, &ss, &cmap);
23281  if (pDevice->pulse.pStreamCapture == NULL) {
23282  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio capture stream.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
23283  goto on_error0;
23284  }
23285 
23286 
23287  /* The callback needs to be set before connecting the stream. */
23288  ((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);
23289 
23290  /* State callback for checking when the device has been corked. */
23291  ((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);
23292 
23293 
23294  /* Connect after we've got all of our internal state set up. */
23295  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;
23296  if (devCapture != NULL) {
23297  streamFlags |= MA_PA_STREAM_DONT_MOVE;
23298  }
23299 
23300  error = ((ma_pa_stream_connect_record_proc)pDevice->pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
23301  if (error != MA_PA_OK) {
23302  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio capture stream.", ma_result_from_pulse(error));
23303  goto on_error1;
23304  }
23305 
23306  result = ma_context_wait_for_pa_stream_to_connect__pulse(pDevice->pContext, (ma_pa_stream*)pDevice->pulse.pStreamCapture);
23307  if (result != MA_SUCCESS) {
23308  goto on_error2;
23309  }
23310 
23311  /* Internal format. */
23312  pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
23313  if (pActualSS != NULL) {
23314  ss = *pActualSS;
23315  }
23316 
23317  pDescriptorCapture->format = ma_format_from_pulse(ss.format);
23318  pDescriptorCapture->channels = ss.channels;
23319  pDescriptorCapture->sampleRate = ss.rate;
23320 
23321  /* Internal channel map. */
23322  pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
23323  if (pActualCMap != NULL) {
23324  cmap = *pActualCMap;
23325  }
23326 
23327  for (iChannel = 0; iChannel < pDescriptorCapture->channels; ++iChannel) {
23328  pDescriptorCapture->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
23329  }
23330 
23331 
23332  /* Buffer. */
23333  pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pDevice->pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
23334  if (pActualAttr != NULL) {
23335  attr = *pActualAttr;
23336  }
23337 
23338  pDescriptorCapture->periodCount = attr.maxlength / attr.fragsize;
23339  pDescriptorCapture->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) / pDescriptorCapture->periodCount;
23340 
23341  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);
23342 
23343 
23344  /* Name. */
23345  devCapture = ((ma_pa_stream_get_device_name_proc)pDevice->pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
23346  if (devCapture != NULL) {
23347  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);
23348  ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
23349  }
23350  }
23351 
23352  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
23353  result = ma_context_get_sink_info__pulse(pDevice->pContext, devPlayback, &sinkInfo);
23354  if (result != MA_SUCCESS) {
23355  ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve sink info for playback device.", result);
23356  goto on_error2;
23357  }
23358 
23359  ss = sinkInfo.sample_spec;
23360  cmap = sinkInfo.channel_map;
23361 
23362  if (ma_format_from_pulse(ss.format) == ma_format_unknown) {
23363  if (ma_is_little_endian()) {
23364  ss.format = MA_PA_SAMPLE_FLOAT32LE;
23365  } else {
23366  ss.format = MA_PA_SAMPLE_FLOAT32BE;
23367  }
23368  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");
23369  }
23370  if (ss.rate == 0) {
23371  ss.rate = MA_DEFAULT_SAMPLE_RATE;
23372  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.rate = 0. Defaulting to %d\n", ss.rate);
23373  }
23374  if (ss.channels == 0) {
23375  ss.channels = MA_DEFAULT_CHANNELS;
23376  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.channels = 0. Defaulting to %d\n", ss.channels);
23377  }
23378 
23379  /* We now have enough information to calculate the actual buffer size in frames. */
23380  pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, ss.rate, pConfig->performanceProfile);
23381 
23382  attr = ma_device__pa_buffer_attr_new(pDescriptorPlayback->periodSizeInFrames, pDescriptorPlayback->periodCount, &ss);
23383 
23384  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);
23385 
23386  pDevice->pulse.pStreamPlayback = ma_context__pa_stream_new__pulse(pDevice->pContext, pConfig->pulse.pStreamNamePlayback, &ss, &cmap);
23387  if (pDevice->pulse.pStreamPlayback == NULL) {
23388  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio playback stream.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
23389  goto on_error2;
23390  }
23391 
23392 
23393  /*
23394  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
23395  device state of MA_STATE_UNINITIALIZED.
23396  */
23397  ((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);
23398 
23399  /* State callback for checking when the device has been corked. */
23400  ((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);
23401 
23402 
23403  /* Connect after we've got all of our internal state set up. */
23404  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;
23405  if (devPlayback != NULL) {
23406  streamFlags |= MA_PA_STREAM_DONT_MOVE;
23407  }
23408 
23409  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);
23410  if (error != MA_PA_OK) {
23411  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio playback stream.", ma_result_from_pulse(error));
23412  goto on_error3;
23413  }
23414 
23415  result = ma_context_wait_for_pa_stream_to_connect__pulse(pDevice->pContext, (ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23416  if (result != MA_SUCCESS) {
23417  goto on_error3;
23418  }
23419 
23420 
23421  /* Internal format. */
23422  pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23423  if (pActualSS != NULL) {
23424  ss = *pActualSS;
23425  }
23426 
23427  pDescriptorPlayback->format = ma_format_from_pulse(ss.format);
23428  pDescriptorPlayback->channels = ss.channels;
23429  pDescriptorPlayback->sampleRate = ss.rate;
23430 
23431  /* Internal channel map. */
23432  pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23433  if (pActualCMap != NULL) {
23434  cmap = *pActualCMap;
23435  }
23436 
23437  for (iChannel = 0; iChannel < pDescriptorPlayback->channels; ++iChannel) {
23438  pDescriptorPlayback->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
23439  }
23440 
23441 
23442  /* Buffer. */
23443  pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pDevice->pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23444  if (pActualAttr != NULL) {
23445  attr = *pActualAttr;
23446  }
23447 
23448  pDescriptorPlayback->periodCount = attr.maxlength / attr.tlength;
23449  pDescriptorPlayback->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) / pDescriptorPlayback->periodCount;
23450  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);
23451 
23452 
23453  /* Name. */
23454  devPlayback = ((ma_pa_stream_get_device_name_proc)pDevice->pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23455  if (devPlayback != NULL) {
23456  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);
23457  ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
23458  }
23459  }
23460 
23461 
23462  /*
23463  We need a ring buffer for handling duplex mode. We can use the main duplex ring buffer in the main
23464  part of the ma_device struct. We cannot, however, depend on ma_device_init() initializing this for
23465  us later on because that will only do it if it's a fully asynchronous backend - i.e. the
23466  onDeviceDataLoop callback is NULL, which is not the case for PulseAudio.
23467  */
23468  if (pConfig->deviceType == ma_device_type_duplex) {
23469  result = ma_duplex_rb_init(format, channels, sampleRate, pDescriptorCapture->sampleRate, pDescriptorCapture->periodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->duplexRB);
23470  if (result != MA_SUCCESS) {
23471  result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to initialize ring buffer.", result);
23472  goto on_error4;
23473  }
23474  }
23475 
23476  return MA_SUCCESS;
23477 
23478 
23479 on_error4:
23480  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
23481  ((ma_pa_stream_disconnect_proc)pDevice->pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23482  }
23483 on_error3:
23484  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
23485  ((ma_pa_stream_unref_proc)pDevice->pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
23486  }
23487 on_error2:
23488  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
23489  ((ma_pa_stream_disconnect_proc)pDevice->pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
23490  }
23491 on_error1:
23492  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
23493  ((ma_pa_stream_unref_proc)pDevice->pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
23494  }
23495 on_error0:
23496  return result;
23497 }
23498 
23499 
23500 static void ma_pulse_operation_complete_callback(ma_pa_stream* pStream, int success, void* pUserData)
23501 {
23502  ma_bool32* pIsSuccessful = (ma_bool32*)pUserData;
23503  MA_ASSERT(pIsSuccessful != NULL);
23504 
23505  *pIsSuccessful = (ma_bool32)success;
23506 
23507  (void)pStream; /* Unused. */
23508 }
23509 
23510 static ma_result ma_device__cork_stream__pulse(ma_device* pDevice, ma_device_type deviceType, int cork)
23511 {
23512  ma_context* pContext = pDevice->pContext;
23513  ma_bool32 wasSuccessful;
23514  ma_pa_stream* pStream;
23515  ma_pa_operation* pOP;
23516  ma_result result;
23517 
23518  /* This should not be called with a duplex device type. */
23519  if (deviceType == ma_device_type_duplex) {
23520  return MA_INVALID_ARGS;
23521  }
23522 
23523  wasSuccessful = MA_FALSE;
23524 
23525  pStream = (ma_pa_stream*)((deviceType == ma_device_type_capture) ? pDevice->pulse.pStreamCapture : pDevice->pulse.pStreamPlayback);
23526  MA_ASSERT(pStream != NULL);
23527 
23528  pOP = ((ma_pa_stream_cork_proc)pContext->pulse.pa_stream_cork)(pStream, cork, ma_pulse_operation_complete_callback, &wasSuccessful);
23529  if (pOP == NULL) {
23530  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);
23531  }
23532 
23533  result = ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
23534  if (result != MA_SUCCESS) {
23535  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] An error occurred while waiting for the PulseAudio stream to cork.", result);
23536  }
23537 
23538  if (!wasSuccessful) {
23539  if (cork) {
23540  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to stop PulseAudio stream.", MA_FAILED_TO_STOP_BACKEND_DEVICE);
23541  } else {
23542  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to start PulseAudio stream.", MA_FAILED_TO_START_BACKEND_DEVICE);
23543  }
23544  }
23545 
23546  return MA_SUCCESS;
23547 }
23548 
23549 static ma_result ma_device_start__pulse(ma_device* pDevice)
23550 {
23551  ma_result result;
23552 
23553  MA_ASSERT(pDevice != NULL);
23554 
23555  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
23556  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_capture, 0);
23557  if (result != MA_SUCCESS) {
23558  return result;
23559  }
23560  }
23561 
23562  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
23563  /* We need to fill some data before uncorking. Not doing this will result in the write callback never getting fired. */
23564  result = ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL);
23565  if (result != MA_SUCCESS) {
23566  return result; /* Failed to write data. Not sure what to do here... Just aborting. */
23567  }
23568 
23569  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 0);
23570  if (result != MA_SUCCESS) {
23571  return result;
23572  }
23573  }
23574 
23575  return MA_SUCCESS;
23576 }
23577 
23578 static ma_result ma_device_stop__pulse(ma_device* pDevice)
23579 {
23580  ma_result result;
23581  ma_bool32 wasSuccessful;
23582 
23583  MA_ASSERT(pDevice != NULL);
23584 
23585  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
23586  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_capture, 1);
23587  if (result != MA_SUCCESS) {
23588  return result;
23589  }
23590  }
23591 
23592  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
23593  /* The stream needs to be drained if it's a playback device. */
23594  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);
23595  ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
23596 
23597  result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 1);
23598  if (result != MA_SUCCESS) {
23599  return result;
23600  }
23601  }
23602 
23603  return MA_SUCCESS;
23604 }
23605 
23606 static ma_result ma_device_data_loop__pulse(ma_device* pDevice)
23607 {
23608  int resultPA;
23609 
23610  MA_ASSERT(pDevice != NULL);
23611 
23612  /* NOTE: Don't start the device here. It'll be done at a higher level. */
23613 
23614  /*
23615  All data is handled through callbacks. All we need to do is iterate over the main loop and let
23616  the callbacks deal with it.
23617  */
23618  while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
23619  resultPA = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pContext->pulse.pMainLoop, 1, NULL);
23620  if (resultPA < 0) {
23621  break;
23622  }
23623  }
23624 
23625  /* NOTE: Don't stop the device here. It'll be done at a higher level. */
23626  return MA_SUCCESS;
23627 }
23628 
23629 static ma_result ma_device_data_loop_wakeup__pulse(ma_device* pDevice)
23630 {
23631  MA_ASSERT(pDevice != NULL);
23632 
23633  ((ma_pa_mainloop_wakeup_proc)pDevice->pContext->pulse.pa_mainloop_wakeup)((ma_pa_mainloop*)pDevice->pContext->pulse.pMainLoop);
23634 
23635  return MA_SUCCESS;
23636 }
23637 
23638 static ma_result ma_context_uninit__pulse(ma_context* pContext)
23639 {
23640  MA_ASSERT(pContext != NULL);
23641  MA_ASSERT(pContext->backend == ma_backend_pulseaudio);
23642 
23643  ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pContext->pulse.pPulseContext);
23644  ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pContext->pulse.pPulseContext);
23645  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pContext->pulse.pMainLoop);
23646 
23647 #ifndef MA_NO_RUNTIME_LINKING
23648  ma_dlclose(pContext, pContext->pulse.pulseSO);
23649 #endif
23650 
23651  return MA_SUCCESS;
23652 }
23653 
23654 static ma_result ma_context_init__pulse(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
23655 {
23656  ma_result result;
23657 #ifndef MA_NO_RUNTIME_LINKING
23658  const char* libpulseNames[] = {
23659  "libpulse.so",
23660  "libpulse.so.0"
23661  };
23662  size_t i;
23663 
23664  for (i = 0; i < ma_countof(libpulseNames); ++i) {
23665  pContext->pulse.pulseSO = ma_dlopen(pContext, libpulseNames[i]);
23666  if (pContext->pulse.pulseSO != NULL) {
23667  break;
23668  }
23669  }
23670 
23671  if (pContext->pulse.pulseSO == NULL) {
23672  return MA_NO_BACKEND;
23673  }
23674 
23675  pContext->pulse.pa_mainloop_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_new");
23676  pContext->pulse.pa_mainloop_free = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_free");
23677  pContext->pulse.pa_mainloop_quit = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_quit");
23678  pContext->pulse.pa_mainloop_get_api = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_get_api");
23679  pContext->pulse.pa_mainloop_iterate = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_iterate");
23680  pContext->pulse.pa_mainloop_wakeup = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_wakeup");
23681  pContext->pulse.pa_threaded_mainloop_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_new");
23682  pContext->pulse.pa_threaded_mainloop_free = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_free");
23683  pContext->pulse.pa_threaded_mainloop_start = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_start");
23684  pContext->pulse.pa_threaded_mainloop_stop = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_stop");
23685  pContext->pulse.pa_threaded_mainloop_lock = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_lock");
23686  pContext->pulse.pa_threaded_mainloop_unlock = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_unlock");
23687  pContext->pulse.pa_threaded_mainloop_wait = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_wait");
23688  pContext->pulse.pa_threaded_mainloop_signal = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_signal");
23689  pContext->pulse.pa_threaded_mainloop_accept = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_accept");
23690  pContext->pulse.pa_threaded_mainloop_get_retval = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_get_retval");
23691  pContext->pulse.pa_threaded_mainloop_get_api = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_get_api");
23692  pContext->pulse.pa_threaded_mainloop_in_thread = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_in_thread");
23693  pContext->pulse.pa_threaded_mainloop_set_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_set_name");
23694  pContext->pulse.pa_context_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_new");
23695  pContext->pulse.pa_context_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_unref");
23696  pContext->pulse.pa_context_connect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_connect");
23697  pContext->pulse.pa_context_disconnect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_disconnect");
23698  pContext->pulse.pa_context_set_state_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_set_state_callback");
23699  pContext->pulse.pa_context_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_state");
23700  pContext->pulse.pa_context_get_sink_info_list = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_sink_info_list");
23701  pContext->pulse.pa_context_get_source_info_list = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_source_info_list");
23702  pContext->pulse.pa_context_get_sink_info_by_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_sink_info_by_name");
23703  pContext->pulse.pa_context_get_source_info_by_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_source_info_by_name");
23704  pContext->pulse.pa_operation_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_operation_unref");
23705  pContext->pulse.pa_operation_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_operation_get_state");
23706  pContext->pulse.pa_channel_map_init_extend = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_init_extend");
23707  pContext->pulse.pa_channel_map_valid = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_valid");
23708  pContext->pulse.pa_channel_map_compatible = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_compatible");
23709  pContext->pulse.pa_stream_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_new");
23710  pContext->pulse.pa_stream_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_unref");
23711  pContext->pulse.pa_stream_connect_playback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_connect_playback");
23712  pContext->pulse.pa_stream_connect_record = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_connect_record");
23713  pContext->pulse.pa_stream_disconnect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_disconnect");
23714  pContext->pulse.pa_stream_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_state");
23715  pContext->pulse.pa_stream_get_sample_spec = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_sample_spec");
23716  pContext->pulse.pa_stream_get_channel_map = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_channel_map");
23717  pContext->pulse.pa_stream_get_buffer_attr = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_buffer_attr");
23718  pContext->pulse.pa_stream_set_buffer_attr = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_buffer_attr");
23719  pContext->pulse.pa_stream_get_device_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_device_name");
23720  pContext->pulse.pa_stream_set_write_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_write_callback");
23721  pContext->pulse.pa_stream_set_read_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_read_callback");
23722  pContext->pulse.pa_stream_set_suspended_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_set_suspended_callback");
23723  pContext->pulse.pa_stream_is_suspended = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_is_suspended");
23724  pContext->pulse.pa_stream_flush = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_flush");
23725  pContext->pulse.pa_stream_drain = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_drain");
23726  pContext->pulse.pa_stream_is_corked = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_is_corked");
23727  pContext->pulse.pa_stream_cork = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_cork");
23728  pContext->pulse.pa_stream_trigger = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_trigger");
23729  pContext->pulse.pa_stream_begin_write = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_begin_write");
23730  pContext->pulse.pa_stream_write = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_write");
23731  pContext->pulse.pa_stream_peek = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_peek");
23732  pContext->pulse.pa_stream_drop = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_drop");
23733  pContext->pulse.pa_stream_writable_size = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_writable_size");
23734  pContext->pulse.pa_stream_readable_size = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_readable_size");
23735 #else
23736  /* This strange assignment system is just for type safety. */
23737  ma_pa_mainloop_new_proc _pa_mainloop_new = pa_mainloop_new;
23738  ma_pa_mainloop_free_proc _pa_mainloop_free = pa_mainloop_free;
23739  ma_pa_mainloop_quit_proc _pa_mainloop_quit = pa_mainloop_quit;
23740  ma_pa_mainloop_get_api_proc _pa_mainloop_get_api = pa_mainloop_get_api;
23741  ma_pa_mainloop_iterate_proc _pa_mainloop_iterate = pa_mainloop_iterate;
23742  ma_pa_mainloop_wakeup_proc _pa_mainloop_wakeup = pa_mainloop_wakeup;
23743  ma_pa_threaded_mainloop_new_proc _pa_threaded_mainloop_new = pa_threaded_mainloop_new;
23744  ma_pa_threaded_mainloop_free_proc _pa_threaded_mainloop_free = pa_threaded_mainloop_free;
23745  ma_pa_threaded_mainloop_start_proc _pa_threaded_mainloop_start = pa_threaded_mainloop_start;
23746  ma_pa_threaded_mainloop_stop_proc _pa_threaded_mainloop_stop = pa_threaded_mainloop_stop;
23747  ma_pa_threaded_mainloop_lock_proc _pa_threaded_mainloop_lock = pa_threaded_mainloop_lock;
23748  ma_pa_threaded_mainloop_unlock_proc _pa_threaded_mainloop_unlock = pa_threaded_mainloop_unlock;
23749  ma_pa_threaded_mainloop_wait_proc _pa_threaded_mainloop_wait = pa_threaded_mainloop_wait;
23750  ma_pa_threaded_mainloop_signal_proc _pa_threaded_mainloop_signal = pa_threaded_mainloop_signal;
23751  ma_pa_threaded_mainloop_accept_proc _pa_threaded_mainloop_accept = pa_threaded_mainloop_accept;
23752  ma_pa_threaded_mainloop_get_retval_proc _pa_threaded_mainloop_get_retval = pa_threaded_mainloop_get_retval;
23753  ma_pa_threaded_mainloop_get_api_proc _pa_threaded_mainloop_get_api = pa_threaded_mainloop_get_api;
23754  ma_pa_threaded_mainloop_in_thread_proc _pa_threaded_mainloop_in_thread = pa_threaded_mainloop_in_thread;
23755  ma_pa_threaded_mainloop_set_name_proc _pa_threaded_mainloop_set_name = pa_threaded_mainloop_set_name;
23756  ma_pa_context_new_proc _pa_context_new = pa_context_new;
23757  ma_pa_context_unref_proc _pa_context_unref = pa_context_unref;
23758  ma_pa_context_connect_proc _pa_context_connect = pa_context_connect;
23759  ma_pa_context_disconnect_proc _pa_context_disconnect = pa_context_disconnect;
23760  ma_pa_context_set_state_callback_proc _pa_context_set_state_callback = pa_context_set_state_callback;
23761  ma_pa_context_get_state_proc _pa_context_get_state = pa_context_get_state;
23762  ma_pa_context_get_sink_info_list_proc _pa_context_get_sink_info_list = pa_context_get_sink_info_list;
23763  ma_pa_context_get_source_info_list_proc _pa_context_get_source_info_list = pa_context_get_source_info_list;
23764  ma_pa_context_get_sink_info_by_name_proc _pa_context_get_sink_info_by_name = pa_context_get_sink_info_by_name;
23765  ma_pa_context_get_source_info_by_name_proc _pa_context_get_source_info_by_name= pa_context_get_source_info_by_name;
23766  ma_pa_operation_unref_proc _pa_operation_unref = pa_operation_unref;
23767  ma_pa_operation_get_state_proc _pa_operation_get_state = pa_operation_get_state;
23768  ma_pa_channel_map_init_extend_proc _pa_channel_map_init_extend = pa_channel_map_init_extend;
23769  ma_pa_channel_map_valid_proc _pa_channel_map_valid = pa_channel_map_valid;
23770  ma_pa_channel_map_compatible_proc _pa_channel_map_compatible = pa_channel_map_compatible;
23771  ma_pa_stream_new_proc _pa_stream_new = pa_stream_new;
23772  ma_pa_stream_unref_proc _pa_stream_unref = pa_stream_unref;
23773  ma_pa_stream_connect_playback_proc _pa_stream_connect_playback = pa_stream_connect_playback;
23774  ma_pa_stream_connect_record_proc _pa_stream_connect_record = pa_stream_connect_record;
23775  ma_pa_stream_disconnect_proc _pa_stream_disconnect = pa_stream_disconnect;
23776  ma_pa_stream_get_state_proc _pa_stream_get_state = pa_stream_get_state;
23777  ma_pa_stream_get_sample_spec_proc _pa_stream_get_sample_spec = pa_stream_get_sample_spec;
23778  ma_pa_stream_get_channel_map_proc _pa_stream_get_channel_map = pa_stream_get_channel_map;
23779  ma_pa_stream_get_buffer_attr_proc _pa_stream_get_buffer_attr = pa_stream_get_buffer_attr;
23780  ma_pa_stream_set_buffer_attr_proc _pa_stream_set_buffer_attr = pa_stream_set_buffer_attr;
23781  ma_pa_stream_get_device_name_proc _pa_stream_get_device_name = pa_stream_get_device_name;
23782  ma_pa_stream_set_write_callback_proc _pa_stream_set_write_callback = pa_stream_set_write_callback;
23783  ma_pa_stream_set_read_callback_proc _pa_stream_set_read_callback = pa_stream_set_read_callback;
23784  ma_pa_stream_set_suspended_callback_proc _pa_stream_set_suspended_callback = pa_stream_set_suspended_callback;
23785  ma_pa_stream_is_suspended_proc _pa_stream_is_suspended = pa_stream_is_suspended;
23786  ma_pa_stream_flush_proc _pa_stream_flush = pa_stream_flush;
23787  ma_pa_stream_drain_proc _pa_stream_drain = pa_stream_drain;
23788  ma_pa_stream_is_corked_proc _pa_stream_is_corked = pa_stream_is_corked;
23789  ma_pa_stream_cork_proc _pa_stream_cork = pa_stream_cork;
23790  ma_pa_stream_trigger_proc _pa_stream_trigger = pa_stream_trigger;
23791  ma_pa_stream_begin_write_proc _pa_stream_begin_write = pa_stream_begin_write;
23792  ma_pa_stream_write_proc _pa_stream_write = pa_stream_write;
23793  ma_pa_stream_peek_proc _pa_stream_peek = pa_stream_peek;
23794  ma_pa_stream_drop_proc _pa_stream_drop = pa_stream_drop;
23795  ma_pa_stream_writable_size_proc _pa_stream_writable_size = pa_stream_writable_size;
23796  ma_pa_stream_readable_size_proc _pa_stream_readable_size = pa_stream_readable_size;
23797 
23798  pContext->pulse.pa_mainloop_new = (ma_proc)_pa_mainloop_new;
23799  pContext->pulse.pa_mainloop_free = (ma_proc)_pa_mainloop_free;
23800  pContext->pulse.pa_mainloop_quit = (ma_proc)_pa_mainloop_quit;
23801  pContext->pulse.pa_mainloop_get_api = (ma_proc)_pa_mainloop_get_api;
23802  pContext->pulse.pa_mainloop_iterate = (ma_proc)_pa_mainloop_iterate;
23803  pContext->pulse.pa_mainloop_wakeup = (ma_proc)_pa_mainloop_wakeup;
23804  pContext->pulse.pa_threaded_mainloop_new = (ma_proc)_pa_threaded_mainloop_new;
23805  pContext->pulse.pa_threaded_mainloop_free = (ma_proc)_pa_threaded_mainloop_free;
23806  pContext->pulse.pa_threaded_mainloop_start = (ma_proc)_pa_threaded_mainloop_start;
23807  pContext->pulse.pa_threaded_mainloop_stop = (ma_proc)_pa_threaded_mainloop_stop;
23808  pContext->pulse.pa_threaded_mainloop_lock = (ma_proc)_pa_threaded_mainloop_lock;
23809  pContext->pulse.pa_threaded_mainloop_unlock = (ma_proc)_pa_threaded_mainloop_unlock;
23810  pContext->pulse.pa_threaded_mainloop_wait = (ma_proc)_pa_threaded_mainloop_wait;
23811  pContext->pulse.pa_threaded_mainloop_signal = (ma_proc)_pa_threaded_mainloop_signal;
23812  pContext->pulse.pa_threaded_mainloop_accept = (ma_proc)_pa_threaded_mainloop_accept;
23813  pContext->pulse.pa_threaded_mainloop_get_retval = (ma_proc)_pa_threaded_mainloop_get_retval;
23814  pContext->pulse.pa_threaded_mainloop_get_api = (ma_proc)_pa_threaded_mainloop_get_api;
23815  pContext->pulse.pa_threaded_mainloop_in_thread = (ma_proc)_pa_threaded_mainloop_in_thread;
23816  pContext->pulse.pa_threaded_mainloop_set_name = (ma_proc)_pa_threaded_mainloop_set_name;
23817  pContext->pulse.pa_context_new = (ma_proc)_pa_context_new;
23818  pContext->pulse.pa_context_unref = (ma_proc)_pa_context_unref;
23819  pContext->pulse.pa_context_connect = (ma_proc)_pa_context_connect;
23820  pContext->pulse.pa_context_disconnect = (ma_proc)_pa_context_disconnect;
23821  pContext->pulse.pa_context_set_state_callback = (ma_proc)_pa_context_set_state_callback;
23822  pContext->pulse.pa_context_get_state = (ma_proc)_pa_context_get_state;
23823  pContext->pulse.pa_context_get_sink_info_list = (ma_proc)_pa_context_get_sink_info_list;
23824  pContext->pulse.pa_context_get_source_info_list = (ma_proc)_pa_context_get_source_info_list;
23825  pContext->pulse.pa_context_get_sink_info_by_name = (ma_proc)_pa_context_get_sink_info_by_name;
23826  pContext->pulse.pa_context_get_source_info_by_name = (ma_proc)_pa_context_get_source_info_by_name;
23827  pContext->pulse.pa_operation_unref = (ma_proc)_pa_operation_unref;
23828  pContext->pulse.pa_operation_get_state = (ma_proc)_pa_operation_get_state;
23829  pContext->pulse.pa_channel_map_init_extend = (ma_proc)_pa_channel_map_init_extend;
23830  pContext->pulse.pa_channel_map_valid = (ma_proc)_pa_channel_map_valid;
23831  pContext->pulse.pa_channel_map_compatible = (ma_proc)_pa_channel_map_compatible;
23832  pContext->pulse.pa_stream_new = (ma_proc)_pa_stream_new;
23833  pContext->pulse.pa_stream_unref = (ma_proc)_pa_stream_unref;
23834  pContext->pulse.pa_stream_connect_playback = (ma_proc)_pa_stream_connect_playback;
23835  pContext->pulse.pa_stream_connect_record = (ma_proc)_pa_stream_connect_record;
23836  pContext->pulse.pa_stream_disconnect = (ma_proc)_pa_stream_disconnect;
23837  pContext->pulse.pa_stream_get_state = (ma_proc)_pa_stream_get_state;
23838  pContext->pulse.pa_stream_get_sample_spec = (ma_proc)_pa_stream_get_sample_spec;
23839  pContext->pulse.pa_stream_get_channel_map = (ma_proc)_pa_stream_get_channel_map;
23840  pContext->pulse.pa_stream_get_buffer_attr = (ma_proc)_pa_stream_get_buffer_attr;
23841  pContext->pulse.pa_stream_set_buffer_attr = (ma_proc)_pa_stream_set_buffer_attr;
23842  pContext->pulse.pa_stream_get_device_name = (ma_proc)_pa_stream_get_device_name;
23843  pContext->pulse.pa_stream_set_write_callback = (ma_proc)_pa_stream_set_write_callback;
23844  pContext->pulse.pa_stream_set_read_callback = (ma_proc)_pa_stream_set_read_callback;
23845  pContext->pulse.pa_stream_set_suspended_callback = (ma_proc)_pa_stream_set_suspended_callback;
23846  pContext->pulse.pa_stream_is_suspended = (ma_proc)_pa_stream_is_suspended;
23847  pContext->pulse.pa_stream_flush = (ma_proc)_pa_stream_flush;
23848  pContext->pulse.pa_stream_drain = (ma_proc)_pa_stream_drain;
23849  pContext->pulse.pa_stream_is_corked = (ma_proc)_pa_stream_is_corked;
23850  pContext->pulse.pa_stream_cork = (ma_proc)_pa_stream_cork;
23851  pContext->pulse.pa_stream_trigger = (ma_proc)_pa_stream_trigger;
23852  pContext->pulse.pa_stream_begin_write = (ma_proc)_pa_stream_begin_write;
23853  pContext->pulse.pa_stream_write = (ma_proc)_pa_stream_write;
23854  pContext->pulse.pa_stream_peek = (ma_proc)_pa_stream_peek;
23855  pContext->pulse.pa_stream_drop = (ma_proc)_pa_stream_drop;
23856  pContext->pulse.pa_stream_writable_size = (ma_proc)_pa_stream_writable_size;
23857  pContext->pulse.pa_stream_readable_size = (ma_proc)_pa_stream_readable_size;
23858 #endif
23859 
23860  /* 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. */
23861  pContext->pulse.pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
23862  if (pContext->pulse.pMainLoop == NULL) {
23863  result = ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create mainloop.", MA_FAILED_TO_INIT_BACKEND);
23864  #ifndef MA_NO_RUNTIME_LINKING
23865  ma_dlclose(pContext, pContext->pulse.pulseSO);
23866  #endif
23867  return result;
23868  }
23869 
23870  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);
23871  if (pContext->pulse.pPulseContext == NULL) {
23872  result = ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio context.", MA_FAILED_TO_INIT_BACKEND);
23873  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pContext->pulse.pMainLoop));
23874  #ifndef MA_NO_RUNTIME_LINKING
23875  ma_dlclose(pContext, pContext->pulse.pulseSO);
23876  #endif
23877  return result;
23878  }
23879 
23880  /* Now we need to connect to the context. Everything is asynchronous so we need to wait for it to connect before returning. */
23881  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));
23882  if (result != MA_SUCCESS) {
23883  ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio context.", result);
23884  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pContext->pulse.pMainLoop));
23885  #ifndef MA_NO_RUNTIME_LINKING
23886  ma_dlclose(pContext, pContext->pulse.pulseSO);
23887  #endif
23888  return result;
23889  }
23890 
23891  /* Since ma_context_init() runs synchronously we need to wait for the PulseAudio context to connect before we return. */
23892  result = ma_context_wait_for_pa_context_to_connect__pulse(pContext);
23893  if (result != MA_SUCCESS) {
23894  ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pContext->pulse.pMainLoop));
23895  #ifndef MA_NO_RUNTIME_LINKING
23896  ma_dlclose(pContext, pContext->pulse.pulseSO);
23897  #endif
23898  return result;
23899  }
23900 
23901 
23902  /* With pa_mainloop we run a synchronous backend, but we implement our own main loop. */
23903  pCallbacks->onContextInit = ma_context_init__pulse;
23904  pCallbacks->onContextUninit = ma_context_uninit__pulse;
23905  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__pulse;
23906  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__pulse;
23907  pCallbacks->onDeviceInit = ma_device_init__pulse;
23908  pCallbacks->onDeviceUninit = ma_device_uninit__pulse;
23909  pCallbacks->onDeviceStart = ma_device_start__pulse;
23910  pCallbacks->onDeviceStop = ma_device_stop__pulse;
23911  pCallbacks->onDeviceRead = NULL; /* Not used because we're implementing onDeviceDataLoop. */
23912  pCallbacks->onDeviceWrite = NULL; /* Not used because we're implementing onDeviceDataLoop. */
23913  pCallbacks->onDeviceDataLoop = ma_device_data_loop__pulse;
23914  pCallbacks->onDeviceDataLoopWakeup = ma_device_data_loop_wakeup__pulse;
23915 
23916  return MA_SUCCESS;
23917 }
23918 #endif
23919 
23920 
23921 /******************************************************************************
23922 
23923 JACK Backend
23924 
23925 ******************************************************************************/
23926 #ifdef MA_HAS_JACK
23927 
23928 /* It is assumed jack.h is available when compile-time linking is being used. */
23929 #ifdef MA_NO_RUNTIME_LINKING
23930 #include <jack/jack.h>
23931 
23932 typedef jack_nframes_t ma_jack_nframes_t;
23933 typedef jack_options_t ma_jack_options_t;
23934 typedef jack_status_t ma_jack_status_t;
23935 typedef jack_client_t ma_jack_client_t;
23936 typedef jack_port_t ma_jack_port_t;
23937 typedef JackProcessCallback ma_JackProcessCallback;
23938 typedef JackBufferSizeCallback ma_JackBufferSizeCallback;
23939 typedef JackShutdownCallback ma_JackShutdownCallback;
23940 #define MA_JACK_DEFAULT_AUDIO_TYPE JACK_DEFAULT_AUDIO_TYPE
23941 #define ma_JackNoStartServer JackNoStartServer
23942 #define ma_JackPortIsInput JackPortIsInput
23943 #define ma_JackPortIsOutput JackPortIsOutput
23944 #define ma_JackPortIsPhysical JackPortIsPhysical
23945 #else
23946 typedef ma_uint32 ma_jack_nframes_t;
23947 typedef int ma_jack_options_t;
23948 typedef int ma_jack_status_t;
23949 typedef struct ma_jack_client_t ma_jack_client_t;
23950 typedef struct ma_jack_port_t ma_jack_port_t;
23951 typedef int (* ma_JackProcessCallback) (ma_jack_nframes_t nframes, void* arg);
23952 typedef int (* ma_JackBufferSizeCallback)(ma_jack_nframes_t nframes, void* arg);
23953 typedef void (* ma_JackShutdownCallback) (void* arg);
23954 #define MA_JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio"
23955 #define ma_JackNoStartServer 1
23956 #define ma_JackPortIsInput 1
23957 #define ma_JackPortIsOutput 2
23958 #define ma_JackPortIsPhysical 4
23959 #endif
23960 
23961 typedef ma_jack_client_t* (* ma_jack_client_open_proc) (const char* client_name, ma_jack_options_t options, ma_jack_status_t* status, ...);
23962 typedef int (* ma_jack_client_close_proc) (ma_jack_client_t* client);
23963 typedef int (* ma_jack_client_name_size_proc) (void);
23964 typedef int (* ma_jack_set_process_callback_proc) (ma_jack_client_t* client, ma_JackProcessCallback process_callback, void* arg);
23965 typedef int (* ma_jack_set_buffer_size_callback_proc)(ma_jack_client_t* client, ma_JackBufferSizeCallback bufsize_callback, void* arg);
23966 typedef void (* ma_jack_on_shutdown_proc) (ma_jack_client_t* client, ma_JackShutdownCallback function, void* arg);
23967 typedef ma_jack_nframes_t (* ma_jack_get_sample_rate_proc) (ma_jack_client_t* client);
23968 typedef ma_jack_nframes_t (* ma_jack_get_buffer_size_proc) (ma_jack_client_t* client);
23969 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);
23970 typedef int (* ma_jack_activate_proc) (ma_jack_client_t* client);
23971 typedef int (* ma_jack_deactivate_proc) (ma_jack_client_t* client);
23972 typedef int (* ma_jack_connect_proc) (ma_jack_client_t* client, const char* source_port, const char* destination_port);
23973 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);
23974 typedef const char* (* ma_jack_port_name_proc) (const ma_jack_port_t* port);
23975 typedef void* (* ma_jack_port_get_buffer_proc) (ma_jack_port_t* port, ma_jack_nframes_t nframes);
23976 typedef void (* ma_jack_free_proc) (void* ptr);
23977 
23978 static ma_result ma_context_open_client__jack(ma_context* pContext, ma_jack_client_t** ppClient)
23979 {
23980  size_t maxClientNameSize;
23981  char clientName[256];
23982  ma_jack_status_t status;
23983  ma_jack_client_t* pClient;
23984 
23985  MA_ASSERT(pContext != NULL);
23986  MA_ASSERT(ppClient != NULL);
23987 
23988  if (ppClient) {
23989  *ppClient = NULL;
23990  }
23991 
23992  maxClientNameSize = ((ma_jack_client_name_size_proc)pContext->jack.jack_client_name_size)(); /* Includes null terminator. */
23993  ma_strncpy_s(clientName, ma_min(sizeof(clientName), maxClientNameSize), (pContext->jack.pClientName != NULL) ? pContext->jack.pClientName : "miniaudio", (size_t)-1);
23994 
23995  pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? 0 : ma_JackNoStartServer, &status, NULL);
23996  if (pClient == NULL) {
23998  }
23999 
24000  if (ppClient) {
24001  *ppClient = pClient;
24002  }
24003 
24004  return MA_SUCCESS;
24005 }
24006 
24007 
24008 static ma_result ma_context_enumerate_devices__jack(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
24009 {
24010  ma_bool32 cbResult = MA_TRUE;
24011 
24012  MA_ASSERT(pContext != NULL);
24013  MA_ASSERT(callback != NULL);
24014 
24015  /* Playback. */
24016  if (cbResult) {
24017  ma_device_info deviceInfo;
24018  MA_ZERO_OBJECT(&deviceInfo);
24019  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
24020  deviceInfo.isDefault = MA_TRUE; /* JACK only uses default devices. */
24021  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
24022  }
24023 
24024  /* Capture. */
24025  if (cbResult) {
24026  ma_device_info deviceInfo;
24027  MA_ZERO_OBJECT(&deviceInfo);
24028  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
24029  deviceInfo.isDefault = MA_TRUE; /* JACK only uses default devices. */
24030  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
24031  }
24032 
24033  (void)cbResult; /* For silencing a static analysis warning. */
24034 
24035  return MA_SUCCESS;
24036 }
24037 
24038 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)
24039 {
24040  ma_jack_client_t* pClient;
24041  ma_result result;
24042  const char** ppPorts;
24043 
24044  MA_ASSERT(pContext != NULL);
24045 
24046  if (pDeviceID != NULL && pDeviceID->jack != 0) {
24047  return MA_NO_DEVICE; /* Don't know the device. */
24048  }
24049 
24050  /* Name / Description */
24051  if (deviceType == ma_device_type_playback) {
24052  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
24053  } else {
24054  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
24055  }
24056 
24057  /* Jack only uses default devices. */
24058  pDeviceInfo->isDefault = MA_TRUE;
24059 
24060  /* Jack only supports f32 and has a specific channel count and sample rate. */
24061  pDeviceInfo->nativeDataFormats[0].format = ma_format_f32;
24062 
24063  /* The channel count and sample rate can only be determined by opening the device. */
24064  result = ma_context_open_client__jack(pContext, &pClient);
24065  if (result != MA_SUCCESS) {
24066  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[JACK] Failed to open client.", result);
24067  }
24068 
24069  pDeviceInfo->nativeDataFormats[0].sampleRate = ((ma_jack_get_sample_rate_proc)pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pClient);
24070  pDeviceInfo->nativeDataFormats[0].channels = 0;
24071 
24072  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));
24073  if (ppPorts == NULL) {
24074  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pClient);
24075  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24076  }
24077 
24078  while (ppPorts[pDeviceInfo->nativeDataFormats[0].channels] != NULL) {
24079  pDeviceInfo->nativeDataFormats[0].channels += 1;
24080  }
24081 
24082  pDeviceInfo->nativeDataFormats[0].flags = 0;
24083  pDeviceInfo->nativeDataFormatCount = 1;
24084 
24085  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppPorts);
24086  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pClient);
24087 
24088  (void)pContext;
24089  return MA_SUCCESS;
24090 }
24091 
24092 
24093 static ma_result ma_device_uninit__jack(ma_device* pDevice)
24094 {
24095  ma_context* pContext;
24096 
24097  MA_ASSERT(pDevice != NULL);
24098 
24099  pContext = pDevice->pContext;
24100  MA_ASSERT(pContext != NULL);
24101 
24102  if (pDevice->jack.pClient != NULL) {
24103  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pDevice->jack.pClient);
24104  }
24105 
24106  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24107  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferCapture, &pDevice->pContext->allocationCallbacks);
24108  }
24109 
24110  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24111  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferPlayback, &pDevice->pContext->allocationCallbacks);
24112  }
24113 
24114  return MA_SUCCESS;
24115 }
24116 
24117 static void ma_device__jack_shutdown_callback(void* pUserData)
24118 {
24119  /* JACK died. Stop the device. */
24120  ma_device* pDevice = (ma_device*)pUserData;
24121  MA_ASSERT(pDevice != NULL);
24122 
24123  ma_device_stop(pDevice);
24124 }
24125 
24126 static int ma_device__jack_buffer_size_callback(ma_jack_nframes_t frameCount, void* pUserData)
24127 {
24128  ma_device* pDevice = (ma_device*)pUserData;
24129  MA_ASSERT(pDevice != NULL);
24130 
24131  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24132  size_t newBufferSize = frameCount * (pDevice->capture.internalChannels * ma_get_bytes_per_sample(pDevice->capture.internalFormat));
24133  float* pNewBuffer = (float*)ma__calloc_from_callbacks(newBufferSize, &pDevice->pContext->allocationCallbacks);
24134  if (pNewBuffer == NULL) {
24135  return MA_OUT_OF_MEMORY;
24136  }
24137 
24138  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferCapture, &pDevice->pContext->allocationCallbacks);
24139 
24140  pDevice->jack.pIntermediaryBufferCapture = pNewBuffer;
24141  pDevice->playback.internalPeriodSizeInFrames = frameCount;
24142  }
24143 
24144  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24145  size_t newBufferSize = frameCount * (pDevice->playback.internalChannels * ma_get_bytes_per_sample(pDevice->playback.internalFormat));
24146  float* pNewBuffer = (float*)ma__calloc_from_callbacks(newBufferSize, &pDevice->pContext->allocationCallbacks);
24147  if (pNewBuffer == NULL) {
24148  return MA_OUT_OF_MEMORY;
24149  }
24150 
24151  ma__free_from_callbacks(pDevice->jack.pIntermediaryBufferPlayback, &pDevice->pContext->allocationCallbacks);
24152 
24153  pDevice->jack.pIntermediaryBufferPlayback = pNewBuffer;
24154  pDevice->playback.internalPeriodSizeInFrames = frameCount;
24155  }
24156 
24157  return 0;
24158 }
24159 
24160 static int ma_device__jack_process_callback(ma_jack_nframes_t frameCount, void* pUserData)
24161 {
24162  ma_device* pDevice;
24163  ma_context* pContext;
24164  ma_uint32 iChannel;
24165 
24166  pDevice = (ma_device*)pUserData;
24167  MA_ASSERT(pDevice != NULL);
24168 
24169  pContext = pDevice->pContext;
24170  MA_ASSERT(pContext != NULL);
24171 
24172  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24173  /* Channels need to be interleaved. */
24174  for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
24175  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);
24176  if (pSrc != NULL) {
24177  float* pDst = pDevice->jack.pIntermediaryBufferCapture + iChannel;
24178  ma_jack_nframes_t iFrame;
24179  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
24180  *pDst = *pSrc;
24181 
24182  pDst += pDevice->capture.internalChannels;
24183  pSrc += 1;
24184  }
24185  }
24186  }
24187 
24188  ma_device_handle_backend_data_callback(pDevice, NULL, pDevice->jack.pIntermediaryBufferCapture, frameCount);
24189  }
24190 
24191  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24192  ma_device_handle_backend_data_callback(pDevice, pDevice->jack.pIntermediaryBufferPlayback, NULL, frameCount);
24193 
24194  /* Channels need to be deinterleaved. */
24195  for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
24196  float* pDst = (float*)((ma_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[iChannel], frameCount);
24197  if (pDst != NULL) {
24198  const float* pSrc = pDevice->jack.pIntermediaryBufferPlayback + iChannel;
24199  ma_jack_nframes_t iFrame;
24200  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
24201  *pDst = *pSrc;
24202 
24203  pDst += 1;
24204  pSrc += pDevice->playback.internalChannels;
24205  }
24206  }
24207  }
24208  }
24209 
24210  return 0;
24211 }
24212 
24213 static ma_result ma_device_init__jack(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
24214 {
24215  ma_result result;
24216  ma_uint32 periodSizeInFrames;
24217 
24218  MA_ASSERT(pConfig != NULL);
24219  MA_ASSERT(pDevice != NULL);
24220 
24221  if (pConfig->deviceType == ma_device_type_loopback) {
24223  }
24224 
24225  /* Only supporting default devices with JACK. */
24226  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->pDeviceID != NULL && pDescriptorPlayback->pDeviceID->jack != 0) ||
24227  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->pDeviceID != NULL && pDescriptorCapture->pDeviceID->jack != 0)) {
24228  return MA_NO_DEVICE;
24229  }
24230 
24231  /* No exclusive mode with the JACK backend. */
24232  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
24233  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
24235  }
24236 
24237  /* Open the client. */
24238  result = ma_context_open_client__jack(pDevice->pContext, (ma_jack_client_t**)&pDevice->jack.pClient);
24239  if (result != MA_SUCCESS) {
24240  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to open client.", result);
24241  }
24242 
24243  /* Callbacks. */
24244  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) {
24245  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to set process callback.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24246  }
24247  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) {
24248  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to set buffer size callback.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24249  }
24250 
24251  ((ma_jack_on_shutdown_proc)pDevice->pContext->jack.jack_on_shutdown)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_shutdown_callback, pDevice);
24252 
24253 
24254  /* The buffer size in frames can change. */
24255  periodSizeInFrames = ((ma_jack_get_buffer_size_proc)pDevice->pContext->jack.jack_get_buffer_size)((ma_jack_client_t*)pDevice->jack.pClient);
24256 
24257  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
24258  const char** ppPorts;
24259 
24260  pDescriptorCapture->format = ma_format_f32;
24261  pDescriptorCapture->channels = 0;
24262  pDescriptorCapture->sampleRate = ((ma_jack_get_sample_rate_proc)pDevice->pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
24263  ma_get_standard_channel_map(ma_standard_channel_map_alsa, pDescriptorCapture->channels, pDescriptorCapture->channelMap);
24264 
24265  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);
24266  if (ppPorts == NULL) {
24267  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24268  }
24269 
24270  while (ppPorts[pDescriptorCapture->channels] != NULL) {
24271  char name[64];
24272  ma_strcpy_s(name, sizeof(name), "capture");
24273  ma_itoa_s((int)pDescriptorCapture->channels, name+7, sizeof(name)-7, 10); /* 7 = length of "capture" */
24274 
24275  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);
24276  if (pDevice->jack.pPortsCapture[pDescriptorCapture->channels] == NULL) {
24277  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
24278  ma_device_uninit__jack(pDevice);
24279  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24280  }
24281 
24282  pDescriptorCapture->channels += 1;
24283  }
24284 
24285  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
24286 
24287  pDescriptorCapture->periodSizeInFrames = periodSizeInFrames;
24288  pDescriptorCapture->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */
24289 
24290  pDevice->jack.pIntermediaryBufferCapture = (float*)ma__calloc_from_callbacks(pDescriptorCapture->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels), &pDevice->pContext->allocationCallbacks);
24291  if (pDevice->jack.pIntermediaryBufferCapture == NULL) {
24292  ma_device_uninit__jack(pDevice);
24293  return MA_OUT_OF_MEMORY;
24294  }
24295  }
24296 
24297  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
24298  const char** ppPorts;
24299 
24300  pDescriptorPlayback->format = ma_format_f32;
24301  pDescriptorPlayback->channels = 0;
24302  pDescriptorPlayback->sampleRate = ((ma_jack_get_sample_rate_proc)pDevice->pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
24303  ma_get_standard_channel_map(ma_standard_channel_map_alsa, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
24304 
24305  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);
24306  if (ppPorts == NULL) {
24307  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to query physical ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24308  }
24309 
24310  while (ppPorts[pDescriptorPlayback->channels] != NULL) {
24311  char name[64];
24312  ma_strcpy_s(name, sizeof(name), "playback");
24313  ma_itoa_s((int)pDescriptorPlayback->channels, name+8, sizeof(name)-8, 10); /* 8 = length of "playback" */
24314 
24315  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);
24316  if (pDevice->jack.pPortsPlayback[pDescriptorPlayback->channels] == NULL) {
24317  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
24318  ma_device_uninit__jack(pDevice);
24319  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to register ports.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
24320  }
24321 
24322  pDescriptorPlayback->channels += 1;
24323  }
24324 
24325  ((ma_jack_free_proc)pDevice->pContext->jack.jack_free)((void*)ppPorts);
24326 
24327  pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
24328  pDescriptorPlayback->periodCount = 1; /* There's no notion of a period in JACK. Just set to 1. */
24329 
24330  pDevice->jack.pIntermediaryBufferPlayback = (float*)ma__calloc_from_callbacks(pDescriptorPlayback->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels), &pDevice->pContext->allocationCallbacks);
24331  if (pDevice->jack.pIntermediaryBufferPlayback == NULL) {
24332  ma_device_uninit__jack(pDevice);
24333  return MA_OUT_OF_MEMORY;
24334  }
24335  }
24336 
24337  return MA_SUCCESS;
24338 }
24339 
24340 
24341 static ma_result ma_device_start__jack(ma_device* pDevice)
24342 {
24343  ma_context* pContext = pDevice->pContext;
24344  int resultJACK;
24345  size_t i;
24346 
24347  resultJACK = ((ma_jack_activate_proc)pContext->jack.jack_activate)((ma_jack_client_t*)pDevice->jack.pClient);
24348  if (resultJACK != 0) {
24349  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to activate the JACK client.", MA_FAILED_TO_START_BACKEND_DEVICE);
24350  }
24351 
24352  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
24353  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);
24354  if (ppServerPorts == NULL) {
24355  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
24356  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to retrieve physical ports.", MA_ERROR);
24357  }
24358 
24359  for (i = 0; ppServerPorts[i] != NULL; ++i) {
24360  const char* pServerPort = ppServerPorts[i];
24361  const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsCapture[i]);
24362 
24363  resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pServerPort, pClientPort);
24364  if (resultJACK != 0) {
24365  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
24366  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
24367  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to connect ports.", MA_ERROR);
24368  }
24369  }
24370 
24371  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
24372  }
24373 
24374  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
24375  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);
24376  if (ppServerPorts == NULL) {
24377  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
24378  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to retrieve physical ports.", MA_ERROR);
24379  }
24380 
24381  for (i = 0; ppServerPorts[i] != NULL; ++i) {
24382  const char* pServerPort = ppServerPorts[i];
24383  const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[i]);
24384 
24385  resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pClientPort, pServerPort);
24386  if (resultJACK != 0) {
24387  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
24388  ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
24389  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] Failed to connect ports.", MA_ERROR);
24390  }
24391  }
24392 
24393  ((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
24394  }
24395 
24396  return MA_SUCCESS;
24397 }
24398 
24399 static ma_result ma_device_stop__jack(ma_device* pDevice)
24400 {
24401  ma_context* pContext = pDevice->pContext;
24402  ma_stop_proc onStop;
24403 
24404  if (((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient) != 0) {
24405  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[JACK] An error occurred when deactivating the JACK client.", MA_ERROR);
24406  }
24407 
24408  onStop = pDevice->onStop;
24409  if (onStop) {
24410  onStop(pDevice);
24411  }
24412 
24413  return MA_SUCCESS;
24414 }
24415 
24416 
24417 static ma_result ma_context_uninit__jack(ma_context* pContext)
24418 {
24419  MA_ASSERT(pContext != NULL);
24420  MA_ASSERT(pContext->backend == ma_backend_jack);
24421 
24422  ma_free(pContext->jack.pClientName, &pContext->allocationCallbacks);
24423  pContext->jack.pClientName = NULL;
24424 
24425 #ifndef MA_NO_RUNTIME_LINKING
24426  ma_dlclose(pContext, pContext->jack.jackSO);
24427 #endif
24428 
24429  return MA_SUCCESS;
24430 }
24431 
24432 static ma_result ma_context_init__jack(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
24433 {
24434 #ifndef MA_NO_RUNTIME_LINKING
24435  const char* libjackNames[] = {
24436 #ifdef MA_WIN32
24437  "libjack.dll",
24438  "libjack64.dll"
24439 #else
24440  "libjack.so",
24441  "libjack.so.0"
24442 #endif
24443  };
24444  size_t i;
24445 
24446  for (i = 0; i < ma_countof(libjackNames); ++i) {
24447  pContext->jack.jackSO = ma_dlopen(pContext, libjackNames[i]);
24448  if (pContext->jack.jackSO != NULL) {
24449  break;
24450  }
24451  }
24452 
24453  if (pContext->jack.jackSO == NULL) {
24454  return MA_NO_BACKEND;
24455  }
24456 
24457  pContext->jack.jack_client_open = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_open");
24458  pContext->jack.jack_client_close = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_close");
24459  pContext->jack.jack_client_name_size = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_name_size");
24460  pContext->jack.jack_set_process_callback = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_set_process_callback");
24461  pContext->jack.jack_set_buffer_size_callback = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_set_buffer_size_callback");
24462  pContext->jack.jack_on_shutdown = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_on_shutdown");
24463  pContext->jack.jack_get_sample_rate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_sample_rate");
24464  pContext->jack.jack_get_buffer_size = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_buffer_size");
24465  pContext->jack.jack_get_ports = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_ports");
24466  pContext->jack.jack_activate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_activate");
24467  pContext->jack.jack_deactivate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_deactivate");
24468  pContext->jack.jack_connect = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_connect");
24469  pContext->jack.jack_port_register = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_register");
24470  pContext->jack.jack_port_name = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_name");
24471  pContext->jack.jack_port_get_buffer = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_get_buffer");
24472  pContext->jack.jack_free = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_free");
24473 #else
24474  /*
24475  This strange assignment system is here just to ensure type safety of miniaudio's function pointer
24476  types. If anything differs slightly the compiler should throw a warning.
24477  */
24478  ma_jack_client_open_proc _jack_client_open = jack_client_open;
24479  ma_jack_client_close_proc _jack_client_close = jack_client_close;
24480  ma_jack_client_name_size_proc _jack_client_name_size = jack_client_name_size;
24481  ma_jack_set_process_callback_proc _jack_set_process_callback = jack_set_process_callback;
24482  ma_jack_set_buffer_size_callback_proc _jack_set_buffer_size_callback = jack_set_buffer_size_callback;
24483  ma_jack_on_shutdown_proc _jack_on_shutdown = jack_on_shutdown;
24484  ma_jack_get_sample_rate_proc _jack_get_sample_rate = jack_get_sample_rate;
24485  ma_jack_get_buffer_size_proc _jack_get_buffer_size = jack_get_buffer_size;
24486  ma_jack_get_ports_proc _jack_get_ports = jack_get_ports;
24487  ma_jack_activate_proc _jack_activate = jack_activate;
24488  ma_jack_deactivate_proc _jack_deactivate = jack_deactivate;
24489  ma_jack_connect_proc _jack_connect = jack_connect;
24490  ma_jack_port_register_proc _jack_port_register = jack_port_register;
24491  ma_jack_port_name_proc _jack_port_name = jack_port_name;
24492  ma_jack_port_get_buffer_proc _jack_port_get_buffer = jack_port_get_buffer;
24493  ma_jack_free_proc _jack_free = jack_free;
24494 
24495  pContext->jack.jack_client_open = (ma_proc)_jack_client_open;
24496  pContext->jack.jack_client_close = (ma_proc)_jack_client_close;
24497  pContext->jack.jack_client_name_size = (ma_proc)_jack_client_name_size;
24498  pContext->jack.jack_set_process_callback = (ma_proc)_jack_set_process_callback;
24499  pContext->jack.jack_set_buffer_size_callback = (ma_proc)_jack_set_buffer_size_callback;
24500  pContext->jack.jack_on_shutdown = (ma_proc)_jack_on_shutdown;
24501  pContext->jack.jack_get_sample_rate = (ma_proc)_jack_get_sample_rate;
24502  pContext->jack.jack_get_buffer_size = (ma_proc)_jack_get_buffer_size;
24503  pContext->jack.jack_get_ports = (ma_proc)_jack_get_ports;
24504  pContext->jack.jack_activate = (ma_proc)_jack_activate;
24505  pContext->jack.jack_deactivate = (ma_proc)_jack_deactivate;
24506  pContext->jack.jack_connect = (ma_proc)_jack_connect;
24507  pContext->jack.jack_port_register = (ma_proc)_jack_port_register;
24508  pContext->jack.jack_port_name = (ma_proc)_jack_port_name;
24509  pContext->jack.jack_port_get_buffer = (ma_proc)_jack_port_get_buffer;
24510  pContext->jack.jack_free = (ma_proc)_jack_free;
24511 #endif
24512 
24513  if (pConfig->jack.pClientName != NULL) {
24514  pContext->jack.pClientName = ma_copy_string(pConfig->jack.pClientName, &pContext->allocationCallbacks);
24515  }
24516  pContext->jack.tryStartServer = pConfig->jack.tryStartServer;
24517 
24518  /*
24519  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
24520  a temporary client.
24521  */
24522  {
24523  ma_jack_client_t* pDummyClient;
24524  ma_result result = ma_context_open_client__jack(pContext, &pDummyClient);
24525  if (result != MA_SUCCESS) {
24526  ma_free(pContext->jack.pClientName, &pContext->allocationCallbacks);
24527  #ifndef MA_NO_RUNTIME_LINKING
24528  ma_dlclose(pContext, pContext->jack.jackSO);
24529  #endif
24530  return MA_NO_BACKEND;
24531  }
24532 
24533  ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pDummyClient);
24534  }
24535 
24536 
24537  pCallbacks->onContextInit = ma_context_init__jack;
24538  pCallbacks->onContextUninit = ma_context_uninit__jack;
24539  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__jack;
24540  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__jack;
24541  pCallbacks->onDeviceInit = ma_device_init__jack;
24542  pCallbacks->onDeviceUninit = ma_device_uninit__jack;
24543  pCallbacks->onDeviceStart = ma_device_start__jack;
24544  pCallbacks->onDeviceStop = ma_device_stop__jack;
24545  pCallbacks->onDeviceRead = NULL; /* Not used because JACK is asynchronous. */
24546  pCallbacks->onDeviceWrite = NULL; /* Not used because JACK is asynchronous. */
24547  pCallbacks->onDeviceDataLoop = NULL; /* Not used because JACK is asynchronous. */
24548 
24549  return MA_SUCCESS;
24550 }
24551 #endif /* JACK */
24552 
24553 
24554 
24555 /******************************************************************************
24556 
24557 Core Audio Backend
24558 
24559 References
24560 ==========
24561 - Technical Note TN2091: Device input using the HAL Output Audio Unit
24562  https://developer.apple.com/library/archive/technotes/tn2091/_index.html
24563 
24564 ******************************************************************************/
24565 #ifdef MA_HAS_COREAUDIO
24566 #include <TargetConditionals.h>
24567 
24568 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1
24569  #define MA_APPLE_MOBILE
24570  #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
24571  #define MA_APPLE_TV
24572  #endif
24573  #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
24574  #define MA_APPLE_WATCH
24575  #endif
24576 #else
24577  #define MA_APPLE_DESKTOP
24578 #endif
24579 
24580 #if defined(MA_APPLE_DESKTOP)
24581 #include <CoreAudio/CoreAudio.h>
24582 #else
24583 #include <AVFoundation/AVFoundation.h>
24584 #endif
24585 
24586 #include <AudioToolbox/AudioToolbox.h>
24587 
24588 /* CoreFoundation */
24589 typedef Boolean (* ma_CFStringGetCString_proc)(CFStringRef theString, char* buffer, CFIndex bufferSize, CFStringEncoding encoding);
24590 typedef void (* ma_CFRelease_proc)(CFTypeRef cf);
24591 
24592 /* CoreAudio */
24593 #if defined(MA_APPLE_DESKTOP)
24594 typedef OSStatus (* ma_AudioObjectGetPropertyData_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* ioDataSize, void* outData);
24595 typedef OSStatus (* ma_AudioObjectGetPropertyDataSize_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* outDataSize);
24596 typedef OSStatus (* ma_AudioObjectSetPropertyData_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData);
24597 typedef OSStatus (* ma_AudioObjectAddPropertyListener_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener, void* inClientData);
24598 typedef OSStatus (* ma_AudioObjectRemovePropertyListener_proc)(AudioObjectID inObjectID, const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener, void* inClientData);
24599 #endif
24600 
24601 /* AudioToolbox */
24602 typedef AudioComponent (* ma_AudioComponentFindNext_proc)(AudioComponent inComponent, const AudioComponentDescription* inDesc);
24603 typedef OSStatus (* ma_AudioComponentInstanceDispose_proc)(AudioComponentInstance inInstance);
24604 typedef OSStatus (* ma_AudioComponentInstanceNew_proc)(AudioComponent inComponent, AudioComponentInstance* outInstance);
24605 typedef OSStatus (* ma_AudioOutputUnitStart_proc)(AudioUnit inUnit);
24606 typedef OSStatus (* ma_AudioOutputUnitStop_proc)(AudioUnit inUnit);
24607 typedef OSStatus (* ma_AudioUnitAddPropertyListener_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc, void* inProcUserData);
24608 typedef OSStatus (* ma_AudioUnitGetPropertyInfo_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32* outDataSize, Boolean* outWriteable);
24609 typedef OSStatus (* ma_AudioUnitGetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData, UInt32* ioDataSize);
24610 typedef OSStatus (* ma_AudioUnitSetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void* inData, UInt32 inDataSize);
24611 typedef OSStatus (* ma_AudioUnitInitialize_proc)(AudioUnit inUnit);
24612 typedef OSStatus (* ma_AudioUnitRender_proc)(AudioUnit inUnit, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData);
24613 
24614 
24615 #define MA_COREAUDIO_OUTPUT_BUS 0
24616 #define MA_COREAUDIO_INPUT_BUS 1
24617 
24618 #if defined(MA_APPLE_DESKTOP)
24619 static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_type deviceType, ma_bool32 disposePreviousAudioUnit);
24620 #endif
24621 
24622 /*
24623 Core Audio
24624 
24625 So far, Core Audio has been the worst backend to work with due to being both unintuitive and having almost no documentation
24626 apart from comments in the headers (which admittedly are quite good). For my own purposes, and for anybody out there whose
24627 needing to figure out how this darn thing works, I'm going to outline a few things here.
24628 
24629 Since miniaudio is a fairly low-level API, one of the things it needs is control over specific devices, and it needs to be
24630 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
24631 that supports this level of detail. There was some public domain sample code I stumbled across that used the AudioComponent
24632 and AudioUnit APIs, but I couldn't see anything that gave low-level control over device selection and capabilities (the
24633 distinction between playback and capture in particular). Therefore, miniaudio is using the AudioObject API.
24634 
24635 Most (all?) functions in the AudioObject API take a AudioObjectID as it's input. This is the device identifier. When
24636 retrieving global information, such as the device list, you use kAudioObjectSystemObject. When retrieving device-specific
24637 data, you pass in the ID for that device. In order to retrieve device-specific IDs you need to enumerate over each of the
24638 devices. This is done using the AudioObjectGetPropertyDataSize() and AudioObjectGetPropertyData() APIs which seem to be
24639 the central APIs for retrieving information about the system and specific devices.
24640 
24641 To use the AudioObjectGetPropertyData() API you need to use the notion of a property address. A property address is a
24642 structure with three variables and is used to identify which property you are getting or setting. The first is the "selector"
24643 which is basically the specific property that you're wanting to retrieve or set. The second is the "scope", which is
24644 typically set to kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeInput for input-specific properties and
24645 kAudioObjectPropertyScopeOutput for output-specific properties. The last is the "element" which is always set to
24646 kAudioObjectPropertyElementMaster in miniaudio's case. I don't know of any cases where this would be set to anything different.
24647 
24648 Back to the earlier issue of device retrieval, you first use the AudioObjectGetPropertyDataSize() API to retrieve the size
24649 of the raw data which is just a list of AudioDeviceID's. You use the kAudioObjectSystemObject AudioObjectID, and a property
24650 address with the kAudioHardwarePropertyDevices selector and the kAudioObjectPropertyScopeGlobal scope. Once you have the
24651 size, allocate a block of memory of that size and then call AudioObjectGetPropertyData(). The data is just a list of
24652 AudioDeviceID's so just do "dataSize/sizeof(AudioDeviceID)" to know the device count.
24653 */
24654 
24655 static ma_result ma_result_from_OSStatus(OSStatus status)
24656 {
24657  switch (status)
24658  {
24659  case noErr: return MA_SUCCESS;
24660  #if defined(MA_APPLE_DESKTOP)
24661  case kAudioHardwareNotRunningError: return MA_DEVICE_NOT_STARTED;
24662  case kAudioHardwareUnspecifiedError: return MA_ERROR;
24663  case kAudioHardwareUnknownPropertyError: return MA_INVALID_ARGS;
24664  case kAudioHardwareBadPropertySizeError: return MA_INVALID_OPERATION;
24665  case kAudioHardwareIllegalOperationError: return MA_INVALID_OPERATION;
24666  case kAudioHardwareBadObjectError: return MA_INVALID_ARGS;
24667  case kAudioHardwareBadDeviceError: return MA_INVALID_ARGS;
24668  case kAudioHardwareBadStreamError: return MA_INVALID_ARGS;
24669  case kAudioHardwareUnsupportedOperationError: return MA_INVALID_OPERATION;
24670  case kAudioDeviceUnsupportedFormatError: return MA_FORMAT_NOT_SUPPORTED;
24671  case kAudioDevicePermissionsError: return MA_ACCESS_DENIED;
24672  #endif
24673  default: return MA_ERROR;
24674  }
24675 }
24676 
24677 #if 0
24678 static ma_channel ma_channel_from_AudioChannelBitmap(AudioChannelBitmap bit)
24679 {
24680  switch (bit)
24681  {
24682  case kAudioChannelBit_Left: return MA_CHANNEL_LEFT;
24683  case kAudioChannelBit_Right: return MA_CHANNEL_RIGHT;
24684  case kAudioChannelBit_Center: return MA_CHANNEL_FRONT_CENTER;
24685  case kAudioChannelBit_LFEScreen: return MA_CHANNEL_LFE;
24686  case kAudioChannelBit_LeftSurround: return MA_CHANNEL_BACK_LEFT;
24687  case kAudioChannelBit_RightSurround: return MA_CHANNEL_BACK_RIGHT;
24688  case kAudioChannelBit_LeftCenter: return MA_CHANNEL_FRONT_LEFT_CENTER;
24689  case kAudioChannelBit_RightCenter: return MA_CHANNEL_FRONT_RIGHT_CENTER;
24690  case kAudioChannelBit_CenterSurround: return MA_CHANNEL_BACK_CENTER;
24691  case kAudioChannelBit_LeftSurroundDirect: return MA_CHANNEL_SIDE_LEFT;
24692  case kAudioChannelBit_RightSurroundDirect: return MA_CHANNEL_SIDE_RIGHT;
24693  case kAudioChannelBit_TopCenterSurround: return MA_CHANNEL_TOP_CENTER;
24694  case kAudioChannelBit_VerticalHeightLeft: return MA_CHANNEL_TOP_FRONT_LEFT;
24695  case kAudioChannelBit_VerticalHeightCenter: return MA_CHANNEL_TOP_FRONT_CENTER;
24696  case kAudioChannelBit_VerticalHeightRight: return MA_CHANNEL_TOP_FRONT_RIGHT;
24697  case kAudioChannelBit_TopBackLeft: return MA_CHANNEL_TOP_BACK_LEFT;
24698  case kAudioChannelBit_TopBackCenter: return MA_CHANNEL_TOP_BACK_CENTER;
24699  case kAudioChannelBit_TopBackRight: return MA_CHANNEL_TOP_BACK_RIGHT;
24700  default: return MA_CHANNEL_NONE;
24701  }
24702 }
24703 #endif
24704 
24705 static ma_result ma_format_from_AudioStreamBasicDescription(const AudioStreamBasicDescription* pDescription, ma_format* pFormatOut)
24706 {
24707  MA_ASSERT(pDescription != NULL);
24708  MA_ASSERT(pFormatOut != NULL);
24709 
24710  *pFormatOut = ma_format_unknown; /* Safety. */
24711 
24712  /* There's a few things miniaudio doesn't support. */
24713  if (pDescription->mFormatID != kAudioFormatLinearPCM) {
24714  return MA_FORMAT_NOT_SUPPORTED;
24715  }
24716 
24717  /* We don't support any non-packed formats that are aligned high. */
24718  if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) != 0) {
24719  return MA_FORMAT_NOT_SUPPORTED;
24720  }
24721 
24722  /* Only supporting native-endian. */
24723  if ((ma_is_little_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) || (ma_is_big_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) == 0)) {
24724  return MA_FORMAT_NOT_SUPPORTED;
24725  }
24726 
24727  /* We are not currently supporting non-interleaved formats (this will be added in a future version of miniaudio). */
24728  /*if ((pDescription->mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) {
24729  return MA_FORMAT_NOT_SUPPORTED;
24730  }*/
24731 
24732  if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0) {
24733  if (pDescription->mBitsPerChannel == 32) {
24734  *pFormatOut = ma_format_f32;
24735  return MA_SUCCESS;
24736  }
24737  } else {
24738  if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) != 0) {
24739  if (pDescription->mBitsPerChannel == 16) {
24740  *pFormatOut = ma_format_s16;
24741  return MA_SUCCESS;
24742  } else if (pDescription->mBitsPerChannel == 24) {
24743  if (pDescription->mBytesPerFrame == (pDescription->mBitsPerChannel/8 * pDescription->mChannelsPerFrame)) {
24744  *pFormatOut = ma_format_s24;
24745  return MA_SUCCESS;
24746  } else {
24747  if (pDescription->mBytesPerFrame/pDescription->mChannelsPerFrame == sizeof(ma_int32)) {
24748  /* TODO: Implement ma_format_s24_32. */
24750  /*return MA_SUCCESS;*/
24751  return MA_FORMAT_NOT_SUPPORTED;
24752  }
24753  }
24754  } else if (pDescription->mBitsPerChannel == 32) {
24755  *pFormatOut = ma_format_s32;
24756  return MA_SUCCESS;
24757  }
24758  } else {
24759  if (pDescription->mBitsPerChannel == 8) {
24760  *pFormatOut = ma_format_u8;
24761  return MA_SUCCESS;
24762  }
24763  }
24764  }
24765 
24766  /* Getting here means the format is not supported. */
24767  return MA_FORMAT_NOT_SUPPORTED;
24768 }
24769 
24770 #if defined(MA_APPLE_DESKTOP)
24771 static ma_channel ma_channel_from_AudioChannelLabel(AudioChannelLabel label)
24772 {
24773  switch (label)
24774  {
24775  case kAudioChannelLabel_Unknown: return MA_CHANNEL_NONE;
24776  case kAudioChannelLabel_Unused: return MA_CHANNEL_NONE;
24777  case kAudioChannelLabel_UseCoordinates: return MA_CHANNEL_NONE;
24778  case kAudioChannelLabel_Left: return MA_CHANNEL_LEFT;
24779  case kAudioChannelLabel_Right: return MA_CHANNEL_RIGHT;
24780  case kAudioChannelLabel_Center: return MA_CHANNEL_FRONT_CENTER;
24781  case kAudioChannelLabel_LFEScreen: return MA_CHANNEL_LFE;
24782  case kAudioChannelLabel_LeftSurround: return MA_CHANNEL_BACK_LEFT;
24783  case kAudioChannelLabel_RightSurround: return MA_CHANNEL_BACK_RIGHT;
24784  case kAudioChannelLabel_LeftCenter: return MA_CHANNEL_FRONT_LEFT_CENTER;
24785  case kAudioChannelLabel_RightCenter: return MA_CHANNEL_FRONT_RIGHT_CENTER;
24786  case kAudioChannelLabel_CenterSurround: return MA_CHANNEL_BACK_CENTER;
24787  case kAudioChannelLabel_LeftSurroundDirect: return MA_CHANNEL_SIDE_LEFT;
24788  case kAudioChannelLabel_RightSurroundDirect: return MA_CHANNEL_SIDE_RIGHT;
24789  case kAudioChannelLabel_TopCenterSurround: return MA_CHANNEL_TOP_CENTER;
24790  case kAudioChannelLabel_VerticalHeightLeft: return MA_CHANNEL_TOP_FRONT_LEFT;
24791  case kAudioChannelLabel_VerticalHeightCenter: return MA_CHANNEL_TOP_FRONT_CENTER;
24792  case kAudioChannelLabel_VerticalHeightRight: return MA_CHANNEL_TOP_FRONT_RIGHT;
24793  case kAudioChannelLabel_TopBackLeft: return MA_CHANNEL_TOP_BACK_LEFT;
24794  case kAudioChannelLabel_TopBackCenter: return MA_CHANNEL_TOP_BACK_CENTER;
24795  case kAudioChannelLabel_TopBackRight: return MA_CHANNEL_TOP_BACK_RIGHT;
24796  case kAudioChannelLabel_RearSurroundLeft: return MA_CHANNEL_BACK_LEFT;
24797  case kAudioChannelLabel_RearSurroundRight: return MA_CHANNEL_BACK_RIGHT;
24798  case kAudioChannelLabel_LeftWide: return MA_CHANNEL_SIDE_LEFT;
24799  case kAudioChannelLabel_RightWide: return MA_CHANNEL_SIDE_RIGHT;
24800  case kAudioChannelLabel_LFE2: return MA_CHANNEL_LFE;
24801  case kAudioChannelLabel_LeftTotal: return MA_CHANNEL_LEFT;
24802  case kAudioChannelLabel_RightTotal: return MA_CHANNEL_RIGHT;
24803  case kAudioChannelLabel_HearingImpaired: return MA_CHANNEL_NONE;
24804  case kAudioChannelLabel_Narration: return MA_CHANNEL_MONO;
24805  case kAudioChannelLabel_Mono: return MA_CHANNEL_MONO;
24806  case kAudioChannelLabel_DialogCentricMix: return MA_CHANNEL_MONO;
24807  case kAudioChannelLabel_CenterSurroundDirect: return MA_CHANNEL_BACK_CENTER;
24808  case kAudioChannelLabel_Haptic: return MA_CHANNEL_NONE;
24809  case kAudioChannelLabel_Ambisonic_W: return MA_CHANNEL_NONE;
24810  case kAudioChannelLabel_Ambisonic_X: return MA_CHANNEL_NONE;
24811  case kAudioChannelLabel_Ambisonic_Y: return MA_CHANNEL_NONE;
24812  case kAudioChannelLabel_Ambisonic_Z: return MA_CHANNEL_NONE;
24813  case kAudioChannelLabel_MS_Mid: return MA_CHANNEL_LEFT;
24814  case kAudioChannelLabel_MS_Side: return MA_CHANNEL_RIGHT;
24815  case kAudioChannelLabel_XY_X: return MA_CHANNEL_LEFT;
24816  case kAudioChannelLabel_XY_Y: return MA_CHANNEL_RIGHT;
24817  case kAudioChannelLabel_HeadphonesLeft: return MA_CHANNEL_LEFT;
24818  case kAudioChannelLabel_HeadphonesRight: return MA_CHANNEL_RIGHT;
24819  case kAudioChannelLabel_ClickTrack: return MA_CHANNEL_NONE;
24820  case kAudioChannelLabel_ForeignLanguage: return MA_CHANNEL_NONE;
24821  case kAudioChannelLabel_Discrete: return MA_CHANNEL_NONE;
24822  case kAudioChannelLabel_Discrete_0: return MA_CHANNEL_AUX_0;
24823  case kAudioChannelLabel_Discrete_1: return MA_CHANNEL_AUX_1;
24824  case kAudioChannelLabel_Discrete_2: return MA_CHANNEL_AUX_2;
24825  case kAudioChannelLabel_Discrete_3: return MA_CHANNEL_AUX_3;
24826  case kAudioChannelLabel_Discrete_4: return MA_CHANNEL_AUX_4;
24827  case kAudioChannelLabel_Discrete_5: return MA_CHANNEL_AUX_5;
24828  case kAudioChannelLabel_Discrete_6: return MA_CHANNEL_AUX_6;
24829  case kAudioChannelLabel_Discrete_7: return MA_CHANNEL_AUX_7;
24830  case kAudioChannelLabel_Discrete_8: return MA_CHANNEL_AUX_8;
24831  case kAudioChannelLabel_Discrete_9: return MA_CHANNEL_AUX_9;
24832  case kAudioChannelLabel_Discrete_10: return MA_CHANNEL_AUX_10;
24833  case kAudioChannelLabel_Discrete_11: return MA_CHANNEL_AUX_11;
24834  case kAudioChannelLabel_Discrete_12: return MA_CHANNEL_AUX_12;
24835  case kAudioChannelLabel_Discrete_13: return MA_CHANNEL_AUX_13;
24836  case kAudioChannelLabel_Discrete_14: return MA_CHANNEL_AUX_14;
24837  case kAudioChannelLabel_Discrete_15: return MA_CHANNEL_AUX_15;
24838  case kAudioChannelLabel_Discrete_65535: return MA_CHANNEL_NONE;
24839 
24840  #if 0 /* Introduced in a later version of macOS. */
24841  case kAudioChannelLabel_HOA_ACN: return MA_CHANNEL_NONE;
24842  case kAudioChannelLabel_HOA_ACN_0: return MA_CHANNEL_AUX_0;
24843  case kAudioChannelLabel_HOA_ACN_1: return MA_CHANNEL_AUX_1;
24844  case kAudioChannelLabel_HOA_ACN_2: return MA_CHANNEL_AUX_2;
24845  case kAudioChannelLabel_HOA_ACN_3: return MA_CHANNEL_AUX_3;
24846  case kAudioChannelLabel_HOA_ACN_4: return MA_CHANNEL_AUX_4;
24847  case kAudioChannelLabel_HOA_ACN_5: return MA_CHANNEL_AUX_5;
24848  case kAudioChannelLabel_HOA_ACN_6: return MA_CHANNEL_AUX_6;
24849  case kAudioChannelLabel_HOA_ACN_7: return MA_CHANNEL_AUX_7;
24850  case kAudioChannelLabel_HOA_ACN_8: return MA_CHANNEL_AUX_8;
24851  case kAudioChannelLabel_HOA_ACN_9: return MA_CHANNEL_AUX_9;
24852  case kAudioChannelLabel_HOA_ACN_10: return MA_CHANNEL_AUX_10;
24853  case kAudioChannelLabel_HOA_ACN_11: return MA_CHANNEL_AUX_11;
24854  case kAudioChannelLabel_HOA_ACN_12: return MA_CHANNEL_AUX_12;
24855  case kAudioChannelLabel_HOA_ACN_13: return MA_CHANNEL_AUX_13;
24856  case kAudioChannelLabel_HOA_ACN_14: return MA_CHANNEL_AUX_14;
24857  case kAudioChannelLabel_HOA_ACN_15: return MA_CHANNEL_AUX_15;
24858  case kAudioChannelLabel_HOA_ACN_65024: return MA_CHANNEL_NONE;
24859  #endif
24860 
24861  default: return MA_CHANNEL_NONE;
24862  }
24863 }
24864 
24865 static ma_result ma_get_channel_map_from_AudioChannelLayout(AudioChannelLayout* pChannelLayout, ma_channel* pChannelMap, size_t channelMapCap)
24866 {
24867  MA_ASSERT(pChannelLayout != NULL);
24868 
24869  if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
24870  UInt32 iChannel;
24871  for (iChannel = 0; iChannel < pChannelLayout->mNumberChannelDescriptions && iChannel < channelMapCap; ++iChannel) {
24872  pChannelMap[iChannel] = ma_channel_from_AudioChannelLabel(pChannelLayout->mChannelDescriptions[iChannel].mChannelLabel);
24873  }
24874  } else
24875 #if 0
24876  if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
24877  /* This is the same kind of system that's used by Windows audio APIs. */
24878  UInt32 iChannel = 0;
24879  UInt32 iBit;
24880  AudioChannelBitmap bitmap = pChannelLayout->mChannelBitmap;
24881  for (iBit = 0; iBit < 32 && iChannel < channelMapCap; ++iBit) {
24882  AudioChannelBitmap bit = bitmap & (1 << iBit);
24883  if (bit != 0) {
24884  pChannelMap[iChannel++] = ma_channel_from_AudioChannelBit(bit);
24885  }
24886  }
24887  } else
24888 #endif
24889  {
24890  /*
24891  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
24892  be updated to determine the mapping based on the tag.
24893  */
24894  UInt32 channelCount;
24895 
24896  /* Our channel map retrieval APIs below take 32-bit integers, so we'll want to clamp the channel map capacity. */
24897  if (channelMapCap > 0xFFFFFFFF) {
24898  channelMapCap = 0xFFFFFFFF;
24899  }
24900 
24901  channelCount = ma_min(AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag), (UInt32)channelMapCap);
24902 
24903  switch (pChannelLayout->mChannelLayoutTag)
24904  {
24905  case kAudioChannelLayoutTag_Mono:
24906  case kAudioChannelLayoutTag_Stereo:
24907  case kAudioChannelLayoutTag_StereoHeadphones:
24908  case kAudioChannelLayoutTag_MatrixStereo:
24909  case kAudioChannelLayoutTag_MidSide:
24910  case kAudioChannelLayoutTag_XY:
24911  case kAudioChannelLayoutTag_Binaural:
24912  case kAudioChannelLayoutTag_Ambisonic_B_Format:
24913  {
24915  } break;
24916 
24917  case kAudioChannelLayoutTag_Octagonal:
24918  {
24919  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
24920  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
24921  } /* Intentional fallthrough. */
24922  case kAudioChannelLayoutTag_Hexagonal:
24923  {
24924  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
24925  } /* Intentional fallthrough. */
24926  case kAudioChannelLayoutTag_Pentagonal:
24927  {
24928  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
24929  } /* Intentional fallghrough. */
24930  case kAudioChannelLayoutTag_Quadraphonic:
24931  {
24932  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
24933  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
24934  pChannelMap[1] = MA_CHANNEL_RIGHT;
24935  pChannelMap[0] = MA_CHANNEL_LEFT;
24936  } break;
24937 
24938  /* TODO: Add support for more tags here. */
24939 
24940  default:
24941  {
24943  } break;
24944  }
24945  }
24946 
24947  return MA_SUCCESS;
24948 }
24949 
24950 static ma_result ma_get_device_object_ids__coreaudio(ma_context* pContext, UInt32* pDeviceCount, AudioObjectID** ppDeviceObjectIDs) /* NOTE: Free the returned buffer with ma_free(). */
24951 {
24952  AudioObjectPropertyAddress propAddressDevices;
24953  UInt32 deviceObjectsDataSize;
24954  OSStatus status;
24955  AudioObjectID* pDeviceObjectIDs;
24956 
24957  MA_ASSERT(pContext != NULL);
24958  MA_ASSERT(pDeviceCount != NULL);
24959  MA_ASSERT(ppDeviceObjectIDs != NULL);
24960 
24961  /* Safety. */
24962  *pDeviceCount = 0;
24963  *ppDeviceObjectIDs = NULL;
24964 
24965  propAddressDevices.mSelector = kAudioHardwarePropertyDevices;
24966  propAddressDevices.mScope = kAudioObjectPropertyScopeGlobal;
24967  propAddressDevices.mElement = kAudioObjectPropertyElementMaster;
24968 
24969  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(kAudioObjectSystemObject, &propAddressDevices, 0, NULL, &deviceObjectsDataSize);
24970  if (status != noErr) {
24971  return ma_result_from_OSStatus(status);
24972  }
24973 
24974  pDeviceObjectIDs = (AudioObjectID*)ma_malloc(deviceObjectsDataSize, &pContext->allocationCallbacks);
24975  if (pDeviceObjectIDs == NULL) {
24976  return MA_OUT_OF_MEMORY;
24977  }
24978 
24979  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDevices, 0, NULL, &deviceObjectsDataSize, pDeviceObjectIDs);
24980  if (status != noErr) {
24981  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
24982  return ma_result_from_OSStatus(status);
24983  }
24984 
24985  *pDeviceCount = deviceObjectsDataSize / sizeof(AudioObjectID);
24986  *ppDeviceObjectIDs = pDeviceObjectIDs;
24987 
24988  return MA_SUCCESS;
24989 }
24990 
24991 static ma_result ma_get_AudioObject_uid_as_CFStringRef(ma_context* pContext, AudioObjectID objectID, CFStringRef* pUID)
24992 {
24993  AudioObjectPropertyAddress propAddress;
24994  UInt32 dataSize;
24995  OSStatus status;
24996 
24997  MA_ASSERT(pContext != NULL);
24998 
24999  propAddress.mSelector = kAudioDevicePropertyDeviceUID;
25000  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
25001  propAddress.mElement = kAudioObjectPropertyElementMaster;
25002 
25003  dataSize = sizeof(*pUID);
25004  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0, NULL, &dataSize, pUID);
25005  if (status != noErr) {
25006  return ma_result_from_OSStatus(status);
25007  }
25008 
25009  return MA_SUCCESS;
25010 }
25011 
25012 static ma_result ma_get_AudioObject_uid(ma_context* pContext, AudioObjectID objectID, size_t bufferSize, char* bufferOut)
25013 {
25014  CFStringRef uid;
25015  ma_result result;
25016 
25017  MA_ASSERT(pContext != NULL);
25018 
25019  result = ma_get_AudioObject_uid_as_CFStringRef(pContext, objectID, &uid);
25020  if (result != MA_SUCCESS) {
25021  return result;
25022  }
25023 
25024  if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(uid, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
25025  return MA_ERROR;
25026  }
25027 
25028  ((ma_CFRelease_proc)pContext->coreaudio.CFRelease)(uid);
25029  return MA_SUCCESS;
25030 }
25031 
25032 static ma_result ma_get_AudioObject_name(ma_context* pContext, AudioObjectID objectID, size_t bufferSize, char* bufferOut)
25033 {
25034  AudioObjectPropertyAddress propAddress;
25035  CFStringRef deviceName = NULL;
25036  UInt32 dataSize;
25037  OSStatus status;
25038 
25039  MA_ASSERT(pContext != NULL);
25040 
25041  propAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
25042  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
25043  propAddress.mElement = kAudioObjectPropertyElementMaster;
25044 
25045  dataSize = sizeof(deviceName);
25046  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0, NULL, &dataSize, &deviceName);
25047  if (status != noErr) {
25048  return ma_result_from_OSStatus(status);
25049  }
25050 
25051  if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(deviceName, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
25052  return MA_ERROR;
25053  }
25054 
25055  ((ma_CFRelease_proc)pContext->coreaudio.CFRelease)(deviceName);
25056  return MA_SUCCESS;
25057 }
25058 
25059 static ma_bool32 ma_does_AudioObject_support_scope(ma_context* pContext, AudioObjectID deviceObjectID, AudioObjectPropertyScope scope)
25060 {
25061  AudioObjectPropertyAddress propAddress;
25062  UInt32 dataSize;
25063  OSStatus status;
25064  AudioBufferList* pBufferList;
25065  ma_bool32 isSupported;
25066 
25067  MA_ASSERT(pContext != NULL);
25068 
25069  /* 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. */
25070  propAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
25071  propAddress.mScope = scope;
25072  propAddress.mElement = kAudioObjectPropertyElementMaster;
25073 
25074  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
25075  if (status != noErr) {
25076  return MA_FALSE;
25077  }
25078 
25079  pBufferList = (AudioBufferList*)ma__malloc_from_callbacks(dataSize, &pContext->allocationCallbacks);
25080  if (pBufferList == NULL) {
25081  return MA_FALSE; /* Out of memory. */
25082  }
25083 
25084  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pBufferList);
25085  if (status != noErr) {
25086  ma__free_from_callbacks(pBufferList, &pContext->allocationCallbacks);
25087  return MA_FALSE;
25088  }
25089 
25090  isSupported = MA_FALSE;
25091  if (pBufferList->mNumberBuffers > 0) {
25092  isSupported = MA_TRUE;
25093  }
25094 
25095  ma__free_from_callbacks(pBufferList, &pContext->allocationCallbacks);
25096  return isSupported;
25097 }
25098 
25099 static ma_bool32 ma_does_AudioObject_support_playback(ma_context* pContext, AudioObjectID deviceObjectID)
25100 {
25101  return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeOutput);
25102 }
25103 
25104 static ma_bool32 ma_does_AudioObject_support_capture(ma_context* pContext, AudioObjectID deviceObjectID)
25105 {
25106  return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeInput);
25107 }
25108 
25109 
25110 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(). */
25111 {
25112  AudioObjectPropertyAddress propAddress;
25113  UInt32 dataSize;
25114  OSStatus status;
25115  AudioStreamRangedDescription* pDescriptions;
25116 
25117  MA_ASSERT(pContext != NULL);
25118  MA_ASSERT(pDescriptionCount != NULL);
25119  MA_ASSERT(ppDescriptions != NULL);
25120 
25121  /*
25122  TODO: Experiment with kAudioStreamPropertyAvailablePhysicalFormats instead of (or in addition to) kAudioStreamPropertyAvailableVirtualFormats. My
25123  MacBook Pro uses s24/32 format, however, which miniaudio does not currently support.
25124  */
25125  propAddress.mSelector = kAudioStreamPropertyAvailableVirtualFormats; /*kAudioStreamPropertyAvailablePhysicalFormats;*/
25126  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
25127  propAddress.mElement = kAudioObjectPropertyElementMaster;
25128 
25129  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
25130  if (status != noErr) {
25131  return ma_result_from_OSStatus(status);
25132  }
25133 
25134  pDescriptions = (AudioStreamRangedDescription*)ma_malloc(dataSize, &pContext->allocationCallbacks);
25135  if (pDescriptions == NULL) {
25136  return MA_OUT_OF_MEMORY;
25137  }
25138 
25139  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pDescriptions);
25140  if (status != noErr) {
25141  ma_free(pDescriptions, &pContext->allocationCallbacks);
25142  return ma_result_from_OSStatus(status);
25143  }
25144 
25145  *pDescriptionCount = dataSize / sizeof(*pDescriptions);
25146  *ppDescriptions = pDescriptions;
25147  return MA_SUCCESS;
25148 }
25149 
25150 
25151 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(). */
25152 {
25153  AudioObjectPropertyAddress propAddress;
25154  UInt32 dataSize;
25155  OSStatus status;
25156  AudioChannelLayout* pChannelLayout;
25157 
25158  MA_ASSERT(pContext != NULL);
25159  MA_ASSERT(ppChannelLayout != NULL);
25160 
25161  *ppChannelLayout = NULL; /* Safety. */
25162 
25163  propAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout;
25164  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
25165  propAddress.mElement = kAudioObjectPropertyElementMaster;
25166 
25167  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
25168  if (status != noErr) {
25169  return ma_result_from_OSStatus(status);
25170  }
25171 
25172  pChannelLayout = (AudioChannelLayout*)ma_malloc(dataSize, &pContext->allocationCallbacks);
25173  if (pChannelLayout == NULL) {
25174  return MA_OUT_OF_MEMORY;
25175  }
25176 
25177  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pChannelLayout);
25178  if (status != noErr) {
25179  ma_free(pChannelLayout, &pContext->allocationCallbacks);
25180  return ma_result_from_OSStatus(status);
25181  }
25182 
25183  *ppChannelLayout = pChannelLayout;
25184  return MA_SUCCESS;
25185 }
25186 
25187 static ma_result ma_get_AudioObject_channel_count(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_uint32* pChannelCount)
25188 {
25189  AudioChannelLayout* pChannelLayout;
25190  ma_result result;
25191 
25192  MA_ASSERT(pContext != NULL);
25193  MA_ASSERT(pChannelCount != NULL);
25194 
25195  *pChannelCount = 0; /* Safety. */
25196 
25197  result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
25198  if (result != MA_SUCCESS) {
25199  return result;
25200  }
25201 
25202  if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
25203  *pChannelCount = pChannelLayout->mNumberChannelDescriptions;
25204  } else if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
25205  *pChannelCount = ma_count_set_bits(pChannelLayout->mChannelBitmap);
25206  } else {
25207  *pChannelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
25208  }
25209 
25210  ma_free(pChannelLayout, &pContext->allocationCallbacks);
25211  return MA_SUCCESS;
25212 }
25213 
25214 #if 0
25215 static ma_result ma_get_AudioObject_channel_map(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_channel* pChannelMap, size_t channelMapCap)
25216 {
25217  AudioChannelLayout* pChannelLayout;
25218  ma_result result;
25219 
25220  MA_ASSERT(pContext != NULL);
25221 
25222  result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
25223  if (result != MA_SUCCESS) {
25224  return result; /* Rather than always failing here, would it be more robust to simply assume a default? */
25225  }
25226 
25227  result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, pChannelMap, channelMapCap);
25228  if (result != MA_SUCCESS) {
25229  ma_free(pChannelLayout, &pContext->allocationCallbacks);
25230  return result;
25231  }
25232 
25233  ma_free(pChannelLayout, &pContext->allocationCallbacks);
25234  return result;
25235 }
25236 #endif
25237 
25238 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(). */
25239 {
25240  AudioObjectPropertyAddress propAddress;
25241  UInt32 dataSize;
25242  OSStatus status;
25243  AudioValueRange* pSampleRateRanges;
25244 
25245  MA_ASSERT(pContext != NULL);
25246  MA_ASSERT(pSampleRateRangesCount != NULL);
25247  MA_ASSERT(ppSampleRateRanges != NULL);
25248 
25249  /* Safety. */
25250  *pSampleRateRangesCount = 0;
25251  *ppSampleRateRanges = NULL;
25252 
25253  propAddress.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
25254  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
25255  propAddress.mElement = kAudioObjectPropertyElementMaster;
25256 
25257  status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0, NULL, &dataSize);
25258  if (status != noErr) {
25259  return ma_result_from_OSStatus(status);
25260  }
25261 
25262  pSampleRateRanges = (AudioValueRange*)ma_malloc(dataSize, &pContext->allocationCallbacks);
25263  if (pSampleRateRanges == NULL) {
25264  return MA_OUT_OF_MEMORY;
25265  }
25266 
25267  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, pSampleRateRanges);
25268  if (status != noErr) {
25269  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25270  return ma_result_from_OSStatus(status);
25271  }
25272 
25273  *pSampleRateRangesCount = dataSize / sizeof(*pSampleRateRanges);
25274  *ppSampleRateRanges = pSampleRateRanges;
25275  return MA_SUCCESS;
25276 }
25277 
25278 #if 0
25279 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)
25280 {
25281  UInt32 sampleRateRangeCount;
25282  AudioValueRange* pSampleRateRanges;
25283  ma_result result;
25284 
25285  MA_ASSERT(pContext != NULL);
25286  MA_ASSERT(pSampleRateOut != NULL);
25287 
25288  *pSampleRateOut = 0; /* Safety. */
25289 
25290  result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
25291  if (result != MA_SUCCESS) {
25292  return result;
25293  }
25294 
25295  if (sampleRateRangeCount == 0) {
25296  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25297  return MA_ERROR; /* Should never hit this case should we? */
25298  }
25299 
25300  if (sampleRateIn == 0) {
25301  /* Search in order of miniaudio's preferred priority. */
25302  UInt32 iMALSampleRate;
25303  for (iMALSampleRate = 0; iMALSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iMALSampleRate) {
25304  ma_uint32 malSampleRate = g_maStandardSampleRatePriorities[iMALSampleRate];
25305  UInt32 iCASampleRate;
25306  for (iCASampleRate = 0; iCASampleRate < sampleRateRangeCount; ++iCASampleRate) {
25307  AudioValueRange caSampleRate = pSampleRateRanges[iCASampleRate];
25308  if (caSampleRate.mMinimum <= malSampleRate && caSampleRate.mMaximum >= malSampleRate) {
25309  *pSampleRateOut = malSampleRate;
25310  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25311  return MA_SUCCESS;
25312  }
25313  }
25314  }
25315 
25316  /*
25317  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
25318  case we just fall back to the first one reported by Core Audio.
25319  */
25320  MA_ASSERT(sampleRateRangeCount > 0);
25321 
25322  *pSampleRateOut = pSampleRateRanges[0].mMinimum;
25323  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25324  return MA_SUCCESS;
25325  } else {
25326  /* Find the closest match to this sample rate. */
25327  UInt32 currentAbsoluteDifference = INT32_MAX;
25328  UInt32 iCurrentClosestRange = (UInt32)-1;
25329  UInt32 iRange;
25330  for (iRange = 0; iRange < sampleRateRangeCount; ++iRange) {
25331  if (pSampleRateRanges[iRange].mMinimum <= sampleRateIn && pSampleRateRanges[iRange].mMaximum >= sampleRateIn) {
25332  *pSampleRateOut = sampleRateIn;
25333  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25334  return MA_SUCCESS;
25335  } else {
25336  UInt32 absoluteDifference;
25337  if (pSampleRateRanges[iRange].mMinimum > sampleRateIn) {
25338  absoluteDifference = pSampleRateRanges[iRange].mMinimum - sampleRateIn;
25339  } else {
25340  absoluteDifference = sampleRateIn - pSampleRateRanges[iRange].mMaximum;
25341  }
25342 
25343  if (currentAbsoluteDifference > absoluteDifference) {
25344  currentAbsoluteDifference = absoluteDifference;
25345  iCurrentClosestRange = iRange;
25346  }
25347  }
25348  }
25349 
25350  MA_ASSERT(iCurrentClosestRange != (UInt32)-1);
25351 
25352  *pSampleRateOut = pSampleRateRanges[iCurrentClosestRange].mMinimum;
25353  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25354  return MA_SUCCESS;
25355  }
25356 
25357  /* Should never get here, but it would mean we weren't able to find any suitable sample rates. */
25358  /*ma_free(pSampleRateRanges, &pContext->allocationCallbacks);*/
25359  /*return MA_ERROR;*/
25360 }
25361 #endif
25362 
25363 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)
25364 {
25365  AudioObjectPropertyAddress propAddress;
25366  AudioValueRange bufferSizeRange;
25367  UInt32 dataSize;
25368  OSStatus status;
25369 
25370  MA_ASSERT(pContext != NULL);
25371  MA_ASSERT(pBufferSizeInFramesOut != NULL);
25372 
25373  *pBufferSizeInFramesOut = 0; /* Safety. */
25374 
25375  propAddress.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
25376  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
25377  propAddress.mElement = kAudioObjectPropertyElementMaster;
25378 
25379  dataSize = sizeof(bufferSizeRange);
25380  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, &bufferSizeRange);
25381  if (status != noErr) {
25382  return ma_result_from_OSStatus(status);
25383  }
25384 
25385  /* This is just a clamp. */
25386  if (bufferSizeInFramesIn < bufferSizeRange.mMinimum) {
25387  *pBufferSizeInFramesOut = (ma_uint32)bufferSizeRange.mMinimum;
25388  } else if (bufferSizeInFramesIn > bufferSizeRange.mMaximum) {
25389  *pBufferSizeInFramesOut = (ma_uint32)bufferSizeRange.mMaximum;
25390  } else {
25391  *pBufferSizeInFramesOut = bufferSizeInFramesIn;
25392  }
25393 
25394  return MA_SUCCESS;
25395 }
25396 
25397 static ma_result ma_set_AudioObject_buffer_size_in_frames(ma_context* pContext, AudioObjectID deviceObjectID, ma_device_type deviceType, ma_uint32* pPeriodSizeInOut)
25398 {
25399  ma_result result;
25400  ma_uint32 chosenBufferSizeInFrames;
25401  AudioObjectPropertyAddress propAddress;
25402  UInt32 dataSize;
25403  OSStatus status;
25404 
25405  MA_ASSERT(pContext != NULL);
25406 
25407  result = ma_get_AudioObject_closest_buffer_size_in_frames(pContext, deviceObjectID, deviceType, *pPeriodSizeInOut, &chosenBufferSizeInFrames);
25408  if (result != MA_SUCCESS) {
25409  return result;
25410  }
25411 
25412  /* Try setting the size of the buffer... If this fails we just use whatever is currently set. */
25413  propAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
25414  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
25415  propAddress.mElement = kAudioObjectPropertyElementMaster;
25416 
25417  ((ma_AudioObjectSetPropertyData_proc)pContext->coreaudio.AudioObjectSetPropertyData)(deviceObjectID, &propAddress, 0, NULL, sizeof(chosenBufferSizeInFrames), &chosenBufferSizeInFrames);
25418 
25419  /* Get the actual size of the buffer. */
25420  dataSize = sizeof(*pPeriodSizeInOut);
25421  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0, NULL, &dataSize, &chosenBufferSizeInFrames);
25422  if (status != noErr) {
25423  return ma_result_from_OSStatus(status);
25424  }
25425 
25426  *pPeriodSizeInOut = chosenBufferSizeInFrames;
25427  return MA_SUCCESS;
25428 }
25429 
25430 static ma_result ma_find_default_AudioObjectID(ma_context* pContext, ma_device_type deviceType, AudioObjectID* pDeviceObjectID)
25431 {
25432  AudioObjectPropertyAddress propAddressDefaultDevice;
25433  UInt32 defaultDeviceObjectIDSize = sizeof(AudioObjectID);
25434  AudioObjectID defaultDeviceObjectID;
25435  OSStatus status;
25436 
25437  MA_ASSERT(pContext != NULL);
25438  MA_ASSERT(pDeviceObjectID != NULL);
25439 
25440  /* Safety. */
25441  *pDeviceObjectID = 0;
25442 
25443  propAddressDefaultDevice.mScope = kAudioObjectPropertyScopeGlobal;
25444  propAddressDefaultDevice.mElement = kAudioObjectPropertyElementMaster;
25445  if (deviceType == ma_device_type_playback) {
25446  propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
25447  } else {
25448  propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultInputDevice;
25449  }
25450 
25451  defaultDeviceObjectIDSize = sizeof(AudioObjectID);
25452  status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDefaultDevice, 0, NULL, &defaultDeviceObjectIDSize, &defaultDeviceObjectID);
25453  if (status == noErr) {
25454  *pDeviceObjectID = defaultDeviceObjectID;
25455  return MA_SUCCESS;
25456  }
25457 
25458  /* If we get here it means we couldn't find the device. */
25459  return MA_NO_DEVICE;
25460 }
25461 
25462 static ma_result ma_find_AudioObjectID(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, AudioObjectID* pDeviceObjectID)
25463 {
25464  MA_ASSERT(pContext != NULL);
25465  MA_ASSERT(pDeviceObjectID != NULL);
25466 
25467  /* Safety. */
25468  *pDeviceObjectID = 0;
25469 
25470  if (pDeviceID == NULL) {
25471  /* Default device. */
25472  return ma_find_default_AudioObjectID(pContext, deviceType, pDeviceObjectID);
25473  } else {
25474  /* Explicit device. */
25475  UInt32 deviceCount;
25476  AudioObjectID* pDeviceObjectIDs;
25477  ma_result result;
25478  UInt32 iDevice;
25479 
25480  result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
25481  if (result != MA_SUCCESS) {
25482  return result;
25483  }
25484 
25485  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
25486  AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
25487 
25488  char uid[256];
25489  if (ma_get_AudioObject_uid(pContext, deviceObjectID, sizeof(uid), uid) != MA_SUCCESS) {
25490  continue;
25491  }
25492 
25493  if (deviceType == ma_device_type_playback) {
25494  if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
25495  if (strcmp(uid, pDeviceID->coreaudio) == 0) {
25496  *pDeviceObjectID = deviceObjectID;
25497  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
25498  return MA_SUCCESS;
25499  }
25500  }
25501  } else {
25502  if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
25503  if (strcmp(uid, pDeviceID->coreaudio) == 0) {
25504  *pDeviceObjectID = deviceObjectID;
25505  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
25506  return MA_SUCCESS;
25507  }
25508  }
25509  }
25510  }
25511 
25512  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
25513  }
25514 
25515  /* If we get here it means we couldn't find the device. */
25516  return MA_NO_DEVICE;
25517 }
25518 
25519 
25520 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)
25521 {
25522  UInt32 deviceFormatDescriptionCount;
25523  AudioStreamRangedDescription* pDeviceFormatDescriptions;
25524  ma_result result;
25525  ma_uint32 desiredSampleRate;
25526  ma_uint32 desiredChannelCount;
25527  ma_format desiredFormat;
25528  AudioStreamBasicDescription bestDeviceFormatSoFar;
25529  ma_bool32 hasSupportedFormat;
25530  UInt32 iFormat;
25531 
25532  result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &deviceFormatDescriptionCount, &pDeviceFormatDescriptions);
25533  if (result != MA_SUCCESS) {
25534  return result;
25535  }
25536 
25537  desiredSampleRate = sampleRate;
25538  if (desiredSampleRate == 0) {
25539  desiredSampleRate = pOrigFormat->mSampleRate;
25540  }
25541 
25542  desiredChannelCount = channels;
25543  if (desiredChannelCount == 0) {
25544  desiredChannelCount = pOrigFormat->mChannelsPerFrame;
25545  }
25546 
25547  desiredFormat = format;
25548  if (desiredFormat == ma_format_unknown) {
25549  result = ma_format_from_AudioStreamBasicDescription(pOrigFormat, &desiredFormat);
25550  if (result != MA_SUCCESS || desiredFormat == ma_format_unknown) {
25551  desiredFormat = g_maFormatPriorities[0];
25552  }
25553  }
25554 
25555  /*
25556  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
25557  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.
25558  */
25559  MA_ZERO_OBJECT(&bestDeviceFormatSoFar);
25560 
25561  hasSupportedFormat = MA_FALSE;
25562  for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
25563  ma_format format;
25564  ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format);
25565  if (formatResult == MA_SUCCESS && format != ma_format_unknown) {
25566  hasSupportedFormat = MA_TRUE;
25567  bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
25568  break;
25569  }
25570  }
25571 
25572  if (!hasSupportedFormat) {
25573  ma_free(pDeviceFormatDescriptions, &pContext->allocationCallbacks);
25574  return MA_FORMAT_NOT_SUPPORTED;
25575  }
25576 
25577 
25578  for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
25579  AudioStreamBasicDescription thisDeviceFormat = pDeviceFormatDescriptions[iFormat].mFormat;
25580  ma_format thisSampleFormat;
25581  ma_result formatResult;
25582  ma_format bestSampleFormatSoFar;
25583 
25584  /* If the format is not supported by miniaudio we need to skip this one entirely. */
25585  formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &thisSampleFormat);
25586  if (formatResult != MA_SUCCESS || thisSampleFormat == ma_format_unknown) {
25587  continue; /* The format is not supported by miniaudio. Skip. */
25588  }
25589 
25590  ma_format_from_AudioStreamBasicDescription(&bestDeviceFormatSoFar, &bestSampleFormatSoFar);
25591 
25592  /* Getting here means the format is supported by miniaudio which makes this format a candidate. */
25593  if (thisDeviceFormat.mSampleRate != desiredSampleRate) {
25594  /*
25595  The sample rate does not match, but this format could still be usable, although it's a very low priority. If the best format
25596  so far has an equal sample rate we can just ignore this one.
25597  */
25598  if (bestDeviceFormatSoFar.mSampleRate == desiredSampleRate) {
25599  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. */
25600  } else {
25601  /* In this case, neither the best format so far nor this one have the same sample rate. Check the channel count next. */
25602  if (thisDeviceFormat.mChannelsPerFrame != desiredChannelCount) {
25603  /* This format has a different sample rate _and_ a different channel count. */
25604  if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
25605  continue; /* No change to the best format. */
25606  } else {
25607  /*
25608  Both this format and the best so far have different sample rates and different channel counts. Whichever has the
25609  best format is the new best.
25610  */
25611  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
25612  bestDeviceFormatSoFar = thisDeviceFormat;
25613  continue;
25614  } else {
25615  continue; /* No change to the best format. */
25616  }
25617  }
25618  } else {
25619  /* This format has a different sample rate but the desired channel count. */
25620  if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
25621  /* Both this format and the best so far have the desired channel count. Whichever has the best format is the new best. */
25622  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
25623  bestDeviceFormatSoFar = thisDeviceFormat;
25624  continue;
25625  } else {
25626  continue; /* No change to the best format for now. */
25627  }
25628  } else {
25629  /* This format has the desired channel count, but the best so far does not. We have a new best. */
25630  bestDeviceFormatSoFar = thisDeviceFormat;
25631  continue;
25632  }
25633  }
25634  }
25635  } else {
25636  /*
25637  The sample rates match which makes this format a very high priority contender. If the best format so far has a different
25638  sample rate it needs to be replaced with this one.
25639  */
25640  if (bestDeviceFormatSoFar.mSampleRate != desiredSampleRate) {
25641  bestDeviceFormatSoFar = thisDeviceFormat;
25642  continue;
25643  } else {
25644  /* In this case both this format and the best format so far have the same sample rate. Check the channel count next. */
25645  if (thisDeviceFormat.mChannelsPerFrame == desiredChannelCount) {
25646  /*
25647  In this case this format has the same channel count as what the client is requesting. If the best format so far has
25648  a different count, this one becomes the new best.
25649  */
25650  if (bestDeviceFormatSoFar.mChannelsPerFrame != desiredChannelCount) {
25651  bestDeviceFormatSoFar = thisDeviceFormat;
25652  continue;
25653  } else {
25654  /* In this case both this format and the best so far have the ideal sample rate and channel count. Check the format. */
25655  if (thisSampleFormat == desiredFormat) {
25656  bestDeviceFormatSoFar = thisDeviceFormat;
25657  break; /* Found the exact match. */
25658  } else {
25659  /* The formats are different. The new best format is the one with the highest priority format according to miniaudio. */
25660  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
25661  bestDeviceFormatSoFar = thisDeviceFormat;
25662  continue;
25663  } else {
25664  continue; /* No change to the best format for now. */
25665  }
25666  }
25667  }
25668  } else {
25669  /*
25670  In this case the channel count is different to what the client has requested. If the best so far has the same channel
25671  count as the requested count then it remains the best.
25672  */
25673  if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
25674  continue;
25675  } else {
25676  /*
25677  This is the case where both have the same sample rate (good) but different channel counts. Right now both have about
25678  the same priority, but we need to compare the format now.
25679  */
25680  if (thisSampleFormat == bestSampleFormatSoFar) {
25681  if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
25682  bestDeviceFormatSoFar = thisDeviceFormat;
25683  continue;
25684  } else {
25685  continue; /* No change to the best format for now. */
25686  }
25687  }
25688  }
25689  }
25690  }
25691  }
25692  }
25693 
25694  *pFormat = bestDeviceFormatSoFar;
25695 
25696  ma_free(pDeviceFormatDescriptions, &pContext->allocationCallbacks);
25697  return MA_SUCCESS;
25698 }
25699 
25700 static ma_result ma_get_AudioUnit_channel_map(ma_context* pContext, AudioUnit audioUnit, ma_device_type deviceType, ma_channel* pChannelMap, size_t channelMapCap)
25701 {
25702  AudioUnitScope deviceScope;
25703  AudioUnitElement deviceBus;
25704  UInt32 channelLayoutSize;
25705  OSStatus status;
25706  AudioChannelLayout* pChannelLayout;
25707  ma_result result;
25708 
25709  MA_ASSERT(pContext != NULL);
25710 
25711  if (deviceType == ma_device_type_playback) {
25712  deviceScope = kAudioUnitScope_Input;
25713  deviceBus = MA_COREAUDIO_OUTPUT_BUS;
25714  } else {
25715  deviceScope = kAudioUnitScope_Output;
25716  deviceBus = MA_COREAUDIO_INPUT_BUS;
25717  }
25718 
25719  status = ((ma_AudioUnitGetPropertyInfo_proc)pContext->coreaudio.AudioUnitGetPropertyInfo)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, &channelLayoutSize, NULL);
25720  if (status != noErr) {
25721  return ma_result_from_OSStatus(status);
25722  }
25723 
25724  pChannelLayout = (AudioChannelLayout*)ma__malloc_from_callbacks(channelLayoutSize, &pContext->allocationCallbacks);
25725  if (pChannelLayout == NULL) {
25726  return MA_OUT_OF_MEMORY;
25727  }
25728 
25729  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, pChannelLayout, &channelLayoutSize);
25730  if (status != noErr) {
25731  ma__free_from_callbacks(pChannelLayout, &pContext->allocationCallbacks);
25732  return ma_result_from_OSStatus(status);
25733  }
25734 
25735  result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, pChannelMap, channelMapCap);
25736  if (result != MA_SUCCESS) {
25737  ma__free_from_callbacks(pChannelLayout, &pContext->allocationCallbacks);
25738  return result;
25739  }
25740 
25741  ma__free_from_callbacks(pChannelLayout, &pContext->allocationCallbacks);
25742  return MA_SUCCESS;
25743 }
25744 #endif /* MA_APPLE_DESKTOP */
25745 
25746 
25747 #if !defined(MA_APPLE_DESKTOP)
25748 static void ma_AVAudioSessionPortDescription_to_device_info(AVAudioSessionPortDescription* pPortDesc, ma_device_info* pInfo)
25749 {
25750  MA_ZERO_OBJECT(pInfo);
25751  ma_strncpy_s(pInfo->name, sizeof(pInfo->name), [pPortDesc.portName UTF8String], (size_t)-1);
25752  ma_strncpy_s(pInfo->id.coreaudio, sizeof(pInfo->id.coreaudio), [pPortDesc.UID UTF8String], (size_t)-1);
25753 }
25754 #endif
25755 
25756 static ma_result ma_context_enumerate_devices__coreaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
25757 {
25758 #if defined(MA_APPLE_DESKTOP)
25759  UInt32 deviceCount;
25760  AudioObjectID* pDeviceObjectIDs;
25761  AudioObjectID defaultDeviceObjectIDPlayback;
25762  AudioObjectID defaultDeviceObjectIDCapture;
25763  ma_result result;
25764  UInt32 iDevice;
25765 
25766  ma_find_default_AudioObjectID(pContext, ma_device_type_playback, &defaultDeviceObjectIDPlayback); /* OK if this fails. */
25767  ma_find_default_AudioObjectID(pContext, ma_device_type_capture, &defaultDeviceObjectIDCapture); /* OK if this fails. */
25768 
25769  result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
25770  if (result != MA_SUCCESS) {
25771  return result;
25772  }
25773 
25774  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
25775  AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
25776  ma_device_info info;
25777 
25778  MA_ZERO_OBJECT(&info);
25779  if (ma_get_AudioObject_uid(pContext, deviceObjectID, sizeof(info.id.coreaudio), info.id.coreaudio) != MA_SUCCESS) {
25780  continue;
25781  }
25782  if (ma_get_AudioObject_name(pContext, deviceObjectID, sizeof(info.name), info.name) != MA_SUCCESS) {
25783  continue;
25784  }
25785 
25786  if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
25787  if (deviceObjectID == defaultDeviceObjectIDPlayback) {
25788  info.isDefault = MA_TRUE;
25789  }
25790 
25791  if (!callback(pContext, ma_device_type_playback, &info, pUserData)) {
25792  break;
25793  }
25794  }
25795  if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
25796  if (deviceObjectID == defaultDeviceObjectIDCapture) {
25797  info.isDefault = MA_TRUE;
25798  }
25799 
25800  if (!callback(pContext, ma_device_type_capture, &info, pUserData)) {
25801  break;
25802  }
25803  }
25804  }
25805 
25806  ma_free(pDeviceObjectIDs, &pContext->allocationCallbacks);
25807 #else
25808  ma_device_info info;
25809  NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
25810  NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
25811 
25812  for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
25813  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, &info);
25814  if (!callback(pContext, ma_device_type_playback, &info, pUserData)) {
25815  return MA_SUCCESS;
25816  }
25817  }
25818 
25819  for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
25820  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, &info);
25821  if (!callback(pContext, ma_device_type_capture, &info, pUserData)) {
25822  return MA_SUCCESS;
25823  }
25824  }
25825 #endif
25826 
25827  return MA_SUCCESS;
25828 }
25829 
25830 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)
25831 {
25832  ma_result result;
25833 
25834  MA_ASSERT(pContext != NULL);
25835 
25836 #if defined(MA_APPLE_DESKTOP)
25837  /* Desktop */
25838  {
25839  AudioObjectID deviceObjectID;
25840  AudioObjectID defaultDeviceObjectID;
25841  UInt32 streamDescriptionCount;
25842  AudioStreamRangedDescription* pStreamDescriptions;
25843  UInt32 iStreamDescription;
25844  UInt32 sampleRateRangeCount;
25845  AudioValueRange* pSampleRateRanges;
25846 
25847  ma_find_default_AudioObjectID(pContext, deviceType, &defaultDeviceObjectID); /* OK if this fails. */
25848 
25849  result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
25850  if (result != MA_SUCCESS) {
25851  return result;
25852  }
25853 
25854  result = ma_get_AudioObject_uid(pContext, deviceObjectID, sizeof(pDeviceInfo->id.coreaudio), pDeviceInfo->id.coreaudio);
25855  if (result != MA_SUCCESS) {
25856  return result;
25857  }
25858 
25859  result = ma_get_AudioObject_name(pContext, deviceObjectID, sizeof(pDeviceInfo->name), pDeviceInfo->name);
25860  if (result != MA_SUCCESS) {
25861  return result;
25862  }
25863 
25864  if (deviceObjectID == defaultDeviceObjectID) {
25865  pDeviceInfo->isDefault = MA_TRUE;
25866  }
25867 
25868  /*
25869  There could be a large number of permutations here. Fortunately there is only a single channel count
25870  being reported which reduces this quite a bit. For sample rates we're only reporting those that are
25871  one of miniaudio's recognized "standard" rates. If there are still more formats than can fit into
25872  our fixed sized array we'll just need to truncate them. This is unlikely and will probably only happen
25873  if some driver performs software data conversion and therefore reports every possible format and
25874  sample rate.
25875  */
25876  pDeviceInfo->nativeDataFormatCount = 0;
25877 
25878  /* Formats. */
25879  {
25880  ma_format uniqueFormats[ma_format_count];
25881  ma_uint32 uniqueFormatCount = 0;
25882  ma_uint32 channels;
25883 
25884  /* Channels. */
25885  result = ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &channels);
25886  if (result != MA_SUCCESS) {
25887  return result;
25888  }
25889 
25890  /* Formats. */
25891  result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &streamDescriptionCount, &pStreamDescriptions);
25892  if (result != MA_SUCCESS) {
25893  return result;
25894  }
25895 
25896  for (iStreamDescription = 0; iStreamDescription < streamDescriptionCount; ++iStreamDescription) {
25897  ma_format format;
25898  ma_bool32 hasFormatBeenHandled = MA_FALSE;
25899  ma_uint32 iOutputFormat;
25900  ma_uint32 iSampleRate;
25901 
25902  result = ma_format_from_AudioStreamBasicDescription(&pStreamDescriptions[iStreamDescription].mFormat, &format);
25903  if (result != MA_SUCCESS) {
25904  continue;
25905  }
25906 
25907  MA_ASSERT(format != ma_format_unknown);
25908 
25909  /* Make sure the format isn't already in the output list. */
25910  for (iOutputFormat = 0; iOutputFormat < uniqueFormatCount; ++iOutputFormat) {
25911  if (uniqueFormats[iOutputFormat] == format) {
25912  hasFormatBeenHandled = MA_TRUE;
25913  break;
25914  }
25915  }
25916 
25917  /* If we've already handled this format just skip it. */
25918  if (hasFormatBeenHandled) {
25919  continue;
25920  }
25921 
25922  uniqueFormats[uniqueFormatCount] = format;
25923  uniqueFormatCount += 1;
25924 
25925  /* Sample Rates */
25926  result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
25927  if (result != MA_SUCCESS) {
25928  return result;
25929  }
25930 
25931  /*
25932  Annoyingly Core Audio reports a sample rate range. We just get all the standard rates that are
25933  between this range.
25934  */
25935  for (iSampleRate = 0; iSampleRate < sampleRateRangeCount; ++iSampleRate) {
25936  ma_uint32 iStandardSampleRate;
25937  for (iStandardSampleRate = 0; iStandardSampleRate < ma_countof(g_maStandardSampleRatePriorities); iStandardSampleRate += 1) {
25938  ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iStandardSampleRate];
25939  if (standardSampleRate >= pSampleRateRanges[iSampleRate].mMinimum && standardSampleRate <= pSampleRateRanges[iSampleRate].mMaximum) {
25940  /* We have a new data format. Add it to the list. */
25941  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
25942  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
25943  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = standardSampleRate;
25944  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
25945  pDeviceInfo->nativeDataFormatCount += 1;
25946 
25947  if (pDeviceInfo->nativeDataFormatCount >= ma_countof(pDeviceInfo->nativeDataFormats)) {
25948  break; /* No more room for any more formats. */
25949  }
25950  }
25951  }
25952  }
25953 
25954  ma_free(pSampleRateRanges, &pContext->allocationCallbacks);
25955 
25956  if (pDeviceInfo->nativeDataFormatCount >= ma_countof(pDeviceInfo->nativeDataFormats)) {
25957  break; /* No more room for any more formats. */
25958  }
25959  }
25960 
25961  ma_free(pStreamDescriptions, &pContext->allocationCallbacks);
25962  }
25963  }
25964 #else
25965  /* Mobile */
25966  {
25967  AudioComponentDescription desc;
25968  AudioComponent component;
25969  AudioUnit audioUnit;
25970  OSStatus status;
25971  AudioUnitScope formatScope;
25972  AudioUnitElement formatElement;
25973  AudioStreamBasicDescription bestFormat;
25974  UInt32 propSize;
25975 
25976  /* We want to ensure we use a consistent device name to device enumeration. */
25977  if (pDeviceID != NULL) {
25978  ma_bool32 found = MA_FALSE;
25979  if (deviceType == ma_device_type_playback) {
25980  NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
25981  for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
25982  if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
25983  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
25984  found = MA_TRUE;
25985  break;
25986  }
25987  }
25988  } else {
25989  NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
25990  for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
25991  if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
25992  ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
25993  found = MA_TRUE;
25994  break;
25995  }
25996  }
25997  }
25998 
25999  if (!found) {
26000  return MA_DOES_NOT_EXIST;
26001  }
26002  } else {
26003  if (deviceType == ma_device_type_playback) {
26004  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
26005  } else {
26006  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
26007  }
26008  }
26009 
26010 
26011  /*
26012  Retrieving device information is more annoying on mobile than desktop. For simplicity I'm locking this down to whatever format is
26013  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
26014  retrieve from the AVAudioSession shared instance.
26015  */
26016  desc.componentType = kAudioUnitType_Output;
26017  desc.componentSubType = kAudioUnitSubType_RemoteIO;
26018  desc.componentManufacturer = kAudioUnitManufacturer_Apple;
26019  desc.componentFlags = 0;
26020  desc.componentFlagsMask = 0;
26021 
26022  component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc);
26023  if (component == NULL) {
26025  }
26026 
26027  status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)(component, &audioUnit);
26028  if (status != noErr) {
26029  return ma_result_from_OSStatus(status);
26030  }
26031 
26032  formatScope = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
26033  formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
26034 
26035  propSize = sizeof(bestFormat);
26036  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
26037  if (status != noErr) {
26038  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
26039  return ma_result_from_OSStatus(status);
26040  }
26041 
26042  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
26043  audioUnit = NULL;
26044 
26045  /* Only a single format is being reported for iOS. */
26046  pDeviceInfo->nativeDataFormatCount = 1;
26047 
26048  result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pDeviceInfo->nativeDataFormats[0].format);
26049  if (result != MA_SUCCESS) {
26050  return result;
26051  }
26052 
26053  pDeviceInfo->nativeDataFormats[0].channels = bestFormat.mChannelsPerFrame;
26054 
26055  /*
26056  It looks like Apple are wanting to push the whole AVAudioSession thing. Thus, we need to use that to determine device settings. To do
26057  this we just get the shared instance and inspect.
26058  */
26059  @autoreleasepool {
26060  AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
26061  MA_ASSERT(pAudioSession != NULL);
26062 
26063  pDeviceInfo->nativeDataFormats[0].sampleRate = (ma_uint32)pAudioSession.sampleRate;
26064  }
26065  }
26066 #endif
26067 
26068  (void)pDeviceInfo; /* Unused. */
26069  return MA_SUCCESS;
26070 }
26071 
26072 static AudioBufferList* ma_allocate_AudioBufferList__coreaudio(ma_uint32 sizeInFrames, ma_format format, ma_uint32 channels, ma_stream_layout layout, const ma_allocation_callbacks* pAllocationCallbacks)
26073 {
26074  AudioBufferList* pBufferList;
26075  UInt32 audioBufferSizeInBytes;
26076  size_t allocationSize;
26077 
26078  MA_ASSERT(sizeInFrames > 0);
26079  MA_ASSERT(format != ma_format_unknown);
26080  MA_ASSERT(channels > 0);
26081 
26082  allocationSize = sizeof(AudioBufferList) - sizeof(AudioBuffer); /* Subtract sizeof(AudioBuffer) because that part is dynamically sized. */
26083  if (layout == ma_stream_layout_interleaved) {
26084  /* Interleaved case. This is the simple case because we just have one buffer. */
26085  allocationSize += sizeof(AudioBuffer) * 1;
26086  } else {
26087  /* Non-interleaved case. This is the more complex case because there's more than one buffer. */
26088  allocationSize += sizeof(AudioBuffer) * channels;
26089  }
26090 
26091  allocationSize += sizeInFrames * ma_get_bytes_per_frame(format, channels);
26092 
26093  pBufferList = (AudioBufferList*)ma__malloc_from_callbacks(allocationSize, pAllocationCallbacks);
26094  if (pBufferList == NULL) {
26095  return NULL;
26096  }
26097 
26098  audioBufferSizeInBytes = (UInt32)(sizeInFrames * ma_get_bytes_per_sample(format));
26099 
26100  if (layout == ma_stream_layout_interleaved) {
26101  pBufferList->mNumberBuffers = 1;
26102  pBufferList->mBuffers[0].mNumberChannels = channels;
26103  pBufferList->mBuffers[0].mDataByteSize = audioBufferSizeInBytes * channels;
26104  pBufferList->mBuffers[0].mData = (ma_uint8*)pBufferList + sizeof(AudioBufferList);
26105  } else {
26106  ma_uint32 iBuffer;
26107  pBufferList->mNumberBuffers = channels;
26108  for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
26109  pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
26110  pBufferList->mBuffers[iBuffer].mDataByteSize = audioBufferSizeInBytes;
26111  pBufferList->mBuffers[iBuffer].mData = (ma_uint8*)pBufferList + ((sizeof(AudioBufferList) - sizeof(AudioBuffer)) + (sizeof(AudioBuffer) * channels)) + (audioBufferSizeInBytes * iBuffer);
26112  }
26113  }
26114 
26115  return pBufferList;
26116 }
26117 
26118 static ma_result ma_device_realloc_AudioBufferList__coreaudio(ma_device* pDevice, ma_uint32 sizeInFrames, ma_format format, ma_uint32 channels, ma_stream_layout layout)
26119 {
26120  MA_ASSERT(pDevice != NULL);
26121  MA_ASSERT(format != ma_format_unknown);
26122  MA_ASSERT(channels > 0);
26123 
26124  /* Only resize the buffer if necessary. */
26125  if (pDevice->coreaudio.audioBufferCapInFrames < sizeInFrames) {
26126  AudioBufferList* pNewAudioBufferList;
26127 
26128  pNewAudioBufferList = ma_allocate_AudioBufferList__coreaudio(sizeInFrames, format, channels, layout, &pDevice->pContext->allocationCallbacks);
26129  if (pNewAudioBufferList != NULL) {
26130  return MA_OUT_OF_MEMORY;
26131  }
26132 
26133  /* At this point we'll have a new AudioBufferList and we can free the old one. */
26134  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
26135  pDevice->coreaudio.pAudioBufferList = pNewAudioBufferList;
26136  pDevice->coreaudio.audioBufferCapInFrames = sizeInFrames;
26137  }
26138 
26139  /* Getting here means the capacity of the audio is fine. */
26140  return MA_SUCCESS;
26141 }
26142 
26143 
26144 static OSStatus ma_on_output__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pActionFlags, const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufferList)
26145 {
26146  ma_device* pDevice = (ma_device*)pUserData;
26147  ma_stream_layout layout;
26148 
26149  MA_ASSERT(pDevice != NULL);
26150 
26151  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);
26152 
26153  /* 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. */
26155  if (pBufferList->mBuffers[0].mNumberChannels != pDevice->playback.internalChannels) {
26157  }
26158 
26159  if (layout == ma_stream_layout_interleaved) {
26160  /* For now we can assume everything is interleaved. */
26161  UInt32 iBuffer;
26162  for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
26163  if (pBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->playback.internalChannels) {
26164  ma_uint32 frameCountForThisBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
26165  if (frameCountForThisBuffer > 0) {
26166  ma_device_handle_backend_data_callback(pDevice, pBufferList->mBuffers[iBuffer].mData, NULL, frameCountForThisBuffer);
26167  }
26168 
26169  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);
26170  } else {
26171  /*
26172  This case is where the number of channels in the output buffer do not match our internal channels. It could mean that it's
26173  not interleaved, in which case we can't handle right now since miniaudio does not yet support non-interleaved streams. We just
26174  output silence here.
26175  */
26176  MA_ZERO_MEMORY(pBufferList->mBuffers[iBuffer].mData, pBufferList->mBuffers[iBuffer].mDataByteSize);
26177  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);
26178  }
26179  }
26180  } else {
26181  /* This is the deinterleaved case. We need to update each buffer in groups of internalChannels. This assumes each buffer is the same size. */
26182  MA_ASSERT(pDevice->playback.internalChannels <= MA_MAX_CHANNELS); /* This should heve been validated at initialization time. */
26183 
26184  /*
26185  For safety we'll check that the internal channels is a multiple of the buffer count. If it's not it means something
26186  very strange has happened and we're not going to support it.
26187  */
26188  if ((pBufferList->mNumberBuffers % pDevice->playback.internalChannels) == 0) {
26189  ma_uint8 tempBuffer[4096];
26190  UInt32 iBuffer;
26191 
26192  for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; iBuffer += pDevice->playback.internalChannels) {
26193  ma_uint32 frameCountPerBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / ma_get_bytes_per_sample(pDevice->playback.internalFormat);
26194  ma_uint32 framesRemaining = frameCountPerBuffer;
26195 
26196  while (framesRemaining > 0) {
26197  void* ppDeinterleavedBuffers[MA_MAX_CHANNELS];
26198  ma_uint32 iChannel;
26199  ma_uint32 framesToRead = sizeof(tempBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
26200  if (framesToRead > framesRemaining) {
26201  framesToRead = framesRemaining;
26202  }
26203 
26204  ma_device_handle_backend_data_callback(pDevice, tempBuffer, NULL, framesToRead);
26205 
26206  for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
26207  ppDeinterleavedBuffers[iChannel] = (void*)ma_offset_ptr(pBufferList->mBuffers[iBuffer+iChannel].mData, (frameCountPerBuffer - framesRemaining) * ma_get_bytes_per_sample(pDevice->playback.internalFormat));
26208  }
26209 
26210  ma_deinterleave_pcm_frames(pDevice->playback.internalFormat, pDevice->playback.internalChannels, framesToRead, tempBuffer, ppDeinterleavedBuffers);
26211 
26212  framesRemaining -= framesToRead;
26213  }
26214  }
26215  }
26216  }
26217 
26218  (void)pActionFlags;
26219  (void)pTimeStamp;
26220  (void)busNumber;
26221  (void)frameCount;
26222 
26223  return noErr;
26224 }
26225 
26226 static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFlags* pActionFlags, const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pUnusedBufferList)
26227 {
26228  ma_device* pDevice = (ma_device*)pUserData;
26229  AudioBufferList* pRenderedBufferList;
26230  ma_result result;
26231  ma_stream_layout layout;
26232  ma_uint32 iBuffer;
26233  OSStatus status;
26234 
26235  MA_ASSERT(pDevice != NULL);
26236 
26237  pRenderedBufferList = (AudioBufferList*)pDevice->coreaudio.pAudioBufferList;
26238  MA_ASSERT(pRenderedBufferList);
26239 
26240  /* 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. */
26242  if (pRenderedBufferList->mBuffers[0].mNumberChannels != pDevice->capture.internalChannels) {
26244  }
26245 
26246  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);
26247 
26248  /*
26249  There has been a situation reported where frame count passed into this function is greater than the capacity of
26250  our capture buffer. There doesn't seem to be a reliable way to determine what the maximum frame count will be,
26251  so we need to instead resort to dynamically reallocating our buffer to ensure it's large enough to capture the
26252  number of frames requested by this callback.
26253  */
26254  result = ma_device_realloc_AudioBufferList__coreaudio(pDevice, frameCount, pDevice->capture.internalFormat, pDevice->capture.internalChannels, layout);
26255  if (result != MA_SUCCESS) {
26256  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "Failed to allocate AudioBufferList for capture.");
26257  return noErr;
26258  }
26259 
26260  /*
26261  When you call AudioUnitRender(), Core Audio tries to be helpful by setting the mDataByteSize to the number of bytes
26262  that were actually rendered. The problem with this is that the next call can fail with -50 due to the size no longer
26263  being set to the capacity of the buffer, but instead the size in bytes of the previous render. This will cause a
26264  problem when a future call to this callback specifies a larger number of frames.
26265 
26266  To work around this we need to explicitly set the size of each buffer to their respective size in bytes.
26267  */
26268  for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
26269  pRenderedBufferList->mBuffers[iBuffer].mDataByteSize = pDevice->coreaudio.audioBufferCapInFrames * ma_get_bytes_per_sample(pDevice->capture.internalFormat) * pRenderedBufferList->mBuffers[iBuffer].mNumberChannels;
26270  }
26271 
26272  status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList);
26273  if (status != noErr) {
26274  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " ERROR: AudioUnitRender() failed with %d\n", status);
26275  return status;
26276  }
26277 
26278  if (layout == ma_stream_layout_interleaved) {
26279  for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
26280  if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->capture.internalChannels) {
26281  ma_device_handle_backend_data_callback(pDevice, NULL, pRenderedBufferList->mBuffers[iBuffer].mData, frameCount);
26282  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " mDataByteSize=%d\n", pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
26283  } else {
26284  /*
26285  This case is where the number of channels in the output buffer do not match our internal channels. It could mean that it's
26286  not interleaved, in which case we can't handle right now since miniaudio does not yet support non-interleaved streams.
26287  */
26288  ma_uint8 silentBuffer[4096];
26289  ma_uint32 framesRemaining;
26290 
26291  MA_ZERO_MEMORY(silentBuffer, sizeof(silentBuffer));
26292 
26293  framesRemaining = frameCount;
26294  while (framesRemaining > 0) {
26295  ma_uint32 framesToSend = sizeof(silentBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
26296  if (framesToSend > framesRemaining) {
26297  framesToSend = framesRemaining;
26298  }
26299 
26300  ma_device_handle_backend_data_callback(pDevice, NULL, silentBuffer, framesToSend);
26301 
26302  framesRemaining -= framesToSend;
26303  }
26304 
26305  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);
26306  }
26307  }
26308  } else {
26309  /* 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. */
26310  MA_ASSERT(pDevice->capture.internalChannels <= MA_MAX_CHANNELS); /* This should have been validated at initialization time. */
26311 
26312  /*
26313  For safety we'll check that the internal channels is a multiple of the buffer count. If it's not it means something
26314  very strange has happened and we're not going to support it.
26315  */
26316  if ((pRenderedBufferList->mNumberBuffers % pDevice->capture.internalChannels) == 0) {
26317  ma_uint8 tempBuffer[4096];
26318  for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; iBuffer += pDevice->capture.internalChannels) {
26319  ma_uint32 framesRemaining = frameCount;
26320  while (framesRemaining > 0) {
26321  void* ppDeinterleavedBuffers[MA_MAX_CHANNELS];
26322  ma_uint32 iChannel;
26323  ma_uint32 framesToSend = sizeof(tempBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
26324  if (framesToSend > framesRemaining) {
26325  framesToSend = framesRemaining;
26326  }
26327 
26328  for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
26329  ppDeinterleavedBuffers[iChannel] = (void*)ma_offset_ptr(pRenderedBufferList->mBuffers[iBuffer+iChannel].mData, (frameCount - framesRemaining) * ma_get_bytes_per_sample(pDevice->capture.internalFormat));
26330  }
26331 
26332  ma_interleave_pcm_frames(pDevice->capture.internalFormat, pDevice->capture.internalChannels, framesToSend, (const void**)ppDeinterleavedBuffers, tempBuffer);
26333  ma_device_handle_backend_data_callback(pDevice, NULL, tempBuffer, framesToSend);
26334 
26335  framesRemaining -= framesToSend;
26336  }
26337  }
26338  }
26339  }
26340 
26341  (void)pActionFlags;
26342  (void)pTimeStamp;
26343  (void)busNumber;
26344  (void)frameCount;
26345  (void)pUnusedBufferList;
26346 
26347  return noErr;
26348 }
26349 
26350 static void on_start_stop__coreaudio(void* pUserData, AudioUnit audioUnit, AudioUnitPropertyID propertyID, AudioUnitScope scope, AudioUnitElement element)
26351 {
26352  ma_device* pDevice = (ma_device*)pUserData;
26353  MA_ASSERT(pDevice != NULL);
26354 
26355  /* Don't do anything if it looks like we're just reinitializing due to a device switch. */
26356  if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isSwitchingPlaybackDevice) ||
26357  ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isSwitchingCaptureDevice)) {
26358  return;
26359  }
26360 
26361  /*
26362  There's been a report of a deadlock here when triggered by ma_device_uninit(). It looks like
26363  AudioUnitGetProprty (called below) and AudioComponentInstanceDispose (called in ma_device_uninit)
26364  can try waiting on the same lock. I'm going to try working around this by not calling any Core
26365  Audio APIs in the callback when the device has been stopped or uninitialized.
26366  */
26368  ma_stop_proc onStop = pDevice->onStop;
26369  if (onStop) {
26370  onStop(pDevice);
26371  }
26372 
26373  ma_event_signal(&pDevice->coreaudio.stopEvent);
26374  } else {
26375  UInt32 isRunning;
26376  UInt32 isRunningSize = sizeof(isRunning);
26377  OSStatus status = ((ma_AudioUnitGetProperty_proc)pDevice->pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioOutputUnitProperty_IsRunning, scope, element, &isRunning, &isRunningSize);
26378  if (status != noErr) {
26379  return; /* Don't really know what to do in this case... just ignore it, I suppose... */
26380  }
26381 
26382  if (!isRunning) {
26383  ma_stop_proc onStop;
26384 
26385  /*
26386  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:
26387 
26388  1) When the device is unplugged, this will be called _before_ the default device change notification.
26389  2) When the device is changed via the default device change notification, this will be called _after_ the switch.
26390 
26391  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.
26392  */
26393  if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isDefaultPlaybackDevice) ||
26394  ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isDefaultCaptureDevice)) {
26395  /*
26396  It looks like the device is switching through an external event, such as the user unplugging the device or changing the default device
26397  via the operating system's sound settings. If we're re-initializing the device, we just terminate because we want the stopping of the
26398  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
26399  hasn't!).
26400  */
26401  if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isSwitchingPlaybackDevice) ||
26402  ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isSwitchingCaptureDevice)) {
26403  return;
26404  }
26405 
26406  /*
26407  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
26408  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
26409  likely be successful in switching to the new device.
26410 
26411  TODO: Try to predict if Core Audio will switch devices. If not, the onStop callback needs to be posted.
26412  */
26413  return;
26414  }
26415 
26416  /* Getting here means we need to stop the device. */
26417  onStop = pDevice->onStop;
26418  if (onStop) {
26419  onStop(pDevice);
26420  }
26421  }
26422  }
26423 
26424  (void)propertyID; /* Unused. */
26425 }
26426 
26427 #if defined(MA_APPLE_DESKTOP)
26428 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. */
26429 static ma_uint32 g_DeviceTrackingInitCounter_CoreAudio = 0;
26430 static ma_mutex g_DeviceTrackingMutex_CoreAudio;
26431 static ma_device** g_ppTrackedDevices_CoreAudio = NULL;
26432 static ma_uint32 g_TrackedDeviceCap_CoreAudio = 0;
26433 static ma_uint32 g_TrackedDeviceCount_CoreAudio = 0;
26434 
26435 static OSStatus ma_default_device_changed__coreaudio(AudioObjectID objectID, UInt32 addressCount, const AudioObjectPropertyAddress* pAddresses, void* pUserData)
26436 {
26437  ma_device_type deviceType;
26438 
26439  /* Not sure if I really need to check this, but it makes me feel better. */
26440  if (addressCount == 0) {
26441  return noErr;
26442  }
26443 
26444  if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultOutputDevice) {
26445  deviceType = ma_device_type_playback;
26446  } else if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultInputDevice) {
26447  deviceType = ma_device_type_capture;
26448  } else {
26449  return noErr; /* Should never hit this. */
26450  }
26451 
26452  ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
26453  {
26454  ma_uint32 iDevice;
26455  for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
26456  ma_result reinitResult;
26457  ma_device* pDevice;
26458 
26459  pDevice = g_ppTrackedDevices_CoreAudio[iDevice];
26460  if (pDevice->type == deviceType || pDevice->type == ma_device_type_duplex) {
26461  if (deviceType == ma_device_type_playback) {
26462  pDevice->coreaudio.isSwitchingPlaybackDevice = MA_TRUE;
26463  reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType, MA_TRUE);
26464  pDevice->coreaudio.isSwitchingPlaybackDevice = MA_FALSE;
26465  } else {
26466  pDevice->coreaudio.isSwitchingCaptureDevice = MA_TRUE;
26467  reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType, MA_TRUE);
26468  pDevice->coreaudio.isSwitchingCaptureDevice = MA_FALSE;
26469  }
26470 
26471  if (reinitResult == MA_SUCCESS) {
26472  ma_device__post_init_setup(pDevice, deviceType);
26473 
26474  /* Restart the device if required. If this fails we need to stop the device entirely. */
26475  if (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
26476  OSStatus status;
26477  if (deviceType == ma_device_type_playback) {
26478  status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
26479  if (status != noErr) {
26480  if (pDevice->type == ma_device_type_duplex) {
26481  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
26482  }
26484  }
26485  } else if (deviceType == ma_device_type_capture) {
26486  status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
26487  if (status != noErr) {
26488  if (pDevice->type == ma_device_type_duplex) {
26489  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
26490  }
26492  }
26493  }
26494  }
26495  }
26496  }
26497  }
26498  }
26499  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
26500 
26501  /* Unused parameters. */
26502  (void)objectID;
26503  (void)pUserData;
26504 
26505  return noErr;
26506 }
26507 
26508 static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContext)
26509 {
26510  MA_ASSERT(pContext != NULL);
26511 
26512  ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
26513  {
26514  /* Don't do anything if we've already initializd device tracking. */
26515  if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
26516  AudioObjectPropertyAddress propAddress;
26517  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
26518  propAddress.mElement = kAudioObjectPropertyElementMaster;
26519 
26520  ma_mutex_init(&g_DeviceTrackingMutex_CoreAudio);
26521 
26522  propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
26523  ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
26524 
26525  propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
26526  ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
26527 
26528  }
26529  g_DeviceTrackingInitCounter_CoreAudio += 1;
26530  }
26531  ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
26532 
26533  return MA_SUCCESS;
26534 }
26535 
26536 static ma_result ma_context__uninit_device_tracking__coreaudio(ma_context* pContext)
26537 {
26538  MA_ASSERT(pContext != NULL);
26539 
26540  ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio);
26541  {
26542  if (g_DeviceTrackingInitCounter_CoreAudio > 0)
26543  g_DeviceTrackingInitCounter_CoreAudio -= 1;
26544 
26545  if (g_DeviceTrackingInitCounter_CoreAudio == 0) {
26546  AudioObjectPropertyAddress propAddress;
26547  propAddress.mScope = kAudioObjectPropertyScopeGlobal;
26548  propAddress.mElement = kAudioObjectPropertyElementMaster;
26549 
26550  propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
26551  ((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
26552 
26553  propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
26554  ((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, NULL);
26555 
26556  /* At this point there should be no tracked devices. If not there's an error somewhere. */
26557  if (g_ppTrackedDevices_CoreAudio != NULL) {
26558  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);
26559  ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
26560  return MA_INVALID_OPERATION;
26561  }
26562 
26563  ma_mutex_uninit(&g_DeviceTrackingMutex_CoreAudio);
26564  }
26565  }
26566  ma_spinlock_unlock(&g_DeviceTrackingInitLock_CoreAudio);
26567 
26568  return MA_SUCCESS;
26569 }
26570 
26571 static ma_result ma_device__track__coreaudio(ma_device* pDevice)
26572 {
26573  MA_ASSERT(pDevice != NULL);
26574 
26575  ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
26576  {
26577  /* Allocate memory if required. */
26578  if (g_TrackedDeviceCap_CoreAudio <= g_TrackedDeviceCount_CoreAudio) {
26579  ma_uint32 oldCap;
26580  ma_uint32 newCap;
26581  ma_device** ppNewDevices;
26582 
26583  oldCap = g_TrackedDeviceCap_CoreAudio;
26584  newCap = g_TrackedDeviceCap_CoreAudio * 2;
26585  if (newCap == 0) {
26586  newCap = 1;
26587  }
26588 
26589  ppNewDevices = (ma_device**)ma__realloc_from_callbacks(g_ppTrackedDevices_CoreAudio, sizeof(*g_ppTrackedDevices_CoreAudio)*newCap, sizeof(*g_ppTrackedDevices_CoreAudio)*oldCap, &pDevice->pContext->allocationCallbacks);
26590  if (ppNewDevices == NULL) {
26591  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
26592  return MA_OUT_OF_MEMORY;
26593  }
26594 
26595  g_ppTrackedDevices_CoreAudio = ppNewDevices;
26596  g_TrackedDeviceCap_CoreAudio = newCap;
26597  }
26598 
26599  g_ppTrackedDevices_CoreAudio[g_TrackedDeviceCount_CoreAudio] = pDevice;
26600  g_TrackedDeviceCount_CoreAudio += 1;
26601  }
26602  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
26603 
26604  return MA_SUCCESS;
26605 }
26606 
26607 static ma_result ma_device__untrack__coreaudio(ma_device* pDevice)
26608 {
26609  MA_ASSERT(pDevice != NULL);
26610 
26611  ma_mutex_lock(&g_DeviceTrackingMutex_CoreAudio);
26612  {
26613  ma_uint32 iDevice;
26614  for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
26615  if (g_ppTrackedDevices_CoreAudio[iDevice] == pDevice) {
26616  /* We've found the device. We now need to remove it from the list. */
26617  ma_uint32 jDevice;
26618  for (jDevice = iDevice; jDevice < g_TrackedDeviceCount_CoreAudio-1; jDevice += 1) {
26619  g_ppTrackedDevices_CoreAudio[jDevice] = g_ppTrackedDevices_CoreAudio[jDevice+1];
26620  }
26621 
26622  g_TrackedDeviceCount_CoreAudio -= 1;
26623 
26624  /* If there's nothing else in the list we need to free memory. */
26625  if (g_TrackedDeviceCount_CoreAudio == 0) {
26626  ma__free_from_callbacks(g_ppTrackedDevices_CoreAudio, &pDevice->pContext->allocationCallbacks);
26627  g_ppTrackedDevices_CoreAudio = NULL;
26628  g_TrackedDeviceCap_CoreAudio = 0;
26629  }
26630 
26631  break;
26632  }
26633  }
26634  }
26635  ma_mutex_unlock(&g_DeviceTrackingMutex_CoreAudio);
26636 
26637  return MA_SUCCESS;
26638 }
26639 #endif
26640 
26641 #if defined(MA_APPLE_MOBILE)
26642 @interface ma_router_change_handler:NSObject {
26643  ma_device* m_pDevice;
26644 }
26645 @end
26646 
26647 @implementation ma_router_change_handler
26648 -(id)init:(ma_device*)pDevice
26649 {
26650  self = [super init];
26651  m_pDevice = pDevice;
26652 
26653  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle_route_change:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
26654 
26655  return self;
26656 }
26657 
26658 -(void)dealloc
26659 {
26660  [self remove_handler];
26661 }
26662 
26663 -(void)remove_handler
26664 {
26665  [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionRouteChangeNotification object:nil];
26666 }
26667 
26668 -(void)handle_route_change:(NSNotification*)pNotification
26669 {
26670  AVAudioSession* pSession = [AVAudioSession sharedInstance];
26671 
26672  NSInteger reason = [[[pNotification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
26673  switch (reason)
26674  {
26675  case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
26676  {
26677  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonOldDeviceUnavailable\n");
26678  } break;
26679 
26680  case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
26681  {
26682  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonNewDeviceAvailable\n");
26683  } break;
26684 
26685  case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
26686  {
26687  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory\n");
26688  } break;
26689 
26690  case AVAudioSessionRouteChangeReasonWakeFromSleep:
26691  {
26692  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonWakeFromSleep\n");
26693  } break;
26694 
26695  case AVAudioSessionRouteChangeReasonOverride:
26696  {
26697  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonOverride\n");
26698  } break;
26699 
26700  case AVAudioSessionRouteChangeReasonCategoryChange:
26701  {
26702  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonCategoryChange\n");
26703  } break;
26704 
26705  case AVAudioSessionRouteChangeReasonUnknown:
26706  default:
26707  {
26708  ma_log_postf(ma_device_get_log(m_pDevice), MA_LOG_LEVEL_DEBUG, "[Core Audio] Route Changed: AVAudioSessionRouteChangeReasonUnknown\n");
26709  } break;
26710  }
26711 
26712  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);
26713 
26714  /* Temporarily disabling this section of code because it appears to be causing errors. */
26715 #if 0
26716  ma_uint32 previousState = ma_device_get_state(m_pDevice);
26717 
26718  if (previousState == MA_STATE_STARTED) {
26719  ma_device_stop(m_pDevice);
26720  }
26721 
26722  if (m_pDevice->type == ma_device_type_capture || m_pDevice->type == ma_device_type_duplex) {
26723  m_pDevice->capture.internalChannels = (ma_uint32)pSession.inputNumberOfChannels;
26724  m_pDevice->capture.internalSampleRate = (ma_uint32)pSession.sampleRate;
26726  }
26727  if (m_pDevice->type == ma_device_type_playback || m_pDevice->type == ma_device_type_duplex) {
26728  m_pDevice->playback.internalChannels = (ma_uint32)pSession.outputNumberOfChannels;
26729  m_pDevice->playback.internalSampleRate = (ma_uint32)pSession.sampleRate;
26731  }
26732 
26733  if (previousState == MA_STATE_STARTED) {
26734  ma_device_start(m_pDevice);
26735  }
26736 #endif
26737 }
26738 @end
26739 #endif
26740 
26741 static ma_result ma_device_uninit__coreaudio(ma_device* pDevice)
26742 {
26743  MA_ASSERT(pDevice != NULL);
26745 
26746 #if defined(MA_APPLE_DESKTOP)
26747  /*
26748  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
26749  just gracefully ignore it.
26750  */
26751  ma_device__untrack__coreaudio(pDevice);
26752 #endif
26753 #if defined(MA_APPLE_MOBILE)
26754  if (pDevice->coreaudio.pRouteChangeHandler != NULL) {
26755  ma_router_change_handler* pRouteChangeHandler = (__bridge_transfer ma_router_change_handler*)pDevice->coreaudio.pRouteChangeHandler;
26756  [pRouteChangeHandler remove_handler];
26757  }
26758 #endif
26759 
26760  if (pDevice->coreaudio.audioUnitCapture != NULL) {
26761  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
26762  }
26763  if (pDevice->coreaudio.audioUnitPlayback != NULL) {
26764  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
26765  }
26766 
26767  if (pDevice->coreaudio.pAudioBufferList) {
26768  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
26769  }
26770 
26771  return MA_SUCCESS;
26772 }
26773 
26774 typedef struct
26775 {
26776  ma_bool32 allowNominalSampleRateChange;
26777 
26778  /* Input. */
26779  ma_format formatIn;
26780  ma_uint32 channelsIn;
26781  ma_uint32 sampleRateIn;
26782  ma_channel channelMapIn[MA_MAX_CHANNELS];
26783  ma_uint32 periodSizeInFramesIn;
26784  ma_uint32 periodSizeInMillisecondsIn;
26785  ma_uint32 periodsIn;
26786  ma_share_mode shareMode;
26787  ma_performance_profile performanceProfile;
26788  ma_bool32 registerStopEvent;
26789 
26790  /* Output. */
26791 #if defined(MA_APPLE_DESKTOP)
26792  AudioObjectID deviceObjectID;
26793 #endif
26794  AudioComponent component;
26795  AudioUnit audioUnit;
26796  AudioBufferList* pAudioBufferList; /* Only used for input devices. */
26797  ma_format formatOut;
26798  ma_uint32 channelsOut;
26799  ma_uint32 sampleRateOut;
26800  ma_channel channelMapOut[MA_MAX_CHANNELS];
26801  ma_uint32 periodSizeInFramesOut;
26802  ma_uint32 periodsOut;
26803  char deviceName[256];
26804 } ma_device_init_internal_data__coreaudio;
26805 
26806 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. */
26807 {
26808  ma_result result;
26809  OSStatus status;
26810  UInt32 enableIOFlag;
26811  AudioStreamBasicDescription bestFormat;
26812  UInt32 actualPeriodSizeInFrames;
26813  AURenderCallbackStruct callbackInfo;
26814 #if defined(MA_APPLE_DESKTOP)
26815  AudioObjectID deviceObjectID;
26816 #else
26817  UInt32 actualPeriodSizeInFramesSize = sizeof(actualPeriodSizeInFrames);
26818 #endif
26819 
26820  /* This API should only be used for a single device type: playback or capture. No full-duplex mode. */
26821  if (deviceType == ma_device_type_duplex) {
26822  return MA_INVALID_ARGS;
26823  }
26824 
26825  MA_ASSERT(pContext != NULL);
26826  MA_ASSERT(deviceType == ma_device_type_playback || deviceType == ma_device_type_capture);
26827 
26828 #if defined(MA_APPLE_DESKTOP)
26829  pData->deviceObjectID = 0;
26830 #endif
26831  pData->component = NULL;
26832  pData->audioUnit = NULL;
26833  pData->pAudioBufferList = NULL;
26834 
26835 #if defined(MA_APPLE_DESKTOP)
26836  result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
26837  if (result != MA_SUCCESS) {
26838  return result;
26839  }
26840 
26841  pData->deviceObjectID = deviceObjectID;
26842 #endif
26843 
26844  /* Core audio doesn't really use the notion of a period so we can leave this unmodified, but not too over the top. */
26845  pData->periodsOut = pData->periodsIn;
26846  if (pData->periodsOut == 0) {
26847  pData->periodsOut = MA_DEFAULT_PERIODS;
26848  }
26849  if (pData->periodsOut > 16) {
26850  pData->periodsOut = 16;
26851  }
26852 
26853 
26854  /* Audio unit. */
26855  status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)((AudioComponent)pContext->coreaudio.component, (AudioUnit*)&pData->audioUnit);
26856  if (status != noErr) {
26857  return ma_result_from_OSStatus(status);
26858  }
26859 
26860 
26861  /* 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. */
26862  enableIOFlag = 1;
26863  if (deviceType == ma_device_type_capture) {
26864  enableIOFlag = 0;
26865  }
26866 
26867  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &enableIOFlag, sizeof(enableIOFlag));
26868  if (status != noErr) {
26869  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
26870  return ma_result_from_OSStatus(status);
26871  }
26872 
26873  enableIOFlag = (enableIOFlag == 0) ? 1 : 0;
26874  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &enableIOFlag, sizeof(enableIOFlag));
26875  if (status != noErr) {
26876  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
26877  return ma_result_from_OSStatus(status);
26878  }
26879 
26880 
26881  /* Set the device to use with this audio unit. This is only used on desktop since we are using defaults on mobile. */
26882 #if defined(MA_APPLE_DESKTOP)
26883  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceObjectID, sizeof(deviceObjectID));
26884  if (status != noErr) {
26885  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
26886  return ma_result_from_OSStatus(result);
26887  }
26888 #else
26889  /*
26890  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
26891  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.
26892  */
26893  if (pDeviceID != NULL) {
26894  if (deviceType == ma_device_type_capture) {
26895  ma_bool32 found = MA_FALSE;
26896  NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
26897  for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
26898  if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
26899  [[AVAudioSession sharedInstance] setPreferredInput:pPortDesc error:nil];
26900  found = MA_TRUE;
26901  break;
26902  }
26903  }
26904 
26905  if (found == MA_FALSE) {
26906  return MA_DOES_NOT_EXIST;
26907  }
26908  }
26909  }
26910 #endif
26911 
26912  /*
26913  Format. This is the hardest part of initialization because there's a few variables to take into account.
26914  1) The format must be supported by the device.
26915  2) The format must be supported miniaudio.
26916  3) There's a priority that miniaudio prefers.
26917 
26918  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
26919  most important property is the sample rate. miniaudio can do format conversion for any sample rate and channel count, but cannot do the same
26920  for the sample data format. If the sample data format is not supported by miniaudio it must be ignored completely.
26921 
26922  On mobile platforms this is a bit different. We just force the use of whatever the audio unit's current format is set to.
26923  */
26924  {
26925  AudioStreamBasicDescription origFormat;
26926  UInt32 origFormatSize = sizeof(origFormat);
26927  AudioUnitScope formatScope = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
26928  AudioUnitElement formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
26929 
26930  if (deviceType == ma_device_type_playback) {
26931  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &origFormat, &origFormatSize);
26932  } else {
26933  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &origFormat, &origFormatSize);
26934  }
26935  if (status != noErr) {
26936  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
26937  return ma_result_from_OSStatus(status);
26938  }
26939 
26940  #if defined(MA_APPLE_DESKTOP)
26941  result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, &origFormat, &bestFormat);
26942  if (result != MA_SUCCESS) {
26943  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
26944  return result;
26945  }
26946 
26947  /*
26948  Technical Note TN2091: Device input using the HAL Output Audio Unit
26949  https://developer.apple.com/library/archive/technotes/tn2091/_index.html
26950 
26951  This documentation says the following:
26952 
26953  The internal AudioConverter can handle any *simple* conversion. Typically, this means that a client can specify ANY
26954  variant of the PCM formats. Consequently, the device's sample rate should match the desired sample rate. If sample rate
26955  conversion is needed, it can be accomplished by buffering the input and converting the data on a separate thread with
26956  another AudioConverter.
26957 
26958  The important part here is the mention that it can handle *simple* conversions, which does *not* include sample rate. We
26959  therefore want to ensure the sample rate stays consistent. This document is specifically for input, but I'm going to play it
26960  safe and apply the same rule to output as well.
26961 
26962  I have tried going against the documentation by setting the sample rate anyway, but this just results in AudioUnitRender()
26963  returning a result code of -10863. I have also tried changing the format directly on the input scope on the input bus, but
26964  this just results in `ca_require: IsStreamFormatWritable(inScope, inElement) NotWritable` when trying to set the format.
26965 
26966  Something that does seem to work, however, has been setting the nominal sample rate on the deivce object. The problem with
26967  this, however, is that it actually changes the sample rate at the operating system level and not just the application. This
26968  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
26969  configuration option. When the `coreaudio.allowNominalSampleRateChange` config option is set to true, changing the sample
26970  rate will be allowed. Otherwise it'll be fixed to the current sample rate. To check the system-defined sample rate, run
26971  the Audio MIDI Setup program that comes installed on macOS and observe how the sample rate changes as the sample rate is
26972  changed by miniaudio.
26973  */
26974  if (pData->allowNominalSampleRateChange) {
26975  AudioValueRange sampleRateRange;
26976  AudioObjectPropertyAddress propAddress;
26977 
26978  sampleRateRange.mMinimum = bestFormat.mSampleRate;
26979  sampleRateRange.mMaximum = bestFormat.mSampleRate;
26980 
26981  propAddress.mSelector = kAudioDevicePropertyNominalSampleRate;
26982  propAddress.mScope = (deviceType == ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
26983  propAddress.mElement = kAudioObjectPropertyElementMaster;
26984 
26985  status = ((ma_AudioObjectSetPropertyData_proc)pContext->coreaudio.AudioObjectSetPropertyData)(deviceObjectID, &propAddress, 0, NULL, sizeof(sampleRateRange), &sampleRateRange);
26986  if (status != noErr) {
26987  bestFormat.mSampleRate = origFormat.mSampleRate;
26988  }
26989  } else {
26990  bestFormat.mSampleRate = origFormat.mSampleRate;
26991  }
26992 
26993  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
26994  if (status != noErr) {
26995  /* We failed to set the format, so fall back to the current format of the audio unit. */
26996  bestFormat = origFormat;
26997  }
26998  #else
26999  bestFormat = origFormat;
27000 
27001  /*
27002  Sample rate is a little different here because for some reason kAudioUnitProperty_StreamFormat returns 0... Oh well. We need to instead try
27003  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
27004  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
27005  can tell, it looks like the sample rate is shared between playback and capture for everything.
27006  */
27007  @autoreleasepool {
27008  AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
27009  MA_ASSERT(pAudioSession != NULL);
27010 
27011  [pAudioSession setPreferredSampleRate:(double)pData->sampleRateIn error:nil];
27012  bestFormat.mSampleRate = pAudioSession.sampleRate;
27013 
27014  /*
27015  I've had a report that the channel count returned by AudioUnitGetProperty above is inconsistent with
27016  AVAudioSession outputNumberOfChannels. I'm going to try using the AVAudioSession values instead.
27017  */
27018  if (deviceType == ma_device_type_playback) {
27019  bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.outputNumberOfChannels;
27020  }
27021  if (deviceType == ma_device_type_capture) {
27022  bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.inputNumberOfChannels;
27023  }
27024  }
27025 
27026  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat));
27027  if (status != noErr) {
27028  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27029  return ma_result_from_OSStatus(status);
27030  }
27031  #endif
27032 
27033  result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pData->formatOut);
27034  if (result != MA_SUCCESS) {
27035  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27036  return result;
27037  }
27038 
27039  if (pData->formatOut == ma_format_unknown) {
27040  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27041  return MA_FORMAT_NOT_SUPPORTED;
27042  }
27043 
27044  pData->channelsOut = bestFormat.mChannelsPerFrame;
27045  pData->sampleRateOut = bestFormat.mSampleRate;
27046  }
27047 
27048  /* Clamp the channel count for safety. */
27049  if (pData->channelsOut > MA_MAX_CHANNELS) {
27050  pData->channelsOut = MA_MAX_CHANNELS;
27051  }
27052 
27053  /*
27054  Internal channel map. This is weird in my testing. If I use the AudioObject to get the
27055  channel map, the channel descriptions are set to "Unknown" for some reason. To work around
27056  this it looks like retrieving it from the AudioUnit will work. However, and this is where
27057  it gets weird, it doesn't seem to work with capture devices, nor at all on iOS... Therefore
27058  I'm going to fall back to a default assumption in these cases.
27059  */
27060 #if defined(MA_APPLE_DESKTOP)
27061  result = ma_get_AudioUnit_channel_map(pContext, pData->audioUnit, deviceType, pData->channelMapOut, pData->channelsOut);
27062  if (result != MA_SUCCESS) {
27063  #if 0
27064  /* Try falling back to the channel map from the AudioObject. */
27065  result = ma_get_AudioObject_channel_map(pContext, deviceObjectID, deviceType, pData->channelMapOut, pData->channelsOut);
27066  if (result != MA_SUCCESS) {
27067  return result;
27068  }
27069  #else
27070  /* Fall back to default assumptions. */
27071  ma_get_standard_channel_map(ma_standard_channel_map_default, pData->channelsOut, pData->channelMapOut);
27072  #endif
27073  }
27074 #else
27075  /* TODO: Figure out how to get the channel map using AVAudioSession. */
27076  ma_get_standard_channel_map(ma_standard_channel_map_default, pData->channelsOut, pData->channelMapOut);
27077 #endif
27078 
27079 
27080  /* Buffer size. Not allowing this to be configurable on iOS. */
27081  if (pData->periodSizeInFramesIn == 0) {
27082  if (pData->periodSizeInMillisecondsIn == 0) {
27083  if (pData->performanceProfile == ma_performance_profile_low_latency) {
27085  } else {
27087  }
27088  } else {
27089  actualPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pData->periodSizeInMillisecondsIn, pData->sampleRateOut);
27090  }
27091  } else {
27092  actualPeriodSizeInFrames = pData->periodSizeInFramesIn;
27093  }
27094 
27095 #if defined(MA_APPLE_DESKTOP)
27096  result = ma_set_AudioObject_buffer_size_in_frames(pContext, deviceObjectID, deviceType, &actualPeriodSizeInFrames);
27097  if (result != MA_SUCCESS) {
27098  return result;
27099  }
27100 #else
27101  /*
27102  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
27103  just going to set it to the value of kAudioUnitProperty_MaximumFramesPerSlice.
27104  */
27105  status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualPeriodSizeInFrames, &actualPeriodSizeInFramesSize);
27106  if (status != noErr) {
27107  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27108  return ma_result_from_OSStatus(status);
27109  }
27110 #endif
27111 
27112 
27113  /*
27114  During testing I discovered that the buffer size can be too big. You'll get an error like this:
27115 
27116  kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=4096, mMaxFramesPerSlice=512
27117 
27118  Note how inFramesToProcess is smaller than mMaxFramesPerSlice. To fix, we need to set kAudioUnitProperty_MaximumFramesPerSlice to that
27119  of the size of our buffer, or do it the other way around and set our buffer size to the kAudioUnitProperty_MaximumFramesPerSlice.
27120  */
27121  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualPeriodSizeInFrames, sizeof(actualPeriodSizeInFrames));
27122  if (status != noErr) {
27123  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27124  return ma_result_from_OSStatus(status);
27125  }
27126 
27127  pData->periodSizeInFramesOut = (ma_uint32)actualPeriodSizeInFrames;
27128 
27129  /* We need a buffer list if this is an input device. We render into this in the input callback. */
27130  if (deviceType == ma_device_type_capture) {
27131  ma_bool32 isInterleaved = (bestFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
27132  AudioBufferList* pBufferList;
27133 
27134  pBufferList = ma_allocate_AudioBufferList__coreaudio(pData->periodSizeInFramesOut, pData->formatOut, pData->channelsOut, (isInterleaved) ? ma_stream_layout_interleaved : ma_stream_layout_deinterleaved, &pContext->allocationCallbacks);
27135  if (pBufferList == NULL) {
27136  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27137  return MA_OUT_OF_MEMORY;
27138  }
27139 
27140  pData->pAudioBufferList = pBufferList;
27141  }
27142 
27143  /* Callbacks. */
27144  callbackInfo.inputProcRefCon = pDevice_DoNotReference;
27145  if (deviceType == ma_device_type_playback) {
27146  callbackInfo.inputProc = ma_on_output__coreaudio;
27147  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &callbackInfo, sizeof(callbackInfo));
27148  if (status != noErr) {
27149  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27150  return ma_result_from_OSStatus(status);
27151  }
27152  } else {
27153  callbackInfo.inputProc = ma_on_input__coreaudio;
27154  status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callbackInfo, sizeof(callbackInfo));
27155  if (status != noErr) {
27156  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27157  return ma_result_from_OSStatus(status);
27158  }
27159  }
27160 
27161  /* We need to listen for stop events. */
27162  if (pData->registerStopEvent) {
27163  status = ((ma_AudioUnitAddPropertyListener_proc)pContext->coreaudio.AudioUnitAddPropertyListener)(pData->audioUnit, kAudioOutputUnitProperty_IsRunning, on_start_stop__coreaudio, pDevice_DoNotReference);
27164  if (status != noErr) {
27165  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27166  return ma_result_from_OSStatus(status);
27167  }
27168  }
27169 
27170  /* Initialize the audio unit. */
27171  status = ((ma_AudioUnitInitialize_proc)pContext->coreaudio.AudioUnitInitialize)(pData->audioUnit);
27172  if (status != noErr) {
27173  ma__free_from_callbacks(pData->pAudioBufferList, &pContext->allocationCallbacks);
27174  pData->pAudioBufferList = NULL;
27175  ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
27176  return ma_result_from_OSStatus(status);
27177  }
27178 
27179  /* Grab the name. */
27180 #if defined(MA_APPLE_DESKTOP)
27181  ma_get_AudioObject_name(pContext, deviceObjectID, sizeof(pData->deviceName), pData->deviceName);
27182 #else
27183  if (deviceType == ma_device_type_playback) {
27184  ma_strcpy_s(pData->deviceName, sizeof(pData->deviceName), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
27185  } else {
27186  ma_strcpy_s(pData->deviceName, sizeof(pData->deviceName), MA_DEFAULT_CAPTURE_DEVICE_NAME);
27187  }
27188 #endif
27189 
27190  return result;
27191 }
27192 
27193 #if defined(MA_APPLE_DESKTOP)
27194 static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_device_type deviceType, ma_bool32 disposePreviousAudioUnit)
27195 {
27196  ma_device_init_internal_data__coreaudio data;
27197  ma_result result;
27198 
27199  /* This should only be called for playback or capture, not duplex. */
27200  if (deviceType == ma_device_type_duplex) {
27201  return MA_INVALID_ARGS;
27202  }
27203 
27204  data.allowNominalSampleRateChange = MA_FALSE; /* Don't change the nominal sample rate when switching devices. */
27205 
27206  if (deviceType == ma_device_type_capture) {
27207  data.formatIn = pDevice->capture.format;
27208  data.channelsIn = pDevice->capture.channels;
27209  data.sampleRateIn = pDevice->sampleRate;
27210  MA_COPY_MEMORY(data.channelMapIn, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
27211  data.shareMode = pDevice->capture.shareMode;
27212  data.performanceProfile = pDevice->coreaudio.originalPerformanceProfile;
27213  data.registerStopEvent = MA_TRUE;
27214 
27215  if (disposePreviousAudioUnit) {
27216  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
27217  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
27218  }
27219  if (pDevice->coreaudio.pAudioBufferList) {
27220  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
27221  }
27222  } else if (deviceType == ma_device_type_playback) {
27223  data.formatIn = pDevice->playback.format;
27224  data.channelsIn = pDevice->playback.channels;
27225  data.sampleRateIn = pDevice->sampleRate;
27226  MA_COPY_MEMORY(data.channelMapIn, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
27227  data.shareMode = pDevice->playback.shareMode;
27228  data.performanceProfile = pDevice->coreaudio.originalPerformanceProfile;
27229  data.registerStopEvent = (pDevice->type != ma_device_type_duplex);
27230 
27231  if (disposePreviousAudioUnit) {
27232  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
27233  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
27234  }
27235  }
27236  data.periodSizeInFramesIn = pDevice->coreaudio.originalPeriodSizeInFrames;
27237  data.periodSizeInMillisecondsIn = pDevice->coreaudio.originalPeriodSizeInMilliseconds;
27238  data.periodsIn = pDevice->coreaudio.originalPeriods;
27239 
27240  /* Need at least 3 periods for duplex. */
27241  if (data.periodsIn < 3 && pDevice->type == ma_device_type_duplex) {
27242  data.periodsIn = 3;
27243  }
27244 
27245  result = ma_device_init_internal__coreaudio(pDevice->pContext, deviceType, NULL, &data, (void*)pDevice);
27246  if (result != MA_SUCCESS) {
27247  return result;
27248  }
27249 
27250  if (deviceType == ma_device_type_capture) {
27251  #if defined(MA_APPLE_DESKTOP)
27252  pDevice->coreaudio.deviceObjectIDCapture = (ma_uint32)data.deviceObjectID;
27253  #endif
27254  pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
27255  pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
27256  pDevice->coreaudio.audioBufferCapInFrames = data.periodSizeInFramesOut;
27257 
27258  pDevice->capture.internalFormat = data.formatOut;
27259  pDevice->capture.internalChannels = data.channelsOut;
27260  pDevice->capture.internalSampleRate = data.sampleRateOut;
27261  MA_COPY_MEMORY(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
27262  pDevice->capture.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
27263  pDevice->capture.internalPeriods = data.periodsOut;
27264  } else if (deviceType == ma_device_type_playback) {
27265  #if defined(MA_APPLE_DESKTOP)
27266  pDevice->coreaudio.deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
27267  #endif
27268  pDevice->coreaudio.audioUnitPlayback = (ma_ptr)data.audioUnit;
27269 
27270  pDevice->playback.internalFormat = data.formatOut;
27271  pDevice->playback.internalChannels = data.channelsOut;
27272  pDevice->playback.internalSampleRate = data.sampleRateOut;
27273  MA_COPY_MEMORY(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
27274  pDevice->playback.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
27275  pDevice->playback.internalPeriods = data.periodsOut;
27276  }
27277 
27278  return MA_SUCCESS;
27279 }
27280 #endif /* MA_APPLE_DESKTOP */
27281 
27282 static ma_result ma_device_init__coreaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
27283 {
27284  ma_result result;
27285 
27286  MA_ASSERT(pDevice != NULL);
27287  MA_ASSERT(pConfig != NULL);
27288 
27289  if (pConfig->deviceType == ma_device_type_loopback) {
27291  }
27292 
27293  /* No exclusive mode with the Core Audio backend for now. */
27294  if (((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive) ||
27295  ((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive)) {
27297  }
27298 
27299  /* Capture needs to be initialized first. */
27300  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
27301  ma_device_init_internal_data__coreaudio data;
27302  data.allowNominalSampleRateChange = pConfig->coreaudio.allowNominalSampleRateChange;
27303  data.formatIn = pDescriptorCapture->format;
27304  data.channelsIn = pDescriptorCapture->channels;
27305  data.sampleRateIn = pDescriptorCapture->sampleRate;
27306  MA_COPY_MEMORY(data.channelMapIn, pDescriptorCapture->channelMap, sizeof(pDescriptorCapture->channelMap));
27307  data.periodSizeInFramesIn = pDescriptorCapture->periodSizeInFrames;
27308  data.periodSizeInMillisecondsIn = pDescriptorCapture->periodSizeInMilliseconds;
27309  data.periodsIn = pDescriptorCapture->periodCount;
27310  data.shareMode = pDescriptorCapture->shareMode;
27311  data.performanceProfile = pConfig->performanceProfile;
27312  data.registerStopEvent = MA_TRUE;
27313 
27314  /* Need at least 3 periods for duplex. */
27315  if (data.periodsIn < 3 && pConfig->deviceType == ma_device_type_duplex) {
27316  data.periodsIn = 3;
27317  }
27318 
27319  result = ma_device_init_internal__coreaudio(pDevice->pContext, ma_device_type_capture, pDescriptorCapture->pDeviceID, &data, (void*)pDevice);
27320  if (result != MA_SUCCESS) {
27321  return result;
27322  }
27323 
27324  pDevice->coreaudio.isDefaultCaptureDevice = (pConfig->capture.pDeviceID == NULL);
27325  #if defined(MA_APPLE_DESKTOP)
27326  pDevice->coreaudio.deviceObjectIDCapture = (ma_uint32)data.deviceObjectID;
27327  #endif
27328  pDevice->coreaudio.audioUnitCapture = (ma_ptr)data.audioUnit;
27329  pDevice->coreaudio.pAudioBufferList = (ma_ptr)data.pAudioBufferList;
27330  pDevice->coreaudio.audioBufferCapInFrames = data.periodSizeInFramesOut;
27331  pDevice->coreaudio.originalPeriodSizeInFrames = pDescriptorCapture->periodSizeInFrames;
27332  pDevice->coreaudio.originalPeriodSizeInMilliseconds = pDescriptorCapture->periodSizeInMilliseconds;
27333  pDevice->coreaudio.originalPeriods = pDescriptorCapture->periodCount;
27334  pDevice->coreaudio.originalPerformanceProfile = pConfig->performanceProfile;
27335 
27336  pDescriptorCapture->format = data.formatOut;
27337  pDescriptorCapture->channels = data.channelsOut;
27338  pDescriptorCapture->sampleRate = data.sampleRateOut;
27339  MA_COPY_MEMORY(pDescriptorCapture->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
27340  pDescriptorCapture->periodSizeInFrames = data.periodSizeInFramesOut;
27341  pDescriptorCapture->periodCount = data.periodsOut;
27342 
27343  #if defined(MA_APPLE_DESKTOP)
27344  /*
27345  If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly
27346  switch the device in the background.
27347  */
27348  if (pConfig->capture.pDeviceID == NULL) {
27349  ma_device__track__coreaudio(pDevice);
27350  }
27351  #endif
27352  }
27353 
27354  /* Playback. */
27355  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
27356  ma_device_init_internal_data__coreaudio data;
27357  data.allowNominalSampleRateChange = pConfig->coreaudio.allowNominalSampleRateChange;
27358  data.formatIn = pDescriptorPlayback->format;
27359  data.channelsIn = pDescriptorPlayback->channels;
27360  data.sampleRateIn = pDescriptorPlayback->sampleRate;
27361  MA_COPY_MEMORY(data.channelMapIn, pDescriptorPlayback->channelMap, sizeof(pDescriptorPlayback->channelMap));
27362  data.shareMode = pDescriptorPlayback->shareMode;
27363  data.performanceProfile = pConfig->performanceProfile;
27364 
27365  /* In full-duplex mode we want the playback buffer to be the same size as the capture buffer. */
27366  if (pConfig->deviceType == ma_device_type_duplex) {
27367  data.periodSizeInFramesIn = pDescriptorCapture->periodSizeInFrames;
27368  data.periodsIn = pDescriptorCapture->periodCount;
27369  data.registerStopEvent = MA_FALSE;
27370  } else {
27371  data.periodSizeInFramesIn = pDescriptorPlayback->periodSizeInFrames;
27372  data.periodSizeInMillisecondsIn = pDescriptorPlayback->periodSizeInMilliseconds;
27373  data.periodsIn = pDescriptorPlayback->periodCount;
27374  data.registerStopEvent = MA_TRUE;
27375  }
27376 
27377  result = ma_device_init_internal__coreaudio(pDevice->pContext, ma_device_type_playback, pDescriptorPlayback->pDeviceID, &data, (void*)pDevice);
27378  if (result != MA_SUCCESS) {
27379  if (pConfig->deviceType == ma_device_type_duplex) {
27380  ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
27381  if (pDevice->coreaudio.pAudioBufferList) {
27382  ma__free_from_callbacks(pDevice->coreaudio.pAudioBufferList, &pDevice->pContext->allocationCallbacks);
27383  }
27384  }
27385  return result;
27386  }
27387 
27388  pDevice->coreaudio.isDefaultPlaybackDevice = (pConfig->playback.pDeviceID == NULL);
27389  #if defined(MA_APPLE_DESKTOP)
27390  pDevice->coreaudio.deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
27391  #endif
27392  pDevice->coreaudio.audioUnitPlayback = (ma_ptr)data.audioUnit;
27393  pDevice->coreaudio.originalPeriodSizeInFrames = pDescriptorPlayback->periodSizeInFrames;
27394  pDevice->coreaudio.originalPeriodSizeInMilliseconds = pDescriptorPlayback->periodSizeInMilliseconds;
27395  pDevice->coreaudio.originalPeriods = pDescriptorPlayback->periodCount;
27396  pDevice->coreaudio.originalPerformanceProfile = pConfig->performanceProfile;
27397 
27398  pDescriptorPlayback->format = data.formatOut;
27399  pDescriptorPlayback->channels = data.channelsOut;
27400  pDescriptorPlayback->sampleRate = data.sampleRateOut;
27401  MA_COPY_MEMORY(pDescriptorPlayback->channelMap, data.channelMapOut, sizeof(data.channelMapOut));
27402  pDescriptorPlayback->periodSizeInFrames = data.periodSizeInFramesOut;
27403  pDescriptorPlayback->periodCount = data.periodsOut;
27404 
27405  #if defined(MA_APPLE_DESKTOP)
27406  /*
27407  If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly
27408  switch the device in the background.
27409  */
27410  if (pDescriptorPlayback->pDeviceID == NULL && (pConfig->deviceType != ma_device_type_duplex || pDescriptorCapture->pDeviceID != NULL)) {
27411  ma_device__track__coreaudio(pDevice);
27412  }
27413  #endif
27414  }
27415 
27416 
27417 
27418  /*
27419  When stopping the device, a callback is called on another thread. We need to wait for this callback
27420  before returning from ma_device_stop(). This event is used for this.
27421  */
27422  ma_event_init(&pDevice->coreaudio.stopEvent);
27423 
27424  /*
27425  We need to detect when a route has changed so we can update the data conversion pipeline accordingly. This is done
27426  differently on non-Desktop Apple platforms.
27427  */
27428 #if defined(MA_APPLE_MOBILE)
27429  pDevice->coreaudio.pRouteChangeHandler = (__bridge_retained void*)[[ma_router_change_handler alloc] init:pDevice];
27430 #endif
27431 
27432  return MA_SUCCESS;
27433 }
27434 
27435 
27436 static ma_result ma_device_start__coreaudio(ma_device* pDevice)
27437 {
27438  MA_ASSERT(pDevice != NULL);
27439 
27440  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
27441  OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
27442  if (status != noErr) {
27443  return ma_result_from_OSStatus(status);
27444  }
27445  }
27446 
27447  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
27448  OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
27449  if (status != noErr) {
27450  if (pDevice->type == ma_device_type_duplex) {
27451  ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
27452  }
27453  return ma_result_from_OSStatus(status);
27454  }
27455  }
27456 
27457  return MA_SUCCESS;
27458 }
27459 
27460 static ma_result ma_device_stop__coreaudio(ma_device* pDevice)
27461 {
27462  MA_ASSERT(pDevice != NULL);
27463 
27464  /* It's not clear from the documentation whether or not AudioOutputUnitStop() actually drains the device or not. */
27465 
27466  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
27467  OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
27468  if (status != noErr) {
27469  return ma_result_from_OSStatus(status);
27470  }
27471  }
27472 
27473  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
27474  OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
27475  if (status != noErr) {
27476  return ma_result_from_OSStatus(status);
27477  }
27478  }
27479 
27480  /* We need to wait for the callback to finish before returning. */
27481  ma_event_wait(&pDevice->coreaudio.stopEvent);
27482  return MA_SUCCESS;
27483 }
27484 
27485 
27486 static ma_result ma_context_uninit__coreaudio(ma_context* pContext)
27487 {
27488  MA_ASSERT(pContext != NULL);
27489  MA_ASSERT(pContext->backend == ma_backend_coreaudio);
27490 
27491 #if defined(MA_APPLE_MOBILE)
27492  if (!pContext->coreaudio.noAudioSessionDeactivate) {
27493  if (![[AVAudioSession sharedInstance] setActive:false error:nil]) {
27494  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to deactivate audio session.", MA_FAILED_TO_INIT_BACKEND);
27495  }
27496  }
27497 #endif
27498 
27499 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
27500  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
27501  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
27502  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
27503 #endif
27504 
27505 #if !defined(MA_APPLE_MOBILE)
27506  ma_context__uninit_device_tracking__coreaudio(pContext);
27507 #endif
27508 
27509  (void)pContext;
27510  return MA_SUCCESS;
27511 }
27512 
27513 #if defined(MA_APPLE_MOBILE)
27514 static AVAudioSessionCategory ma_to_AVAudioSessionCategory(ma_ios_session_category category)
27515 {
27516  /* The "default" and "none" categories are treated different and should not be used as an input into this function. */
27519 
27520  switch (category) {
27521  case ma_ios_session_category_ambient: return AVAudioSessionCategoryAmbient;
27522  case ma_ios_session_category_solo_ambient: return AVAudioSessionCategorySoloAmbient;
27523  case ma_ios_session_category_playback: return AVAudioSessionCategoryPlayback;
27524  case ma_ios_session_category_record: return AVAudioSessionCategoryRecord;
27525  case ma_ios_session_category_play_and_record: return AVAudioSessionCategoryPlayAndRecord;
27526  case ma_ios_session_category_multi_route: return AVAudioSessionCategoryMultiRoute;
27527  case ma_ios_session_category_none: return AVAudioSessionCategoryAmbient;
27528  case ma_ios_session_category_default: return AVAudioSessionCategoryAmbient;
27529  default: return AVAudioSessionCategoryAmbient;
27530  }
27531 }
27532 #endif
27533 
27534 static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
27535 {
27536 #if !defined(MA_APPLE_MOBILE)
27537  ma_result result;
27538 #endif
27539 
27540  MA_ASSERT(pConfig != NULL);
27541  MA_ASSERT(pContext != NULL);
27542 
27543 #if defined(MA_APPLE_MOBILE)
27544  @autoreleasepool {
27545  AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
27546  AVAudioSessionCategoryOptions options = pConfig->coreaudio.sessionCategoryOptions;
27547 
27548  MA_ASSERT(pAudioSession != NULL);
27549 
27551  /*
27552  I'm going to use trial and error to determine our default session category. First we'll try PlayAndRecord. If that fails
27553  we'll try Playback and if that fails we'll try record. If all of these fail we'll just not set the category.
27554  */
27555  #if !defined(MA_APPLE_TV) && !defined(MA_APPLE_WATCH)
27556  options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
27557  #endif
27558 
27559  if ([pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord withOptions:options error:nil]) {
27560  /* Using PlayAndRecord */
27561  } else if ([pAudioSession setCategory: AVAudioSessionCategoryPlayback withOptions:options error:nil]) {
27562  /* Using Playback */
27563  } else if ([pAudioSession setCategory: AVAudioSessionCategoryRecord withOptions:options error:nil]) {
27564  /* Using Record */
27565  } else {
27566  /* Leave as default? */
27567  }
27568  } else {
27570  if (![pAudioSession setCategory: ma_to_AVAudioSessionCategory(pConfig->coreaudio.sessionCategory) withOptions:options error:nil]) {
27571  return MA_INVALID_OPERATION; /* Failed to set session category. */
27572  }
27573  }
27574  }
27575 
27576  if (!pConfig->coreaudio.noAudioSessionActivate) {
27577  if (![pAudioSession setActive:true error:nil]) {
27578  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to activate audio session.", MA_FAILED_TO_INIT_BACKEND);
27579  }
27580  }
27581  }
27582 #endif
27583 
27584 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
27585  pContext->coreaudio.hCoreFoundation = ma_dlopen(pContext, "CoreFoundation.framework/CoreFoundation");
27586  if (pContext->coreaudio.hCoreFoundation == NULL) {
27587  return MA_API_NOT_FOUND;
27588  }
27589 
27590  pContext->coreaudio.CFStringGetCString = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFStringGetCString");
27591  pContext->coreaudio.CFRelease = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation, "CFRelease");
27592 
27593 
27594  pContext->coreaudio.hCoreAudio = ma_dlopen(pContext, "CoreAudio.framework/CoreAudio");
27595  if (pContext->coreaudio.hCoreAudio == NULL) {
27596  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
27597  return MA_API_NOT_FOUND;
27598  }
27599 
27600  pContext->coreaudio.AudioObjectGetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyData");
27601  pContext->coreaudio.AudioObjectGetPropertyDataSize = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectGetPropertyDataSize");
27602  pContext->coreaudio.AudioObjectSetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectSetPropertyData");
27603  pContext->coreaudio.AudioObjectAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectAddPropertyListener");
27604  pContext->coreaudio.AudioObjectRemovePropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio, "AudioObjectRemovePropertyListener");
27605 
27606  /*
27607  It looks like Apple has moved some APIs from AudioUnit into AudioToolbox on more recent versions of macOS. They are still
27608  defined in AudioUnit, but just in case they decide to remove them from there entirely I'm going to implement a fallback.
27609  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
27610  AudioToolbox.
27611  */
27612  pContext->coreaudio.hAudioUnit = ma_dlopen(pContext, "AudioUnit.framework/AudioUnit");
27613  if (pContext->coreaudio.hAudioUnit == NULL) {
27614  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
27615  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
27616  return MA_API_NOT_FOUND;
27617  }
27618 
27619  if (ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentFindNext") == NULL) {
27620  /* Couldn't find the required symbols in AudioUnit, so fall back to AudioToolbox. */
27621  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
27622  pContext->coreaudio.hAudioUnit = ma_dlopen(pContext, "AudioToolbox.framework/AudioToolbox");
27623  if (pContext->coreaudio.hAudioUnit == NULL) {
27624  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
27625  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
27626  return MA_API_NOT_FOUND;
27627  }
27628  }
27629 
27630  pContext->coreaudio.AudioComponentFindNext = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentFindNext");
27631  pContext->coreaudio.AudioComponentInstanceDispose = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceDispose");
27632  pContext->coreaudio.AudioComponentInstanceNew = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioComponentInstanceNew");
27633  pContext->coreaudio.AudioOutputUnitStart = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStart");
27634  pContext->coreaudio.AudioOutputUnitStop = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioOutputUnitStop");
27635  pContext->coreaudio.AudioUnitAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitAddPropertyListener");
27636  pContext->coreaudio.AudioUnitGetPropertyInfo = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetPropertyInfo");
27637  pContext->coreaudio.AudioUnitGetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitGetProperty");
27638  pContext->coreaudio.AudioUnitSetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitSetProperty");
27639  pContext->coreaudio.AudioUnitInitialize = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitInitialize");
27640  pContext->coreaudio.AudioUnitRender = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit, "AudioUnitRender");
27641 #else
27642  pContext->coreaudio.CFStringGetCString = (ma_proc)CFStringGetCString;
27643  pContext->coreaudio.CFRelease = (ma_proc)CFRelease;
27644 
27645  #if defined(MA_APPLE_DESKTOP)
27646  pContext->coreaudio.AudioObjectGetPropertyData = (ma_proc)AudioObjectGetPropertyData;
27647  pContext->coreaudio.AudioObjectGetPropertyDataSize = (ma_proc)AudioObjectGetPropertyDataSize;
27648  pContext->coreaudio.AudioObjectSetPropertyData = (ma_proc)AudioObjectSetPropertyData;
27649  pContext->coreaudio.AudioObjectAddPropertyListener = (ma_proc)AudioObjectAddPropertyListener;
27650  pContext->coreaudio.AudioObjectRemovePropertyListener = (ma_proc)AudioObjectRemovePropertyListener;
27651  #endif
27652 
27653  pContext->coreaudio.AudioComponentFindNext = (ma_proc)AudioComponentFindNext;
27654  pContext->coreaudio.AudioComponentInstanceDispose = (ma_proc)AudioComponentInstanceDispose;
27655  pContext->coreaudio.AudioComponentInstanceNew = (ma_proc)AudioComponentInstanceNew;
27656  pContext->coreaudio.AudioOutputUnitStart = (ma_proc)AudioOutputUnitStart;
27657  pContext->coreaudio.AudioOutputUnitStop = (ma_proc)AudioOutputUnitStop;
27658  pContext->coreaudio.AudioUnitAddPropertyListener = (ma_proc)AudioUnitAddPropertyListener;
27659  pContext->coreaudio.AudioUnitGetPropertyInfo = (ma_proc)AudioUnitGetPropertyInfo;
27660  pContext->coreaudio.AudioUnitGetProperty = (ma_proc)AudioUnitGetProperty;
27661  pContext->coreaudio.AudioUnitSetProperty = (ma_proc)AudioUnitSetProperty;
27662  pContext->coreaudio.AudioUnitInitialize = (ma_proc)AudioUnitInitialize;
27663  pContext->coreaudio.AudioUnitRender = (ma_proc)AudioUnitRender;
27664 #endif
27665 
27666  /* Audio component. */
27667  {
27668  AudioComponentDescription desc;
27669  desc.componentType = kAudioUnitType_Output;
27670  #if defined(MA_APPLE_DESKTOP)
27671  desc.componentSubType = kAudioUnitSubType_HALOutput;
27672  #else
27673  desc.componentSubType = kAudioUnitSubType_RemoteIO;
27674  #endif
27675  desc.componentManufacturer = kAudioUnitManufacturer_Apple;
27676  desc.componentFlags = 0;
27677  desc.componentFlagsMask = 0;
27678 
27679  pContext->coreaudio.component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc);
27680  if (pContext->coreaudio.component == NULL) {
27681  #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
27682  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
27683  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
27684  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
27685  #endif
27687  }
27688  }
27689 
27690 #if !defined(MA_APPLE_MOBILE)
27691  result = ma_context__init_device_tracking__coreaudio(pContext);
27692  if (result != MA_SUCCESS) {
27693  #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
27694  ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
27695  ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
27696  ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
27697  #endif
27698  return result;
27699  }
27700 #endif
27701 
27702  pContext->coreaudio.noAudioSessionDeactivate = pConfig->coreaudio.noAudioSessionDeactivate;
27703 
27704  pCallbacks->onContextInit = ma_context_init__coreaudio;
27705  pCallbacks->onContextUninit = ma_context_uninit__coreaudio;
27706  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__coreaudio;
27707  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__coreaudio;
27708  pCallbacks->onDeviceInit = ma_device_init__coreaudio;
27709  pCallbacks->onDeviceUninit = ma_device_uninit__coreaudio;
27710  pCallbacks->onDeviceStart = ma_device_start__coreaudio;
27711  pCallbacks->onDeviceStop = ma_device_stop__coreaudio;
27712  pCallbacks->onDeviceRead = NULL;
27713  pCallbacks->onDeviceWrite = NULL;
27714  pCallbacks->onDeviceDataLoop = NULL;
27715 
27716  return MA_SUCCESS;
27717 }
27718 #endif /* Core Audio */
27719 
27720 
27721 
27722 /******************************************************************************
27723 
27724 sndio Backend
27725 
27726 ******************************************************************************/
27727 #ifdef MA_HAS_SNDIO
27728 #include <fcntl.h>
27729 
27730 /*
27731 Only supporting OpenBSD. This did not work very well at all on FreeBSD when I tried it. Not sure if this is due
27732 to miniaudio's implementation or if it's some kind of system configuration issue, but basically the default device
27733 just doesn't emit any sound, or at times you'll hear tiny pieces. I will consider enabling this when there's
27734 demand for it or if I can get it tested and debugged more thoroughly.
27735 */
27736 #if 0
27737 #if defined(__NetBSD__) || defined(__OpenBSD__)
27738 #include <sys/audioio.h>
27739 #endif
27740 #if defined(__FreeBSD__) || defined(__DragonFly__)
27741 #include <sys/soundcard.h>
27742 #endif
27743 #endif
27744 
27745 #define MA_SIO_DEVANY "default"
27746 #define MA_SIO_PLAY 1
27747 #define MA_SIO_REC 2
27748 #define MA_SIO_NENC 8
27749 #define MA_SIO_NCHAN 8
27750 #define MA_SIO_NRATE 16
27751 #define MA_SIO_NCONF 4
27752 
27753 struct ma_sio_hdl; /* <-- Opaque */
27754 
27755 struct ma_sio_par
27756 {
27757  unsigned int bits;
27758  unsigned int bps;
27759  unsigned int sig;
27760  unsigned int le;
27761  unsigned int msb;
27762  unsigned int rchan;
27763  unsigned int pchan;
27764  unsigned int rate;
27765  unsigned int bufsz;
27766  unsigned int xrun;
27767  unsigned int round;
27768  unsigned int appbufsz;
27769  int __pad[3];
27770  unsigned int __magic;
27771 };
27772 
27773 struct ma_sio_enc
27774 {
27775  unsigned int bits;
27776  unsigned int bps;
27777  unsigned int sig;
27778  unsigned int le;
27779  unsigned int msb;
27780 };
27781 
27782 struct ma_sio_conf
27783 {
27784  unsigned int enc;
27785  unsigned int rchan;
27786  unsigned int pchan;
27787  unsigned int rate;
27788 };
27789 
27790 struct ma_sio_cap
27791 {
27792  struct ma_sio_enc enc[MA_SIO_NENC];
27793  unsigned int rchan[MA_SIO_NCHAN];
27794  unsigned int pchan[MA_SIO_NCHAN];
27795  unsigned int rate[MA_SIO_NRATE];
27796  int __pad[7];
27797  unsigned int nconf;
27798  struct ma_sio_conf confs[MA_SIO_NCONF];
27799 };
27800 
27801 typedef struct ma_sio_hdl* (* ma_sio_open_proc) (const char*, unsigned int, int);
27802 typedef void (* ma_sio_close_proc) (struct ma_sio_hdl*);
27803 typedef int (* ma_sio_setpar_proc) (struct ma_sio_hdl*, struct ma_sio_par*);
27804 typedef int (* ma_sio_getpar_proc) (struct ma_sio_hdl*, struct ma_sio_par*);
27805 typedef int (* ma_sio_getcap_proc) (struct ma_sio_hdl*, struct ma_sio_cap*);
27806 typedef size_t (* ma_sio_write_proc) (struct ma_sio_hdl*, const void*, size_t);
27807 typedef size_t (* ma_sio_read_proc) (struct ma_sio_hdl*, void*, size_t);
27808 typedef int (* ma_sio_start_proc) (struct ma_sio_hdl*);
27809 typedef int (* ma_sio_stop_proc) (struct ma_sio_hdl*);
27810 typedef int (* ma_sio_initpar_proc)(struct ma_sio_par*);
27811 
27812 static ma_uint32 ma_get_standard_sample_rate_priority_index__sndio(ma_uint32 sampleRate) /* Lower = higher priority */
27813 {
27814  ma_uint32 i;
27815  for (i = 0; i < ma_countof(g_maStandardSampleRatePriorities); ++i) {
27816  if (g_maStandardSampleRatePriorities[i] == sampleRate) {
27817  return i;
27818  }
27819  }
27820 
27821  return (ma_uint32)-1;
27822 }
27823 
27824 static ma_format ma_format_from_sio_enc__sndio(unsigned int bits, unsigned int bps, unsigned int sig, unsigned int le, unsigned int msb)
27825 {
27826  /* We only support native-endian right now. */
27827  if ((ma_is_little_endian() && le == 0) || (ma_is_big_endian() && le == 1)) {
27828  return ma_format_unknown;
27829  }
27830 
27831  if (bits == 8 && bps == 1 && sig == 0) {
27832  return ma_format_u8;
27833  }
27834  if (bits == 16 && bps == 2 && sig == 1) {
27835  return ma_format_s16;
27836  }
27837  if (bits == 24 && bps == 3 && sig == 1) {
27838  return ma_format_s24;
27839  }
27840  if (bits == 24 && bps == 4 && sig == 1 && msb == 0) {
27841  /*return ma_format_s24_32;*/
27842  }
27843  if (bits == 32 && bps == 4 && sig == 1) {
27844  return ma_format_s32;
27845  }
27846 
27847  return ma_format_unknown;
27848 }
27849 
27850 static ma_format ma_find_best_format_from_sio_cap__sndio(struct ma_sio_cap* caps)
27851 {
27852  ma_format bestFormat;
27853  unsigned int iConfig;
27854 
27855  MA_ASSERT(caps != NULL);
27856 
27857  bestFormat = ma_format_unknown;
27858  for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
27859  unsigned int iEncoding;
27860  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
27861  unsigned int bits;
27862  unsigned int bps;
27863  unsigned int sig;
27864  unsigned int le;
27865  unsigned int msb;
27866  ma_format format;
27867 
27868  if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
27869  continue;
27870  }
27871 
27872  bits = caps->enc[iEncoding].bits;
27873  bps = caps->enc[iEncoding].bps;
27874  sig = caps->enc[iEncoding].sig;
27875  le = caps->enc[iEncoding].le;
27876  msb = caps->enc[iEncoding].msb;
27877  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
27878  if (format == ma_format_unknown) {
27879  continue; /* Format not supported. */
27880  }
27881 
27882  if (bestFormat == ma_format_unknown) {
27883  bestFormat = format;
27884  } else {
27885  if (ma_get_format_priority_index(bestFormat) > ma_get_format_priority_index(format)) { /* <-- Lower = better. */
27886  bestFormat = format;
27887  }
27888  }
27889  }
27890  }
27891 
27892  return bestFormat;
27893 }
27894 
27895 static ma_uint32 ma_find_best_channels_from_sio_cap__sndio(struct ma_sio_cap* caps, ma_device_type deviceType, ma_format requiredFormat)
27896 {
27897  ma_uint32 maxChannels;
27898  unsigned int iConfig;
27899 
27900  MA_ASSERT(caps != NULL);
27901  MA_ASSERT(requiredFormat != ma_format_unknown);
27902 
27903  /* Just pick whatever configuration has the most channels. */
27904  maxChannels = 0;
27905  for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
27906  /* The encoding should be of requiredFormat. */
27907  unsigned int iEncoding;
27908  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
27909  unsigned int iChannel;
27910  unsigned int bits;
27911  unsigned int bps;
27912  unsigned int sig;
27913  unsigned int le;
27914  unsigned int msb;
27915  ma_format format;
27916 
27917  if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
27918  continue;
27919  }
27920 
27921  bits = caps->enc[iEncoding].bits;
27922  bps = caps->enc[iEncoding].bps;
27923  sig = caps->enc[iEncoding].sig;
27924  le = caps->enc[iEncoding].le;
27925  msb = caps->enc[iEncoding].msb;
27926  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
27927  if (format != requiredFormat) {
27928  continue;
27929  }
27930 
27931  /* Getting here means the format is supported. Iterate over each channel count and grab the biggest one. */
27932  for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
27933  unsigned int chan = 0;
27934  unsigned int channels;
27935 
27936  if (deviceType == ma_device_type_playback) {
27937  chan = caps->confs[iConfig].pchan;
27938  } else {
27939  chan = caps->confs[iConfig].rchan;
27940  }
27941 
27942  if ((chan & (1UL << iChannel)) == 0) {
27943  continue;
27944  }
27945 
27946  if (deviceType == ma_device_type_playback) {
27947  channels = caps->pchan[iChannel];
27948  } else {
27949  channels = caps->rchan[iChannel];
27950  }
27951 
27952  if (maxChannels < channels) {
27953  maxChannels = channels;
27954  }
27955  }
27956  }
27957  }
27958 
27959  return maxChannels;
27960 }
27961 
27962 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)
27963 {
27964  ma_uint32 firstSampleRate;
27965  ma_uint32 bestSampleRate;
27966  unsigned int iConfig;
27967 
27968  MA_ASSERT(caps != NULL);
27969  MA_ASSERT(requiredFormat != ma_format_unknown);
27970  MA_ASSERT(requiredChannels > 0);
27971  MA_ASSERT(requiredChannels <= MA_MAX_CHANNELS);
27972 
27973  firstSampleRate = 0; /* <-- If the device does not support a standard rate we'll fall back to the first one that's found. */
27974  bestSampleRate = 0;
27975 
27976  for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
27977  /* The encoding should be of requiredFormat. */
27978  unsigned int iEncoding;
27979  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
27980  unsigned int iChannel;
27981  unsigned int bits;
27982  unsigned int bps;
27983  unsigned int sig;
27984  unsigned int le;
27985  unsigned int msb;
27986  ma_format format;
27987 
27988  if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
27989  continue;
27990  }
27991 
27992  bits = caps->enc[iEncoding].bits;
27993  bps = caps->enc[iEncoding].bps;
27994  sig = caps->enc[iEncoding].sig;
27995  le = caps->enc[iEncoding].le;
27996  msb = caps->enc[iEncoding].msb;
27997  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
27998  if (format != requiredFormat) {
27999  continue;
28000  }
28001 
28002  /* Getting here means the format is supported. Iterate over each channel count and grab the biggest one. */
28003  for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
28004  unsigned int chan = 0;
28005  unsigned int channels;
28006  unsigned int iRate;
28007 
28008  if (deviceType == ma_device_type_playback) {
28009  chan = caps->confs[iConfig].pchan;
28010  } else {
28011  chan = caps->confs[iConfig].rchan;
28012  }
28013 
28014  if ((chan & (1UL << iChannel)) == 0) {
28015  continue;
28016  }
28017 
28018  if (deviceType == ma_device_type_playback) {
28019  channels = caps->pchan[iChannel];
28020  } else {
28021  channels = caps->rchan[iChannel];
28022  }
28023 
28024  if (channels != requiredChannels) {
28025  continue;
28026  }
28027 
28028  /* Getting here means we have found a compatible encoding/channel pair. */
28029  for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
28030  ma_uint32 rate = (ma_uint32)caps->rate[iRate];
28031  ma_uint32 ratePriority;
28032 
28033  if (firstSampleRate == 0) {
28034  firstSampleRate = rate;
28035  }
28036 
28037  /* Disregard this rate if it's not a standard one. */
28038  ratePriority = ma_get_standard_sample_rate_priority_index__sndio(rate);
28039  if (ratePriority == (ma_uint32)-1) {
28040  continue;
28041  }
28042 
28043  if (ma_get_standard_sample_rate_priority_index__sndio(bestSampleRate) > ratePriority) { /* Lower = better. */
28044  bestSampleRate = rate;
28045  }
28046  }
28047  }
28048  }
28049  }
28050 
28051  /* If a standard sample rate was not found just fall back to the first one that was iterated. */
28052  if (bestSampleRate == 0) {
28053  bestSampleRate = firstSampleRate;
28054  }
28055 
28056  return bestSampleRate;
28057 }
28058 
28059 
28060 static ma_result ma_context_enumerate_devices__sndio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
28061 {
28062  ma_bool32 isTerminating = MA_FALSE;
28063  struct ma_sio_hdl* handle;
28064 
28065  MA_ASSERT(pContext != NULL);
28066  MA_ASSERT(callback != NULL);
28067 
28068  /* sndio doesn't seem to have a good device enumeration API, so I'm therefore only enumerating over default devices for now. */
28069 
28070  /* Playback. */
28071  if (!isTerminating) {
28072  handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_PLAY, 0);
28073  if (handle != NULL) {
28074  /* Supports playback. */
28075  ma_device_info deviceInfo;
28076  MA_ZERO_OBJECT(&deviceInfo);
28077  ma_strcpy_s(deviceInfo.id.sndio, sizeof(deviceInfo.id.sndio), MA_SIO_DEVANY);
28078  ma_strcpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
28079 
28080  isTerminating = !callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
28081 
28082  ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
28083  }
28084  }
28085 
28086  /* Capture. */
28087  if (!isTerminating) {
28088  handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_REC, 0);
28089  if (handle != NULL) {
28090  /* Supports capture. */
28091  ma_device_info deviceInfo;
28092  MA_ZERO_OBJECT(&deviceInfo);
28093  ma_strcpy_s(deviceInfo.id.sndio, sizeof(deviceInfo.id.sndio), "default");
28094  ma_strcpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME);
28095 
28096  isTerminating = !callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
28097 
28098  ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
28099  }
28100  }
28101 
28102  return MA_SUCCESS;
28103 }
28104 
28105 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)
28106 {
28107  char devid[256];
28108  struct ma_sio_hdl* handle;
28109  struct ma_sio_cap caps;
28110  unsigned int iConfig;
28111 
28112  MA_ASSERT(pContext != NULL);
28113 
28114  /* We need to open the device before we can get information about it. */
28115  if (pDeviceID == NULL) {
28116  ma_strcpy_s(devid, sizeof(devid), MA_SIO_DEVANY);
28117  ma_strcpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), (deviceType == ma_device_type_playback) ? MA_DEFAULT_PLAYBACK_DEVICE_NAME : MA_DEFAULT_CAPTURE_DEVICE_NAME);
28118  } else {
28119  ma_strcpy_s(devid, sizeof(devid), pDeviceID->sndio);
28120  ma_strcpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), devid);
28121  }
28122 
28123  handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(devid, (deviceType == ma_device_type_playback) ? MA_SIO_PLAY : MA_SIO_REC, 0);
28124  if (handle == NULL) {
28125  return MA_NO_DEVICE;
28126  }
28127 
28128  if (((ma_sio_getcap_proc)pContext->sndio.sio_getcap)(handle, &caps) == 0) {
28129  return MA_ERROR;
28130  }
28131 
28132  pDeviceInfo->nativeDataFormatCount = 0;
28133 
28134  for (iConfig = 0; iConfig < caps.nconf; iConfig += 1) {
28135  /*
28136  The main thing we care about is that the encoding is supported by miniaudio. If it is, we want to give
28137  preference to some formats over others.
28138  */
28139  unsigned int iEncoding;
28140  unsigned int iChannel;
28141  unsigned int iRate;
28142 
28143  for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
28144  unsigned int bits;
28145  unsigned int bps;
28146  unsigned int sig;
28147  unsigned int le;
28148  unsigned int msb;
28149  ma_format format;
28150 
28151  if ((caps.confs[iConfig].enc & (1UL << iEncoding)) == 0) {
28152  continue;
28153  }
28154 
28155  bits = caps.enc[iEncoding].bits;
28156  bps = caps.enc[iEncoding].bps;
28157  sig = caps.enc[iEncoding].sig;
28158  le = caps.enc[iEncoding].le;
28159  msb = caps.enc[iEncoding].msb;
28160  format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
28161  if (format == ma_format_unknown) {
28162  continue; /* Format not supported. */
28163  }
28164 
28165 
28166  /* Channels. */
28167  for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
28168  unsigned int chan = 0;
28169  unsigned int channels;
28170 
28171  if (deviceType == ma_device_type_playback) {
28172  chan = caps.confs[iConfig].pchan;
28173  } else {
28174  chan = caps.confs[iConfig].rchan;
28175  }
28176 
28177  if ((chan & (1UL << iChannel)) == 0) {
28178  continue;
28179  }
28180 
28181  if (deviceType == ma_device_type_playback) {
28182  channels = caps.pchan[iChannel];
28183  } else {
28184  channels = caps.rchan[iChannel];
28185  }
28186 
28187 
28188  /* Sample Rates. */
28189  for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
28190  if ((caps.confs[iConfig].rate & (1UL << iRate)) != 0) {
28191  ma_device_info_add_native_data_format(pDeviceInfo, format, channels, caps.rate[iRate], 0);
28192  }
28193  }
28194  }
28195  }
28196  }
28197 
28198  ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
28199  return MA_SUCCESS;
28200 }
28201 
28202 static ma_result ma_device_uninit__sndio(ma_device* pDevice)
28203 {
28204  MA_ASSERT(pDevice != NULL);
28205 
28206  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
28207  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)pDevice->sndio.handleCapture);
28208  }
28209 
28210  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
28211  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
28212  }
28213 
28214  return MA_SUCCESS;
28215 }
28216 
28217 static ma_result ma_device_init_handle__sndio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
28218 {
28219  const char* pDeviceName;
28220  ma_ptr handle;
28221  int openFlags = 0;
28222  struct ma_sio_cap caps;
28223  struct ma_sio_par par;
28224  const ma_device_id* pDeviceID;
28225  ma_format format;
28226  ma_uint32 channels;
28227  ma_uint32 sampleRate;
28228  ma_format internalFormat;
28229  ma_uint32 internalChannels;
28230  ma_uint32 internalSampleRate;
28231  ma_uint32 internalPeriodSizeInFrames;
28232  ma_uint32 internalPeriods;
28233 
28234  MA_ASSERT(pConfig != NULL);
28235  MA_ASSERT(deviceType != ma_device_type_duplex);
28236  MA_ASSERT(pDevice != NULL);
28237 
28238  if (deviceType == ma_device_type_capture) {
28239  openFlags = MA_SIO_REC;
28240  } else {
28241  openFlags = MA_SIO_PLAY;
28242  }
28243 
28244  pDeviceID = pDescriptor->pDeviceID;
28245  format = pDescriptor->format;
28246  channels = pDescriptor->channels;
28247  sampleRate = pDescriptor->sampleRate;
28248 
28249  pDeviceName = MA_SIO_DEVANY;
28250  if (pDeviceID != NULL) {
28251  pDeviceName = pDeviceID->sndio;
28252  }
28253 
28254  handle = (ma_ptr)((ma_sio_open_proc)pDevice->pContext->sndio.sio_open)(pDeviceName, openFlags, 0);
28255  if (handle == NULL) {
28256  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to open device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
28257  }
28258 
28259  /* We need to retrieve the device caps to determine the most appropriate format to use. */
28260  if (((ma_sio_getcap_proc)pDevice->pContext->sndio.sio_getcap)((struct ma_sio_hdl*)handle, &caps) == 0) {
28261  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)handle);
28262  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to retrieve device caps.", MA_ERROR);
28263  }
28264 
28265  /*
28266  Note: sndio reports a huge range of available channels. This is inconvenient for us because there's no real
28267  way, as far as I can tell, to get the _actual_ channel count of the device. I'm therefore restricting this
28268  to the requested channels, regardless of whether or not the default channel count is requested.
28269 
28270  For hardware devices, I'm suspecting only a single channel count will be reported and we can safely use the
28271  value returned by ma_find_best_channels_from_sio_cap__sndio().
28272  */
28273  if (deviceType == ma_device_type_capture) {
28274  if (format == ma_format_unknown) {
28275  format = ma_find_best_format_from_sio_cap__sndio(&caps);
28276  }
28277 
28278  if (channels == 0) {
28279  if (strlen(pDeviceName) > strlen("rsnd/") && strncmp(pDeviceName, "rsnd/", strlen("rsnd/")) == 0) {
28280  channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType, format);
28281  } else {
28282  channels = MA_DEFAULT_CHANNELS;
28283  }
28284  }
28285  } else {
28286  if (format == ma_format_unknown) {
28287  format = ma_find_best_format_from_sio_cap__sndio(&caps);
28288  }
28289 
28290  if (channels == 0) {
28291  if (strlen(pDeviceName) > strlen("rsnd/") && strncmp(pDeviceName, "rsnd/", strlen("rsnd/")) == 0) {
28292  channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType, format);
28293  } else {
28294  channels = MA_DEFAULT_CHANNELS;
28295  }
28296  }
28297  }
28298 
28299  if (sampleRate == 0) {
28300  sampleRate = ma_find_best_sample_rate_from_sio_cap__sndio(&caps, pConfig->deviceType, format, channels);
28301  }
28302 
28303 
28304  ((ma_sio_initpar_proc)pDevice->pContext->sndio.sio_initpar)(&par);
28305  par.msb = 0;
28306  par.le = ma_is_little_endian();
28307 
28308  switch (format) {
28309  case ma_format_u8:
28310  {
28311  par.bits = 8;
28312  par.bps = 1;
28313  par.sig = 0;
28314  } break;
28315 
28316  case ma_format_s24:
28317  {
28318  par.bits = 24;
28319  par.bps = 3;
28320  par.sig = 1;
28321  } break;
28322 
28323  case ma_format_s32:
28324  {
28325  par.bits = 32;
28326  par.bps = 4;
28327  par.sig = 1;
28328  } break;
28329 
28330  case ma_format_s16:
28331  case ma_format_f32:
28332  case ma_format_unknown:
28333  default:
28334  {
28335  par.bits = 16;
28336  par.bps = 2;
28337  par.sig = 1;
28338  } break;
28339  }
28340 
28341  if (deviceType == ma_device_type_capture) {
28342  par.rchan = channels;
28343  } else {
28344  par.pchan = channels;
28345  }
28346 
28347  par.rate = sampleRate;
28348 
28349  internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, par.rate, pConfig->performanceProfile);
28350 
28351  par.round = internalPeriodSizeInFrames;
28352  par.appbufsz = par.round * pDescriptor->periodCount;
28353 
28354  if (((ma_sio_setpar_proc)pDevice->pContext->sndio.sio_setpar)((struct ma_sio_hdl*)handle, &par) == 0) {
28355  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)handle);
28356  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to set buffer size.", MA_FORMAT_NOT_SUPPORTED);
28357  }
28358 
28359  if (((ma_sio_getpar_proc)pDevice->pContext->sndio.sio_getpar)((struct ma_sio_hdl*)handle, &par) == 0) {
28360  ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)handle);
28361  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to retrieve buffer size.", MA_FORMAT_NOT_SUPPORTED);
28362  }
28363 
28364  internalFormat = ma_format_from_sio_enc__sndio(par.bits, par.bps, par.sig, par.le, par.msb);
28365  internalChannels = (deviceType == ma_device_type_capture) ? par.rchan : par.pchan;
28366  internalSampleRate = par.rate;
28367  internalPeriods = par.appbufsz / par.round;
28368  internalPeriodSizeInFrames = par.round;
28369 
28370  if (deviceType == ma_device_type_capture) {
28371  pDevice->sndio.handleCapture = handle;
28372  } else {
28373  pDevice->sndio.handlePlayback = handle;
28374  }
28375 
28376  pDescriptor->format = internalFormat;
28377  pDescriptor->channels = internalChannels;
28378  pDescriptor->sampleRate = internalSampleRate;
28380  pDescriptor->periodSizeInFrames = internalPeriodSizeInFrames;
28381  pDescriptor->periodCount = internalPeriods;
28382 
28383  #ifdef MA_DEBUG_OUTPUT
28384  {
28385  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "DEVICE INFO\n");
28386  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Format: %s\n", ma_get_format_name(internalFormat));
28387  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Channels: %d\n", internalChannels);
28388  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Sample Rate: %d\n", internalSampleRate);
28389  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Period Size: %d\n", internalPeriodSizeInFrames);
28390  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " Periods: %d\n", internalPeriods);
28391  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " appbufsz: %d\n", par.appbufsz);
28392  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " round: %d\n", par.round);
28393  }
28394  #endif
28395 
28396  return MA_SUCCESS;
28397 }
28398 
28399 static ma_result ma_device_init__sndio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
28400 {
28401  MA_ASSERT(pDevice != NULL);
28402 
28403  MA_ZERO_OBJECT(&pDevice->sndio);
28404 
28405  if (pConfig->deviceType == ma_device_type_loopback) {
28407  }
28408 
28409  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
28410  ma_result result = ma_device_init_handle__sndio(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
28411  if (result != MA_SUCCESS) {
28412  return result;
28413  }
28414  }
28415 
28416  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
28417  ma_result result = ma_device_init_handle__sndio(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
28418  if (result != MA_SUCCESS) {
28419  return result;
28420  }
28421  }
28422 
28423  return MA_SUCCESS;
28424 }
28425 
28426 static ma_result ma_device_start__sndio(ma_device* pDevice)
28427 {
28428  MA_ASSERT(pDevice != NULL);
28429 
28430  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
28431  ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((struct ma_sio_hdl*)pDevice->sndio.handleCapture);
28432  }
28433 
28434  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
28435  ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback); /* <-- Doesn't actually playback until data is written. */
28436  }
28437 
28438  return MA_SUCCESS;
28439 }
28440 
28441 static ma_result ma_device_stop__sndio(ma_device* pDevice)
28442 {
28443  MA_ASSERT(pDevice != NULL);
28444 
28445  /*
28446  From the documentation:
28447 
28448  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
28449  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
28450  buffer is drained. In no case are samples in the play buffer discarded.
28451 
28452  Therefore, sio_stop() performs all of the necessary draining for us.
28453  */
28454 
28455  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
28456  ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((struct ma_sio_hdl*)pDevice->sndio.handleCapture);
28457  }
28458 
28459  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
28460  ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
28461  }
28462 
28463  return MA_SUCCESS;
28464 }
28465 
28466 static ma_result ma_device_write__sndio(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
28467 {
28468  int result;
28469 
28470  if (pFramesWritten != NULL) {
28471  *pFramesWritten = 0;
28472  }
28473 
28474  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));
28475  if (result == 0) {
28476  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[sndio] Failed to send data from the client to the device.", MA_IO_ERROR);
28477  }
28478 
28479  if (pFramesWritten != NULL) {
28480  *pFramesWritten = frameCount;
28481  }
28482 
28483  return MA_SUCCESS;
28484 }
28485 
28486 static ma_result ma_device_read__sndio(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
28487 {
28488  int result;
28489 
28490  if (pFramesRead != NULL) {
28491  *pFramesRead = 0;
28492  }
28493 
28494  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));
28495  if (result == 0) {
28496  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);
28497  }
28498 
28499  if (pFramesRead != NULL) {
28500  *pFramesRead = frameCount;
28501  }
28502 
28503  return MA_SUCCESS;
28504 }
28505 
28506 static ma_result ma_context_uninit__sndio(ma_context* pContext)
28507 {
28508  MA_ASSERT(pContext != NULL);
28509  MA_ASSERT(pContext->backend == ma_backend_sndio);
28510 
28511  (void)pContext;
28512  return MA_SUCCESS;
28513 }
28514 
28515 static ma_result ma_context_init__sndio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
28516 {
28517 #ifndef MA_NO_RUNTIME_LINKING
28518  const char* libsndioNames[] = {
28519  "libsndio.so"
28520  };
28521  size_t i;
28522 
28523  for (i = 0; i < ma_countof(libsndioNames); ++i) {
28524  pContext->sndio.sndioSO = ma_dlopen(pContext, libsndioNames[i]);
28525  if (pContext->sndio.sndioSO != NULL) {
28526  break;
28527  }
28528  }
28529 
28530  if (pContext->sndio.sndioSO == NULL) {
28531  return MA_NO_BACKEND;
28532  }
28533 
28534  pContext->sndio.sio_open = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_open");
28535  pContext->sndio.sio_close = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_close");
28536  pContext->sndio.sio_setpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_setpar");
28537  pContext->sndio.sio_getpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_getpar");
28538  pContext->sndio.sio_getcap = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_getcap");
28539  pContext->sndio.sio_write = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_write");
28540  pContext->sndio.sio_read = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_read");
28541  pContext->sndio.sio_start = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_start");
28542  pContext->sndio.sio_stop = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_stop");
28543  pContext->sndio.sio_initpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_initpar");
28544 #else
28545  pContext->sndio.sio_open = sio_open;
28546  pContext->sndio.sio_close = sio_close;
28547  pContext->sndio.sio_setpar = sio_setpar;
28548  pContext->sndio.sio_getpar = sio_getpar;
28549  pContext->sndio.sio_getcap = sio_getcap;
28550  pContext->sndio.sio_write = sio_write;
28551  pContext->sndio.sio_read = sio_read;
28552  pContext->sndio.sio_start = sio_start;
28553  pContext->sndio.sio_stop = sio_stop;
28554  pContext->sndio.sio_initpar = sio_initpar;
28555 #endif
28556 
28557  pCallbacks->onContextInit = ma_context_init__sndio;
28558  pCallbacks->onContextUninit = ma_context_uninit__sndio;
28559  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__sndio;
28560  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__sndio;
28561  pCallbacks->onDeviceInit = ma_device_init__sndio;
28562  pCallbacks->onDeviceUninit = ma_device_uninit__sndio;
28563  pCallbacks->onDeviceStart = ma_device_start__sndio;
28564  pCallbacks->onDeviceStop = ma_device_stop__sndio;
28565  pCallbacks->onDeviceRead = ma_device_read__sndio;
28566  pCallbacks->onDeviceWrite = ma_device_write__sndio;
28567  pCallbacks->onDeviceDataLoop = NULL;
28568 
28569  (void)pConfig;
28570  return MA_SUCCESS;
28571 }
28572 #endif /* sndio */
28573 
28574 
28575 
28576 /******************************************************************************
28577 
28578 audio(4) Backend
28579 
28580 ******************************************************************************/
28581 #ifdef MA_HAS_AUDIO4
28582 #include <fcntl.h>
28583 #include <poll.h>
28584 #include <errno.h>
28585 #include <sys/stat.h>
28586 #include <sys/types.h>
28587 #include <sys/ioctl.h>
28588 #include <sys/audioio.h>
28589 
28590 #if defined(__OpenBSD__)
28591  #include <sys/param.h>
28592  #if defined(OpenBSD) && OpenBSD >= 201709
28593  #define MA_AUDIO4_USE_NEW_API
28594  #endif
28595 #endif
28596 
28597 static void ma_construct_device_id__audio4(char* id, size_t idSize, const char* base, int deviceIndex)
28598 {
28599  size_t baseLen;
28600 
28601  MA_ASSERT(id != NULL);
28602  MA_ASSERT(idSize > 0);
28603  MA_ASSERT(deviceIndex >= 0);
28604 
28605  baseLen = strlen(base);
28606  MA_ASSERT(idSize > baseLen);
28607 
28608  ma_strcpy_s(id, idSize, base);
28609  ma_itoa_s(deviceIndex, id+baseLen, idSize-baseLen, 10);
28610 }
28611 
28612 static ma_result ma_extract_device_index_from_id__audio4(const char* id, const char* base, int* pIndexOut)
28613 {
28614  size_t idLen;
28615  size_t baseLen;
28616  const char* deviceIndexStr;
28617 
28618  MA_ASSERT(id != NULL);
28619  MA_ASSERT(base != NULL);
28620  MA_ASSERT(pIndexOut != NULL);
28621 
28622  idLen = strlen(id);
28623  baseLen = strlen(base);
28624  if (idLen <= baseLen) {
28625  return MA_ERROR; /* Doesn't look like the id starts with the base. */
28626  }
28627 
28628  if (strncmp(id, base, baseLen) != 0) {
28629  return MA_ERROR; /* ID does not begin with base. */
28630  }
28631 
28632  deviceIndexStr = id + baseLen;
28633  if (deviceIndexStr[0] == '\0') {
28634  return MA_ERROR; /* No index specified in the ID. */
28635  }
28636 
28637  if (pIndexOut) {
28638  *pIndexOut = atoi(deviceIndexStr);
28639  }
28640 
28641  return MA_SUCCESS;
28642 }
28643 
28644 
28645 #if !defined(MA_AUDIO4_USE_NEW_API) /* Old API */
28646 static ma_format ma_format_from_encoding__audio4(unsigned int encoding, unsigned int precision)
28647 {
28648  if (precision == 8 && (encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR_LE || encoding == AUDIO_ENCODING_ULINEAR_BE)) {
28649  return ma_format_u8;
28650  } else {
28651  if (ma_is_little_endian() && encoding == AUDIO_ENCODING_SLINEAR_LE) {
28652  if (precision == 16) {
28653  return ma_format_s16;
28654  } else if (precision == 24) {
28655  return ma_format_s24;
28656  } else if (precision == 32) {
28657  return ma_format_s32;
28658  }
28659  } else if (ma_is_big_endian() && encoding == AUDIO_ENCODING_SLINEAR_BE) {
28660  if (precision == 16) {
28661  return ma_format_s16;
28662  } else if (precision == 24) {
28663  return ma_format_s24;
28664  } else if (precision == 32) {
28665  return ma_format_s32;
28666  }
28667  }
28668  }
28669 
28670  return ma_format_unknown; /* Encoding not supported. */
28671 }
28672 
28673 static void ma_encoding_from_format__audio4(ma_format format, unsigned int* pEncoding, unsigned int* pPrecision)
28674 {
28675  MA_ASSERT(pEncoding != NULL);
28676  MA_ASSERT(pPrecision != NULL);
28677 
28678  switch (format)
28679  {
28680  case ma_format_u8:
28681  {
28682  *pEncoding = AUDIO_ENCODING_ULINEAR;
28683  *pPrecision = 8;
28684  } break;
28685 
28686  case ma_format_s24:
28687  {
28688  *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
28689  *pPrecision = 24;
28690  } break;
28691 
28692  case ma_format_s32:
28693  {
28694  *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
28695  *pPrecision = 32;
28696  } break;
28697 
28698  case ma_format_s16:
28699  case ma_format_f32:
28700  case ma_format_unknown:
28701  default:
28702  {
28703  *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
28704  *pPrecision = 16;
28705  } break;
28706  }
28707 }
28708 
28709 static ma_format ma_format_from_prinfo__audio4(struct audio_prinfo* prinfo)
28710 {
28711  return ma_format_from_encoding__audio4(prinfo->encoding, prinfo->precision);
28712 }
28713 
28714 static ma_format ma_best_format_from_fd__audio4(int fd, ma_format preferredFormat)
28715 {
28716  audio_encoding_t encoding;
28717  ma_uint32 iFormat;
28718  int counter = 0;
28719 
28720  /* First check to see if the preferred format is supported. */
28721  if (preferredFormat != ma_format_unknown) {
28722  counter = 0;
28723  for (;;) {
28724  MA_ZERO_OBJECT(&encoding);
28725  encoding.index = counter;
28726  if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
28727  break;
28728  }
28729 
28730  if (preferredFormat == ma_format_from_encoding__audio4(encoding.encoding, encoding.precision)) {
28731  return preferredFormat; /* Found the preferred format. */
28732  }
28733 
28734  /* Getting here means this encoding does not match our preferred format so we need to more on to the next encoding. */
28735  counter += 1;
28736  }
28737  }
28738 
28739  /* Getting here means our preferred format is not supported, so fall back to our standard priorities. */
28740  for (iFormat = 0; iFormat < ma_countof(g_maFormatPriorities); iFormat += 1) {
28741  ma_format format = g_maFormatPriorities[iFormat];
28742 
28743  counter = 0;
28744  for (;;) {
28745  MA_ZERO_OBJECT(&encoding);
28746  encoding.index = counter;
28747  if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
28748  break;
28749  }
28750 
28751  if (format == ma_format_from_encoding__audio4(encoding.encoding, encoding.precision)) {
28752  return format; /* Found a workable format. */
28753  }
28754 
28755  /* Getting here means this encoding does not match our preferred format so we need to more on to the next encoding. */
28756  counter += 1;
28757  }
28758  }
28759 
28760  /* Getting here means not appropriate format was found. */
28761  return ma_format_unknown;
28762 }
28763 #else
28764 static ma_format ma_format_from_swpar__audio4(struct audio_swpar* par)
28765 {
28766  if (par->bits == 8 && par->bps == 1 && par->sig == 0) {
28767  return ma_format_u8;
28768  }
28769  if (par->bits == 16 && par->bps == 2 && par->sig == 1 && par->le == ma_is_little_endian()) {
28770  return ma_format_s16;
28771  }
28772  if (par->bits == 24 && par->bps == 3 && par->sig == 1 && par->le == ma_is_little_endian()) {
28773  return ma_format_s24;
28774  }
28775  if (par->bits == 32 && par->bps == 4 && par->sig == 1 && par->le == ma_is_little_endian()) {
28776  return ma_format_f32;
28777  }
28778 
28779  /* Format not supported. */
28780  return ma_format_unknown;
28781 }
28782 #endif
28783 
28784 static ma_result ma_context_get_device_info_from_fd__audio4(ma_context* pContext, ma_device_type deviceType, int fd, ma_device_info* pDeviceInfo)
28785 {
28786  audio_device_t fdDevice;
28787 
28788  MA_ASSERT(pContext != NULL);
28789  MA_ASSERT(fd >= 0);
28790  MA_ASSERT(pDeviceInfo != NULL);
28791 
28792  (void)pContext;
28793  (void)deviceType;
28794 
28795  if (ioctl(fd, AUDIO_GETDEV, &fdDevice) < 0) {
28796  return MA_ERROR; /* Failed to retrieve device info. */
28797  }
28798 
28799  /* Name. */
28800  ma_strcpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), fdDevice.name);
28801 
28802  #if !defined(MA_AUDIO4_USE_NEW_API)
28803  {
28804  audio_info_t fdInfo;
28805  int counter = 0;
28806  ma_uint32 channels;
28807  ma_uint32 sampleRate;
28808 
28809  if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
28810  return MA_ERROR;
28811  }
28812 
28813  if (deviceType == ma_device_type_playback) {
28814  channels = fdInfo.play.channels;
28815  sampleRate = fdInfo.play.sample_rate;
28816  } else {
28817  channels = fdInfo.record.channels;
28818  sampleRate = fdInfo.record.sample_rate;
28819  }
28820 
28821  /* Supported formats. We get this by looking at the encodings. */
28822  pDeviceInfo->nativeDataFormatCount = 0;
28823  for (;;) {
28824  audio_encoding_t encoding;
28825  ma_format format;
28826 
28827  MA_ZERO_OBJECT(&encoding);
28828  encoding.index = counter;
28829  if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
28830  break;
28831  }
28832 
28833  format = ma_format_from_encoding__audio4(encoding.encoding, encoding.precision);
28834  if (format != ma_format_unknown) {
28835  ma_device_info_add_native_data_format(pDeviceInfo, format, channels, sampleRate, 0);
28836  }
28837 
28838  counter += 1;
28839  }
28840  }
28841  #else
28842  {
28843  struct audio_swpar fdPar;
28844  ma_format format;
28845  ma_uint32 channels;
28846  ma_uint32 sampleRate;
28847 
28848  if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
28849  return MA_ERROR;
28850  }
28851 
28852  format = ma_format_from_swpar__audio4(&fdPar);
28853  if (format == ma_format_unknown) {
28854  return MA_FORMAT_NOT_SUPPORTED;
28855  }
28856 
28857  if (deviceType == ma_device_type_playback) {
28858  channels = fdPar.pchan;
28859  } else {
28860  channels = fdPar.rchan;
28861  }
28862 
28863  sampleRate = fdPar.rate;
28864 
28865  pDeviceInfo->nativeDataFormatCount = 0;
28866  ma_device_info_add_native_data_format(pDeviceInfo, format, channels, sampleRate, 0);
28867  }
28868  #endif
28869 
28870  return MA_SUCCESS;
28871 }
28872 
28873 static ma_result ma_context_enumerate_devices__audio4(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
28874 {
28875  const int maxDevices = 64;
28876  char devpath[256];
28877  int iDevice;
28878 
28879  MA_ASSERT(pContext != NULL);
28880  MA_ASSERT(callback != NULL);
28881 
28882  /*
28883  Every device will be named "/dev/audioN", with a "/dev/audioctlN" equivalent. We use the "/dev/audioctlN"
28884  version here since we can open it even when another process has control of the "/dev/audioN" device.
28885  */
28886  for (iDevice = 0; iDevice < maxDevices; ++iDevice) {
28887  struct stat st;
28888  int fd;
28889  ma_bool32 isTerminating = MA_FALSE;
28890 
28891  ma_strcpy_s(devpath, sizeof(devpath), "/dev/audioctl");
28892  ma_itoa_s(iDevice, devpath+strlen(devpath), sizeof(devpath)-strlen(devpath), 10);
28893 
28894  if (stat(devpath, &st) < 0) {
28895  break;
28896  }
28897 
28898  /* The device exists, but we need to check if it's usable as playback and/or capture. */
28899 
28900  /* Playback. */
28901  if (!isTerminating) {
28902  fd = open(devpath, O_RDONLY, 0);
28903  if (fd >= 0) {
28904  /* Supports playback. */
28905  ma_device_info deviceInfo;
28906  MA_ZERO_OBJECT(&deviceInfo);
28907  ma_construct_device_id__audio4(deviceInfo.id.audio4, sizeof(deviceInfo.id.audio4), "/dev/audio", iDevice);
28908  if (ma_context_get_device_info_from_fd__audio4(pContext, ma_device_type_playback, fd, &deviceInfo) == MA_SUCCESS) {
28909  isTerminating = !callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
28910  }
28911 
28912  close(fd);
28913  }
28914  }
28915 
28916  /* Capture. */
28917  if (!isTerminating) {
28918  fd = open(devpath, O_WRONLY, 0);
28919  if (fd >= 0) {
28920  /* Supports capture. */
28921  ma_device_info deviceInfo;
28922  MA_ZERO_OBJECT(&deviceInfo);
28923  ma_construct_device_id__audio4(deviceInfo.id.audio4, sizeof(deviceInfo.id.audio4), "/dev/audio", iDevice);
28924  if (ma_context_get_device_info_from_fd__audio4(pContext, ma_device_type_capture, fd, &deviceInfo) == MA_SUCCESS) {
28925  isTerminating = !callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
28926  }
28927 
28928  close(fd);
28929  }
28930  }
28931 
28932  if (isTerminating) {
28933  break;
28934  }
28935  }
28936 
28937  return MA_SUCCESS;
28938 }
28939 
28940 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)
28941 {
28942  int fd = -1;
28943  int deviceIndex = -1;
28944  char ctlid[256];
28945  ma_result result;
28946 
28947  MA_ASSERT(pContext != NULL);
28948 
28949  /*
28950  We need to open the "/dev/audioctlN" device to get the info. To do this we need to extract the number
28951  from the device ID which will be in "/dev/audioN" format.
28952  */
28953  if (pDeviceID == NULL) {
28954  /* Default device. */
28955  ma_strcpy_s(ctlid, sizeof(ctlid), "/dev/audioctl");
28956  } else {
28957  /* Specific device. We need to convert from "/dev/audioN" to "/dev/audioctlN". */
28958  result = ma_extract_device_index_from_id__audio4(pDeviceID->audio4, "/dev/audio", &deviceIndex);
28959  if (result != MA_SUCCESS) {
28960  return result;
28961  }
28962 
28963  ma_construct_device_id__audio4(ctlid, sizeof(ctlid), "/dev/audioctl", deviceIndex);
28964  }
28965 
28966  fd = open(ctlid, (deviceType == ma_device_type_playback) ? O_WRONLY : O_RDONLY, 0);
28967  if (fd == -1) {
28968  return MA_NO_DEVICE;
28969  }
28970 
28971  if (deviceIndex == -1) {
28972  ma_strcpy_s(pDeviceInfo->id.audio4, sizeof(pDeviceInfo->id.audio4), "/dev/audio");
28973  } else {
28974  ma_construct_device_id__audio4(pDeviceInfo->id.audio4, sizeof(pDeviceInfo->id.audio4), "/dev/audio", deviceIndex);
28975  }
28976 
28977  result = ma_context_get_device_info_from_fd__audio4(pContext, deviceType, fd, pDeviceInfo);
28978 
28979  close(fd);
28980  return result;
28981 }
28982 
28983 static ma_result ma_device_uninit__audio4(ma_device* pDevice)
28984 {
28985  MA_ASSERT(pDevice != NULL);
28986 
28987  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
28988  close(pDevice->audio4.fdCapture);
28989  }
28990 
28991  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
28992  close(pDevice->audio4.fdPlayback);
28993  }
28994 
28995  return MA_SUCCESS;
28996 }
28997 
28998 static ma_result ma_device_init_fd__audio4(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
28999 {
29000  const char* pDefaultDeviceNames[] = {
29001  "/dev/audio",
29002  "/dev/audio0"
29003  };
29004  int fd;
29005  int fdFlags = 0;
29006  ma_format internalFormat;
29007  ma_uint32 internalChannels;
29008  ma_uint32 internalSampleRate;
29009  ma_uint32 internalPeriodSizeInFrames;
29010  ma_uint32 internalPeriods;
29011 
29012  MA_ASSERT(pConfig != NULL);
29013  MA_ASSERT(deviceType != ma_device_type_duplex);
29014  MA_ASSERT(pDevice != NULL);
29015 
29016  /* The first thing to do is open the file. */
29017  if (deviceType == ma_device_type_capture) {
29018  fdFlags = O_RDONLY;
29019  } else {
29020  fdFlags = O_WRONLY;
29021  }
29022  /*fdFlags |= O_NONBLOCK;*/
29023 
29024  if (pDescriptor->pDeviceID == NULL) {
29025  /* Default device. */
29026  size_t iDevice;
29027  for (iDevice = 0; iDevice < ma_countof(pDefaultDeviceNames); ++iDevice) {
29028  fd = open(pDefaultDeviceNames[iDevice], fdFlags, 0);
29029  if (fd != -1) {
29030  break;
29031  }
29032  }
29033  } else {
29034  /* Specific device. */
29035  fd = open(pDescriptor->pDeviceID->audio4, fdFlags, 0);
29036  }
29037 
29038  if (fd == -1) {
29039  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to open device.", ma_result_from_errno(errno));
29040  }
29041 
29042  #if !defined(MA_AUDIO4_USE_NEW_API) /* Old API */
29043  {
29044  audio_info_t fdInfo;
29045 
29046  /*
29047  The documentation is a little bit unclear to me as to how it handles formats. It says the
29048  following:
29049 
29050  Regardless of formats supported by underlying driver, the audio driver accepts the
29051  following formats.
29052 
29053  By then the next sentence says this:
29054 
29055  `encoding` and `precision` are one of the values obtained by AUDIO_GETENC.
29056 
29057  It sounds like a direct contradiction to me. I'm going to play this safe any only use the
29058  best sample format returned by AUDIO_GETENC. If the requested format is supported we'll
29059  use that, but otherwise we'll just use our standard format priorities to pick an
29060  appropriate one.
29061  */
29062  AUDIO_INITINFO(&fdInfo);
29063 
29064  /* We get the driver to do as much of the data conversion as possible. */
29065  if (deviceType == ma_device_type_capture) {
29066  fdInfo.mode = AUMODE_RECORD;
29067  ma_encoding_from_format__audio4(ma_best_format_from_fd__audio4(fd, pDescriptor->format), &fdInfo.record.encoding, &fdInfo.record.precision);
29068 
29069  if (pDescriptor->channels != 0) {
29070  fdInfo.record.channels = ma_clamp(pDescriptor->channels, 1, 12); /* From the documentation: `channels` ranges from 1 to 12. */
29071  }
29072 
29073  if (pDescriptor->sampleRate != 0) {
29074  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`.) */
29075  }
29076  } else {
29077  fdInfo.mode = AUMODE_PLAY;
29078  ma_encoding_from_format__audio4(ma_best_format_from_fd__audio4(fd, pDescriptor->format), &fdInfo.play.encoding, &fdInfo.play.precision);
29079 
29080  if (pDescriptor->channels != 0) {
29081  fdInfo.play.channels = ma_clamp(pDescriptor->channels, 1, 12); /* From the documentation: `channels` ranges from 1 to 12. */
29082  }
29083 
29084  if (pDescriptor->sampleRate != 0) {
29085  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`.) */
29086  }
29087  }
29088 
29089  if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
29090  close(fd);
29091  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to set device format. AUDIO_SETINFO failed.", MA_FORMAT_NOT_SUPPORTED);
29092  }
29093 
29094  if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
29095  close(fd);
29096  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] AUDIO_GETINFO failed.", MA_FORMAT_NOT_SUPPORTED);
29097  }
29098 
29099  if (deviceType == ma_device_type_capture) {
29100  internalFormat = ma_format_from_prinfo__audio4(&fdInfo.record);
29101  internalChannels = fdInfo.record.channels;
29102  internalSampleRate = fdInfo.record.sample_rate;
29103  } else {
29104  internalFormat = ma_format_from_prinfo__audio4(&fdInfo.play);
29105  internalChannels = fdInfo.play.channels;
29106  internalSampleRate = fdInfo.play.sample_rate;
29107  }
29108 
29109  if (internalFormat == ma_format_unknown) {
29110  close(fd);
29111  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);
29112  }
29113 
29114  /* Buffer. */
29115  {
29116  ma_uint32 internalPeriodSizeInBytes;
29117 
29118  internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, internalSampleRate, pConfig->performanceProfile);
29119 
29120  internalPeriodSizeInBytes = internalPeriodSizeInFrames * ma_get_bytes_per_frame(internalFormat, internalChannels);
29121  if (internalPeriodSizeInBytes < 16) {
29122  internalPeriodSizeInBytes = 16;
29123  }
29124 
29125  internalPeriods = pDescriptor->periodCount;
29126  if (internalPeriods < 2) {
29127  internalPeriods = 2;
29128  }
29129 
29130  /* What miniaudio calls a period, audio4 calls a block. */
29131  AUDIO_INITINFO(&fdInfo);
29132  fdInfo.hiwat = internalPeriods;
29133  fdInfo.lowat = internalPeriods-1;
29134  fdInfo.blocksize = internalPeriodSizeInBytes;
29135  if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
29136  close(fd);
29137  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to set internal buffer size. AUDIO_SETINFO failed.", MA_FORMAT_NOT_SUPPORTED);
29138  }
29139 
29140  internalPeriods = fdInfo.hiwat;
29141  internalPeriodSizeInFrames = fdInfo.blocksize / ma_get_bytes_per_frame(internalFormat, internalChannels);
29142  }
29143  }
29144  #else
29145  {
29146  struct audio_swpar fdPar;
29147 
29148  /* 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. */
29149  if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
29150  close(fd);
29151  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to retrieve initial device parameters.", MA_FORMAT_NOT_SUPPORTED);
29152  }
29153 
29154  internalFormat = ma_format_from_swpar__audio4(&fdPar);
29155  internalChannels = (deviceType == ma_device_type_capture) ? fdPar.rchan : fdPar.pchan;
29156  internalSampleRate = fdPar.rate;
29157 
29158  if (internalFormat == ma_format_unknown) {
29159  close(fd);
29160  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);
29161  }
29162 
29163  /* Buffer. */
29164  {
29165  ma_uint32 internalPeriodSizeInBytes;
29166 
29167  internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, internalSampleRate, pConfig->performanceProfile);
29168 
29169  /* What miniaudio calls a period, audio4 calls a block. */
29170  internalPeriodSizeInBytes = internalPeriodSizeInFrames * ma_get_bytes_per_frame(internalFormat, internalChannels);
29171  if (internalPeriodSizeInBytes < 16) {
29172  internalPeriodSizeInBytes = 16;
29173  }
29174 
29175  fdPar.nblks = pDescriptor->periodCount;
29176  fdPar.round = internalPeriodSizeInBytes;
29177 
29178  if (ioctl(fd, AUDIO_SETPAR, &fdPar) < 0) {
29179  close(fd);
29180  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to set device parameters.", MA_FORMAT_NOT_SUPPORTED);
29181  }
29182 
29183  if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
29184  close(fd);
29185  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to retrieve actual device parameters.", MA_FORMAT_NOT_SUPPORTED);
29186  }
29187  }
29188 
29189  internalFormat = ma_format_from_swpar__audio4(&fdPar);
29190  internalChannels = (deviceType == ma_device_type_capture) ? fdPar.rchan : fdPar.pchan;
29191  internalSampleRate = fdPar.rate;
29192  internalPeriods = fdPar.nblks;
29193  internalPeriodSizeInFrames = fdPar.round / ma_get_bytes_per_frame(internalFormat, internalChannels);
29194  }
29195  #endif
29196 
29197  if (internalFormat == ma_format_unknown) {
29198  close(fd);
29199  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);
29200  }
29201 
29202  if (deviceType == ma_device_type_capture) {
29203  pDevice->audio4.fdCapture = fd;
29204  } else {
29205  pDevice->audio4.fdPlayback = fd;
29206  }
29207 
29208  pDescriptor->format = internalFormat;
29209  pDescriptor->channels = internalChannels;
29210  pDescriptor->sampleRate = internalSampleRate;
29212  pDescriptor->periodSizeInFrames = internalPeriodSizeInFrames;
29213  pDescriptor->periodCount = internalPeriods;
29214 
29215  return MA_SUCCESS;
29216 }
29217 
29218 static ma_result ma_device_init__audio4(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
29219 {
29220  MA_ASSERT(pDevice != NULL);
29221 
29222  MA_ZERO_OBJECT(&pDevice->audio4);
29223 
29224  if (pConfig->deviceType == ma_device_type_loopback) {
29226  }
29227 
29228  pDevice->audio4.fdCapture = -1;
29229  pDevice->audio4.fdPlayback = -1;
29230 
29231  /*
29232  The version of the operating system dictates whether or not the device is exclusive or shared. NetBSD
29233  introduced in-kernel mixing which means it's shared. All other BSD flavours are exclusive as far as
29234  I'm aware.
29235  */
29236 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 800000000
29237  /* NetBSD 8.0+ */
29238  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
29239  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
29241  }
29242 #else
29243  /* All other flavors. */
29244 #endif
29245 
29246  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
29247  ma_result result = ma_device_init_fd__audio4(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
29248  if (result != MA_SUCCESS) {
29249  return result;
29250  }
29251  }
29252 
29253  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
29254  ma_result result = ma_device_init_fd__audio4(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
29255  if (result != MA_SUCCESS) {
29256  if (pConfig->deviceType == ma_device_type_duplex) {
29257  close(pDevice->audio4.fdCapture);
29258  }
29259  return result;
29260  }
29261  }
29262 
29263  return MA_SUCCESS;
29264 }
29265 
29266 static ma_result ma_device_start__audio4(ma_device* pDevice)
29267 {
29268  MA_ASSERT(pDevice != NULL);
29269 
29270  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
29271  if (pDevice->audio4.fdCapture == -1) {
29272  return MA_INVALID_ARGS;
29273  }
29274  }
29275 
29276  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
29277  if (pDevice->audio4.fdPlayback == -1) {
29278  return MA_INVALID_ARGS;
29279  }
29280  }
29281 
29282  return MA_SUCCESS;
29283 }
29284 
29285 static ma_result ma_device_stop_fd__audio4(ma_device* pDevice, int fd)
29286 {
29287  if (fd == -1) {
29288  return MA_INVALID_ARGS;
29289  }
29290 
29291 #if !defined(MA_AUDIO4_USE_NEW_API)
29292  if (ioctl(fd, AUDIO_FLUSH, 0) < 0) {
29293  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to stop device. AUDIO_FLUSH failed.", ma_result_from_errno(errno));
29294  }
29295 #else
29296  if (ioctl(fd, AUDIO_STOP, 0) < 0) {
29297  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to stop device. AUDIO_STOP failed.", ma_result_from_errno(errno));
29298  }
29299 #endif
29300 
29301  return MA_SUCCESS;
29302 }
29303 
29304 static ma_result ma_device_stop__audio4(ma_device* pDevice)
29305 {
29306  MA_ASSERT(pDevice != NULL);
29307 
29308  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
29309  ma_result result;
29310 
29311  result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdCapture);
29312  if (result != MA_SUCCESS) {
29313  return result;
29314  }
29315  }
29316 
29317  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
29318  ma_result result;
29319 
29320  /* 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. */
29321  #if !defined(MA_AUDIO4_USE_NEW_API)
29322  ioctl(pDevice->audio4.fdPlayback, AUDIO_DRAIN, 0);
29323  #endif
29324 
29325  /* Here is where the device is stopped immediately. */
29326  result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdPlayback);
29327  if (result != MA_SUCCESS) {
29328  return result;
29329  }
29330  }
29331 
29332  return MA_SUCCESS;
29333 }
29334 
29335 static ma_result ma_device_write__audio4(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
29336 {
29337  int result;
29338 
29339  if (pFramesWritten != NULL) {
29340  *pFramesWritten = 0;
29341  }
29342 
29343  result = write(pDevice->audio4.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
29344  if (result < 0) {
29345  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to write data to the device.", ma_result_from_errno(errno));
29346  }
29347 
29348  if (pFramesWritten != NULL) {
29349  *pFramesWritten = (ma_uint32)result / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
29350  }
29351 
29352  return MA_SUCCESS;
29353 }
29354 
29355 static ma_result ma_device_read__audio4(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
29356 {
29357  int result;
29358 
29359  if (pFramesRead != NULL) {
29360  *pFramesRead = 0;
29361  }
29362 
29363  result = read(pDevice->audio4.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
29364  if (result < 0) {
29365  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[audio4] Failed to read data from the device.", ma_result_from_errno(errno));
29366  }
29367 
29368  if (pFramesRead != NULL) {
29369  *pFramesRead = (ma_uint32)result / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
29370  }
29371 
29372  return MA_SUCCESS;
29373 }
29374 
29375 static ma_result ma_context_uninit__audio4(ma_context* pContext)
29376 {
29377  MA_ASSERT(pContext != NULL);
29378  MA_ASSERT(pContext->backend == ma_backend_audio4);
29379 
29380  (void)pContext;
29381  return MA_SUCCESS;
29382 }
29383 
29384 static ma_result ma_context_init__audio4(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
29385 {
29386  MA_ASSERT(pContext != NULL);
29387 
29388  (void)pConfig;
29389 
29390  pCallbacks->onContextInit = ma_context_init__audio4;
29391  pCallbacks->onContextUninit = ma_context_uninit__audio4;
29392  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__audio4;
29393  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__audio4;
29394  pCallbacks->onDeviceInit = ma_device_init__audio4;
29395  pCallbacks->onDeviceUninit = ma_device_uninit__audio4;
29396  pCallbacks->onDeviceStart = ma_device_start__audio4;
29397  pCallbacks->onDeviceStop = ma_device_stop__audio4;
29398  pCallbacks->onDeviceRead = ma_device_read__audio4;
29399  pCallbacks->onDeviceWrite = ma_device_write__audio4;
29400  pCallbacks->onDeviceDataLoop = NULL;
29401 
29402  return MA_SUCCESS;
29403 }
29404 #endif /* audio4 */
29405 
29406 
29407 /******************************************************************************
29408 
29409 OSS Backend
29410 
29411 ******************************************************************************/
29412 #ifdef MA_HAS_OSS
29413 #include <sys/ioctl.h>
29414 #include <unistd.h>
29415 #include <fcntl.h>
29416 #include <sys/soundcard.h>
29417 
29418 #ifndef SNDCTL_DSP_HALT
29419 #define SNDCTL_DSP_HALT SNDCTL_DSP_RESET
29420 #endif
29421 
29422 #define MA_OSS_DEFAULT_DEVICE_NAME "/dev/dsp"
29423 
29424 static int ma_open_temp_device__oss()
29425 {
29426  /* The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same. */
29427  int fd = open("/dev/mixer", O_RDONLY, 0);
29428  if (fd >= 0) {
29429  return fd;
29430  }
29431 
29432  return -1;
29433 }
29434 
29435 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)
29436 {
29437  const char* deviceName;
29438  int flags;
29439 
29440  MA_ASSERT(pContext != NULL);
29441  MA_ASSERT(pfd != NULL);
29442  (void)pContext;
29443 
29444  *pfd = -1;
29445 
29446  /* This function should only be called for playback or capture, not duplex. */
29447  if (deviceType == ma_device_type_duplex) {
29448  return MA_INVALID_ARGS;
29449  }
29450 
29451  deviceName = MA_OSS_DEFAULT_DEVICE_NAME;
29452  if (pDeviceID != NULL) {
29453  deviceName = pDeviceID->oss;
29454  }
29455 
29456  flags = (deviceType == ma_device_type_playback) ? O_WRONLY : O_RDONLY;
29457  if (shareMode == ma_share_mode_exclusive) {
29458  flags |= O_EXCL;
29459  }
29460 
29461  *pfd = open(deviceName, flags, 0);
29462  if (*pfd == -1) {
29463  return ma_result_from_errno(errno);
29464  }
29465 
29466  return MA_SUCCESS;
29467 }
29468 
29469 static ma_result ma_context_enumerate_devices__oss(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
29470 {
29471  int fd;
29472  oss_sysinfo si;
29473  int result;
29474 
29475  MA_ASSERT(pContext != NULL);
29476  MA_ASSERT(callback != NULL);
29477 
29478  fd = ma_open_temp_device__oss();
29479  if (fd == -1) {
29480  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);
29481  }
29482 
29483  result = ioctl(fd, SNDCTL_SYSINFO, &si);
29484  if (result != -1) {
29485  int iAudioDevice;
29486  for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
29487  oss_audioinfo ai;
29488  ai.dev = iAudioDevice;
29489  result = ioctl(fd, SNDCTL_AUDIOINFO, &ai);
29490  if (result != -1) {
29491  if (ai.devnode[0] != '\0') { /* <-- Can be blank, according to documentation. */
29492  ma_device_info deviceInfo;
29493  ma_bool32 isTerminating = MA_FALSE;
29494 
29495  MA_ZERO_OBJECT(&deviceInfo);
29496 
29497  /* ID */
29498  ma_strncpy_s(deviceInfo.id.oss, sizeof(deviceInfo.id.oss), ai.devnode, (size_t)-1);
29499 
29500  /*
29501  The human readable device name should be in the "ai.handle" variable, but it can
29502  sometimes be empty in which case we just fall back to "ai.name" which is less user
29503  friendly, but usually has a value.
29504  */
29505  if (ai.handle[0] != '\0') {
29506  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), ai.handle, (size_t)-1);
29507  } else {
29508  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), ai.name, (size_t)-1);
29509  }
29510 
29511  /* The device can be both playback and capture. */
29512  if (!isTerminating && (ai.caps & PCM_CAP_OUTPUT) != 0) {
29513  isTerminating = !callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
29514  }
29515  if (!isTerminating && (ai.caps & PCM_CAP_INPUT) != 0) {
29516  isTerminating = !callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
29517  }
29518 
29519  if (isTerminating) {
29520  break;
29521  }
29522  }
29523  }
29524  }
29525  } else {
29526  close(fd);
29527  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve system information for device enumeration.", MA_NO_BACKEND);
29528  }
29529 
29530  close(fd);
29531  return MA_SUCCESS;
29532 }
29533 
29534 static void ma_context_add_native_data_format__oss(ma_context* pContext, oss_audioinfo* pAudioInfo, ma_format format, ma_device_info* pDeviceInfo)
29535 {
29536  unsigned int minChannels;
29537  unsigned int maxChannels;
29538  unsigned int iRate;
29539 
29540  MA_ASSERT(pContext != NULL);
29541  MA_ASSERT(pAudioInfo != NULL);
29542  MA_ASSERT(pDeviceInfo != NULL);
29543 
29544  /* If we support all channels we just report 0. */
29545  minChannels = ma_clamp(pAudioInfo->min_channels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
29546  maxChannels = ma_clamp(pAudioInfo->max_channels, MA_MIN_CHANNELS, MA_MAX_CHANNELS);
29547 
29548  /*
29549  OSS has this annoying thing where sample rates can be reported in two ways. We prefer explicitness,
29550  which OSS has in the form of nrates/rates, however there are times where nrates can be 0, in which
29551  case we'll need to use min_rate and max_rate and report only standard rates.
29552  */
29553  if (pAudioInfo->nrates > 0) {
29554  for (iRate = 0; iRate < pAudioInfo->nrates; iRate += 1) {
29555  unsigned int rate = pAudioInfo->rates[iRate];
29556 
29557  if (minChannels == MA_MIN_CHANNELS && maxChannels == MA_MAX_CHANNELS) {
29558  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. */
29559  } else {
29560  unsigned int iChannel;
29561  for (iChannel = minChannels; iChannel <= maxChannels; iChannel += 1) {
29562  ma_device_info_add_native_data_format(pDeviceInfo, format, iChannel, rate, 0);
29563  }
29564  }
29565  }
29566  } else {
29567  for (iRate = 0; iRate < ma_countof(g_maStandardSampleRatePriorities); iRate += 1) {
29568  ma_uint32 standardRate = g_maStandardSampleRatePriorities[iRate];
29569 
29570  if (standardRate >= (ma_uint32)pAudioInfo->min_rate && standardRate <= (ma_uint32)pAudioInfo->max_rate) {
29571  if (minChannels == MA_MIN_CHANNELS && maxChannels == MA_MAX_CHANNELS) {
29572  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. */
29573  } else {
29574  unsigned int iChannel;
29575  for (iChannel = minChannels; iChannel <= maxChannels; iChannel += 1) {
29576  ma_device_info_add_native_data_format(pDeviceInfo, format, iChannel, standardRate, 0);
29577  }
29578  }
29579  }
29580  }
29581  }
29582 }
29583 
29584 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)
29585 {
29586  ma_bool32 foundDevice;
29587  int fdTemp;
29588  oss_sysinfo si;
29589  int result;
29590 
29591  MA_ASSERT(pContext != NULL);
29592 
29593  /* Handle the default device a little differently. */
29594  if (pDeviceID == NULL) {
29595  if (deviceType == ma_device_type_playback) {
29596  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
29597  } else {
29598  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
29599  }
29600 
29601  return MA_SUCCESS;
29602  }
29603 
29604 
29605  /* If we get here it means we are _not_ using the default device. */
29606  foundDevice = MA_FALSE;
29607 
29608  fdTemp = ma_open_temp_device__oss();
29609  if (fdTemp == -1) {
29610  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);
29611  }
29612 
29613  result = ioctl(fdTemp, SNDCTL_SYSINFO, &si);
29614  if (result != -1) {
29615  int iAudioDevice;
29616  for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
29617  oss_audioinfo ai;
29618  ai.dev = iAudioDevice;
29619  result = ioctl(fdTemp, SNDCTL_AUDIOINFO, &ai);
29620  if (result != -1) {
29621  if (ma_strcmp(ai.devnode, pDeviceID->oss) == 0) {
29622  /* It has the same name, so now just confirm the type. */
29623  if ((deviceType == ma_device_type_playback && ((ai.caps & PCM_CAP_OUTPUT) != 0)) ||
29624  (deviceType == ma_device_type_capture && ((ai.caps & PCM_CAP_INPUT) != 0))) {
29625  unsigned int formatMask;
29626 
29627  /* ID */
29628  ma_strncpy_s(pDeviceInfo->id.oss, sizeof(pDeviceInfo->id.oss), ai.devnode, (size_t)-1);
29629 
29630  /*
29631  The human readable device name should be in the "ai.handle" variable, but it can
29632  sometimes be empty in which case we just fall back to "ai.name" which is less user
29633  friendly, but usually has a value.
29634  */
29635  if (ai.handle[0] != '\0') {
29636  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ai.handle, (size_t)-1);
29637  } else {
29638  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ai.name, (size_t)-1);
29639  }
29640 
29641 
29642  pDeviceInfo->nativeDataFormatCount = 0;
29643 
29644  if (deviceType == ma_device_type_playback) {
29645  formatMask = ai.oformats;
29646  } else {
29647  formatMask = ai.iformats;
29648  }
29649 
29650  if (((formatMask & AFMT_S16_LE) != 0 && ma_is_little_endian()) || (AFMT_S16_BE && ma_is_big_endian())) {
29651  ma_context_add_native_data_format__oss(pContext, &ai, ma_format_s16, pDeviceInfo);
29652  }
29653  if (((formatMask & AFMT_S32_LE) != 0 && ma_is_little_endian()) || (AFMT_S32_BE && ma_is_big_endian())) {
29654  ma_context_add_native_data_format__oss(pContext, &ai, ma_format_s32, pDeviceInfo);
29655  }
29656  if ((formatMask & AFMT_U8) != 0) {
29657  ma_context_add_native_data_format__oss(pContext, &ai, ma_format_u8, pDeviceInfo);
29658  }
29659 
29660  foundDevice = MA_TRUE;
29661  break;
29662  }
29663  }
29664  }
29665  }
29666  } else {
29667  close(fdTemp);
29668  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve system information for device enumeration.", MA_NO_BACKEND);
29669  }
29670 
29671 
29672  close(fdTemp);
29673 
29674  if (!foundDevice) {
29675  return MA_NO_DEVICE;
29676  }
29677 
29678  return MA_SUCCESS;
29679 }
29680 
29681 static ma_result ma_device_uninit__oss(ma_device* pDevice)
29682 {
29683  MA_ASSERT(pDevice != NULL);
29684 
29685  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
29686  close(pDevice->oss.fdCapture);
29687  }
29688 
29689  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
29690  close(pDevice->oss.fdPlayback);
29691  }
29692 
29693  return MA_SUCCESS;
29694 }
29695 
29696 static int ma_format_to_oss(ma_format format)
29697 {
29698  int ossFormat = AFMT_U8;
29699  switch (format) {
29700  case ma_format_s16: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break;
29701  case ma_format_s24: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break;
29702  case ma_format_s32: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break;
29703  case ma_format_f32: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break;
29704  case ma_format_u8:
29705  default: ossFormat = AFMT_U8; break;
29706  }
29707 
29708  return ossFormat;
29709 }
29710 
29711 static ma_format ma_format_from_oss(int ossFormat)
29712 {
29713  if (ossFormat == AFMT_U8) {
29714  return ma_format_u8;
29715  } else {
29716  if (ma_is_little_endian()) {
29717  switch (ossFormat) {
29718  case AFMT_S16_LE: return ma_format_s16;
29719  case AFMT_S32_LE: return ma_format_s32;
29720  default: return ma_format_unknown;
29721  }
29722  } else {
29723  switch (ossFormat) {
29724  case AFMT_S16_BE: return ma_format_s16;
29725  case AFMT_S32_BE: return ma_format_s32;
29726  default: return ma_format_unknown;
29727  }
29728  }
29729  }
29730 
29731  return ma_format_unknown;
29732 }
29733 
29734 static ma_result ma_device_init_fd__oss(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor, ma_device_type deviceType)
29735 {
29736  ma_result result;
29737  int ossResult;
29738  int fd;
29739  const ma_device_id* pDeviceID = NULL;
29740  ma_share_mode shareMode;
29741  int ossFormat;
29742  int ossChannels;
29743  int ossSampleRate;
29744  int ossFragment;
29745 
29746  MA_ASSERT(pDevice != NULL);
29747  MA_ASSERT(pConfig != NULL);
29748  MA_ASSERT(deviceType != ma_device_type_duplex);
29749 
29750  pDeviceID = pDescriptor->pDeviceID;
29751  shareMode = pDescriptor->shareMode;
29752  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. */
29753  ossChannels = (int)(pDescriptor->channels > 0) ? pDescriptor->channels : MA_DEFAULT_CHANNELS;
29754  ossSampleRate = (int)(pDescriptor->sampleRate > 0) ? pDescriptor->sampleRate : MA_DEFAULT_SAMPLE_RATE;
29755 
29756  result = ma_context_open_device__oss(pDevice->pContext, deviceType, pDeviceID, shareMode, &fd);
29757  if (result != MA_SUCCESS) {
29758  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", result);
29759  }
29760 
29761  /*
29762  The OSS documantation is very clear about the order we should be initializing the device's properties:
29763  1) Format
29764  2) Channels
29765  3) Sample rate.
29766  */
29767 
29768  /* Format. */
29769  ossResult = ioctl(fd, SNDCTL_DSP_SETFMT, &ossFormat);
29770  if (ossResult == -1) {
29771  close(fd);
29772  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set format.", MA_FORMAT_NOT_SUPPORTED);
29773  }
29774 
29775  /* Channels. */
29776  ossResult = ioctl(fd, SNDCTL_DSP_CHANNELS, &ossChannels);
29777  if (ossResult == -1) {
29778  close(fd);
29779  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set channel count.", MA_FORMAT_NOT_SUPPORTED);
29780  }
29781 
29782  /* Sample Rate. */
29783  ossResult = ioctl(fd, SNDCTL_DSP_SPEED, &ossSampleRate);
29784  if (ossResult == -1) {
29785  close(fd);
29786  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set sample rate.", MA_FORMAT_NOT_SUPPORTED);
29787  }
29788 
29789  /*
29790  Buffer.
29791 
29792  The documentation says that the fragment settings should be set as soon as possible, but I'm not sure if
29793  it should be done before or after format/channels/rate.
29794 
29795  OSS wants the fragment size in bytes and a power of 2. When setting, we specify the power, not the actual
29796  value.
29797  */
29798  {
29799  ma_uint32 periodSizeInFrames;
29800  ma_uint32 periodSizeInBytes;
29801  ma_uint32 ossFragmentSizePower;
29802 
29803  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, (ma_uint32)ossSampleRate, pConfig->performanceProfile);
29804 
29805  periodSizeInBytes = ma_round_to_power_of_2(periodSizeInFrames * ma_get_bytes_per_frame(ma_format_from_oss(ossFormat), ossChannels));
29806  if (periodSizeInBytes < 16) {
29807  periodSizeInBytes = 16;
29808  }
29809 
29810  ossFragmentSizePower = 4;
29811  periodSizeInBytes >>= 4;
29812  while (periodSizeInBytes >>= 1) {
29813  ossFragmentSizePower += 1;
29814  }
29815 
29816  ossFragment = (int)((pConfig->periods << 16) | ossFragmentSizePower);
29817  ossResult = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossFragment);
29818  if (ossResult == -1) {
29819  close(fd);
29820  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to set fragment size and period count.", MA_FORMAT_NOT_SUPPORTED);
29821  }
29822  }
29823 
29824  /* Internal settings. */
29825  if (deviceType == ma_device_type_capture) {
29826  pDevice->oss.fdCapture = fd;
29827  } else {
29828  pDevice->oss.fdPlayback = fd;
29829  }
29830 
29831  pDescriptor->format = ma_format_from_oss(ossFormat);
29832  pDescriptor->channels = ossChannels;
29833  pDescriptor->sampleRate = ossSampleRate;
29835  pDescriptor->periodCount = (ma_uint32)(ossFragment >> 16);
29836  pDescriptor->periodSizeInFrames = (ma_uint32)(1 << (ossFragment & 0xFFFF)) / ma_get_bytes_per_frame(pDescriptor->format, pDescriptor->channels);
29837 
29838  if (pDescriptor->format == ma_format_unknown) {
29839  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] The device's internal format is not supported by miniaudio.", MA_FORMAT_NOT_SUPPORTED);
29840  }
29841 
29842  return MA_SUCCESS;
29843 }
29844 
29845 static ma_result ma_device_init__oss(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
29846 {
29847  MA_ASSERT(pDevice != NULL);
29848  MA_ASSERT(pConfig != NULL);
29849 
29850  MA_ZERO_OBJECT(&pDevice->oss);
29851 
29852  if (pConfig->deviceType == ma_device_type_loopback) {
29854  }
29855 
29856  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
29857  ma_result result = ma_device_init_fd__oss(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
29858  if (result != MA_SUCCESS) {
29859  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", result);
29860  }
29861  }
29862 
29863  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
29864  ma_result result = ma_device_init_fd__oss(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
29865  if (result != MA_SUCCESS) {
29866  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OSS] Failed to open device.", result);
29867  }
29868  }
29869 
29870  return MA_SUCCESS;
29871 }
29872 
29873 /*
29874 Note on Starting and Stopping
29875 =============================
29876 In the past I was using SNDCTL_DSP_HALT to stop the device, however this results in issues when
29877 trying to resume the device again. If we use SNDCTL_DSP_HALT, the next write() or read() will
29878 fail. Instead what we need to do is just not write or read to and from the device when the
29879 device is not running.
29880 
29881 As a result, both the start and stop functions for OSS are just empty stubs. The starting and
29882 stopping logic is handled by ma_device_write__oss() and ma_device_read__oss(). These will check
29883 the device state, and if the device is stopped they will simply not do any kind of processing.
29884 
29885 The downside to this technique is that I've noticed a fairly lengthy delay in stopping the
29886 device, up to a second. This is on a virtual machine, and as such might just be due to the
29887 virtual drivers, but I'm not fully sure. I am not sure how to work around this problem so for
29888 the moment that's just how it's going to have to be.
29889 
29890 When starting the device, OSS will automatically start it when write() or read() is called.
29891 */
29892 static ma_result ma_device_start__oss(ma_device* pDevice)
29893 {
29894  MA_ASSERT(pDevice != NULL);
29895 
29896  /* The device is automatically started with reading and writing. */
29897  (void)pDevice;
29898 
29899  return MA_SUCCESS;
29900 }
29901 
29902 static ma_result ma_device_stop__oss(ma_device* pDevice)
29903 {
29904  MA_ASSERT(pDevice != NULL);
29905 
29906  /* See note above on why this is empty. */
29907  (void)pDevice;
29908 
29909  return MA_SUCCESS;
29910 }
29911 
29912 static ma_result ma_device_write__oss(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
29913 {
29914  int resultOSS;
29915  ma_uint32 deviceState;
29916 
29917  if (pFramesWritten != NULL) {
29918  *pFramesWritten = 0;
29919  }
29920 
29921  /* Don't do any processing if the device is stopped. */
29922  deviceState = ma_device_get_state(pDevice);
29923  if (deviceState != MA_STATE_STARTED && deviceState != MA_STATE_STARTING) {
29924  return MA_SUCCESS;
29925  }
29926 
29927  resultOSS = write(pDevice->oss.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
29928  if (resultOSS < 0) {
29929  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));
29930  }
29931 
29932  if (pFramesWritten != NULL) {
29933  *pFramesWritten = (ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
29934  }
29935 
29936  return MA_SUCCESS;
29937 }
29938 
29939 static ma_result ma_device_read__oss(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
29940 {
29941  int resultOSS;
29942  ma_uint32 deviceState;
29943 
29944  if (pFramesRead != NULL) {
29945  *pFramesRead = 0;
29946  }
29947 
29948  /* Don't do any processing if the device is stopped. */
29949  deviceState = ma_device_get_state(pDevice);
29950  if (deviceState != MA_STATE_STARTED && deviceState != MA_STATE_STARTING) {
29951  return MA_SUCCESS;
29952  }
29953 
29954  resultOSS = read(pDevice->oss.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
29955  if (resultOSS < 0) {
29956  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));
29957  }
29958 
29959  if (pFramesRead != NULL) {
29960  *pFramesRead = (ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
29961  }
29962 
29963  return MA_SUCCESS;
29964 }
29965 
29966 static ma_result ma_context_uninit__oss(ma_context* pContext)
29967 {
29968  MA_ASSERT(pContext != NULL);
29969  MA_ASSERT(pContext->backend == ma_backend_oss);
29970 
29971  (void)pContext;
29972  return MA_SUCCESS;
29973 }
29974 
29975 static ma_result ma_context_init__oss(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
29976 {
29977  int fd;
29978  int ossVersion;
29979  int result;
29980 
29981  MA_ASSERT(pContext != NULL);
29982 
29983  (void)pConfig;
29984 
29985  /* Try opening a temporary device first so we can get version information. This is closed at the end. */
29986  fd = ma_open_temp_device__oss();
29987  if (fd == -1) {
29988  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. */
29989  }
29990 
29991  /* Grab the OSS version. */
29992  ossVersion = 0;
29993  result = ioctl(fd, OSS_GETVERSION, &ossVersion);
29994  if (result == -1) {
29995  close(fd);
29996  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve OSS version.", MA_NO_BACKEND);
29997  }
29998 
29999  /* The file handle to temp device is no longer needed. Close ASAP. */
30000  close(fd);
30001 
30002  pContext->oss.versionMajor = ((ossVersion & 0xFF0000) >> 16);
30003  pContext->oss.versionMinor = ((ossVersion & 0x00FF00) >> 8);
30004 
30005  pCallbacks->onContextInit = ma_context_init__oss;
30006  pCallbacks->onContextUninit = ma_context_uninit__oss;
30007  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__oss;
30008  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__oss;
30009  pCallbacks->onDeviceInit = ma_device_init__oss;
30010  pCallbacks->onDeviceUninit = ma_device_uninit__oss;
30011  pCallbacks->onDeviceStart = ma_device_start__oss;
30012  pCallbacks->onDeviceStop = ma_device_stop__oss;
30013  pCallbacks->onDeviceRead = ma_device_read__oss;
30014  pCallbacks->onDeviceWrite = ma_device_write__oss;
30015  pCallbacks->onDeviceDataLoop = NULL;
30016 
30017  return MA_SUCCESS;
30018 }
30019 #endif /* OSS */
30020 
30021 
30022 /******************************************************************************
30023 
30024 AAudio Backend
30025 
30026 ******************************************************************************/
30027 #ifdef MA_HAS_AAUDIO
30028 
30029 /*#include <AAudio/AAudio.h>*/
30030 
30031 typedef int32_t ma_aaudio_result_t;
30032 typedef int32_t ma_aaudio_direction_t;
30033 typedef int32_t ma_aaudio_sharing_mode_t;
30034 typedef int32_t ma_aaudio_format_t;
30035 typedef int32_t ma_aaudio_stream_state_t;
30036 typedef int32_t ma_aaudio_performance_mode_t;
30037 typedef int32_t ma_aaudio_usage_t;
30038 typedef int32_t ma_aaudio_content_type_t;
30039 typedef int32_t ma_aaudio_input_preset_t;
30040 typedef int32_t ma_aaudio_data_callback_result_t;
30041 typedef struct ma_AAudioStreamBuilder_t* ma_AAudioStreamBuilder;
30042 typedef struct ma_AAudioStream_t* ma_AAudioStream;
30043 
30044 #define MA_AAUDIO_UNSPECIFIED 0
30045 
30046 /* Result codes. miniaudio only cares about the success code. */
30047 #define MA_AAUDIO_OK 0
30048 
30049 /* Directions. */
30050 #define MA_AAUDIO_DIRECTION_OUTPUT 0
30051 #define MA_AAUDIO_DIRECTION_INPUT 1
30052 
30053 /* Sharing modes. */
30054 #define MA_AAUDIO_SHARING_MODE_EXCLUSIVE 0
30055 #define MA_AAUDIO_SHARING_MODE_SHARED 1
30056 
30057 /* Formats. */
30058 #define MA_AAUDIO_FORMAT_PCM_I16 1
30059 #define MA_AAUDIO_FORMAT_PCM_FLOAT 2
30060 
30061 /* Stream states. */
30062 #define MA_AAUDIO_STREAM_STATE_UNINITIALIZED 0
30063 #define MA_AAUDIO_STREAM_STATE_UNKNOWN 1
30064 #define MA_AAUDIO_STREAM_STATE_OPEN 2
30065 #define MA_AAUDIO_STREAM_STATE_STARTING 3
30066 #define MA_AAUDIO_STREAM_STATE_STARTED 4
30067 #define MA_AAUDIO_STREAM_STATE_PAUSING 5
30068 #define MA_AAUDIO_STREAM_STATE_PAUSED 6
30069 #define MA_AAUDIO_STREAM_STATE_FLUSHING 7
30070 #define MA_AAUDIO_STREAM_STATE_FLUSHED 8
30071 #define MA_AAUDIO_STREAM_STATE_STOPPING 9
30072 #define MA_AAUDIO_STREAM_STATE_STOPPED 10
30073 #define MA_AAUDIO_STREAM_STATE_CLOSING 11
30074 #define MA_AAUDIO_STREAM_STATE_CLOSED 12
30075 #define MA_AAUDIO_STREAM_STATE_DISCONNECTED 13
30076 
30077 /* Performance modes. */
30078 #define MA_AAUDIO_PERFORMANCE_MODE_NONE 10
30079 #define MA_AAUDIO_PERFORMANCE_MODE_POWER_SAVING 11
30080 #define MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY 12
30081 
30082 /* Usage types. */
30083 #define MA_AAUDIO_USAGE_MEDIA 1
30084 #define MA_AAUDIO_USAGE_VOICE_COMMUNICATION 2
30085 #define MA_AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING 3
30086 #define MA_AAUDIO_USAGE_ALARM 4
30087 #define MA_AAUDIO_USAGE_NOTIFICATION 5
30088 #define MA_AAUDIO_USAGE_NOTIFICATION_RINGTONE 6
30089 #define MA_AAUDIO_USAGE_NOTIFICATION_EVENT 10
30090 #define MA_AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY 11
30091 #define MA_AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE 12
30092 #define MA_AAUDIO_USAGE_ASSISTANCE_SONIFICATION 13
30093 #define MA_AAUDIO_USAGE_GAME 14
30094 #define MA_AAUDIO_USAGE_ASSISTANT 16
30095 #define MA_AAUDIO_SYSTEM_USAGE_EMERGENCY 1000
30096 #define MA_AAUDIO_SYSTEM_USAGE_SAFETY 1001
30097 #define MA_AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS 1002
30098 #define MA_AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT 1003
30099 
30100 /* Content types. */
30101 #define MA_AAUDIO_CONTENT_TYPE_SPEECH 1
30102 #define MA_AAUDIO_CONTENT_TYPE_MUSIC 2
30103 #define MA_AAUDIO_CONTENT_TYPE_MOVIE 3
30104 #define MA_AAUDIO_CONTENT_TYPE_SONIFICATION 4
30105 
30106 /* Input presets. */
30107 #define MA_AAUDIO_INPUT_PRESET_GENERIC 1
30108 #define MA_AAUDIO_INPUT_PRESET_CAMCORDER 5
30109 #define MA_AAUDIO_INPUT_PRESET_VOICE_RECOGNITION 6
30110 #define MA_AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION 7
30111 #define MA_AAUDIO_INPUT_PRESET_UNPROCESSED 9
30112 #define MA_AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE 10
30113 
30114 /* Callback results. */
30115 #define MA_AAUDIO_CALLBACK_RESULT_CONTINUE 0
30116 #define MA_AAUDIO_CALLBACK_RESULT_STOP 1
30117 
30118 
30119 typedef ma_aaudio_data_callback_result_t (* ma_AAudioStream_dataCallback) (ma_AAudioStream* pStream, void* pUserData, void* pAudioData, int32_t numFrames);
30120 typedef void (* ma_AAudioStream_errorCallback)(ma_AAudioStream *pStream, void *pUserData, ma_aaudio_result_t error);
30121 
30122 typedef ma_aaudio_result_t (* MA_PFN_AAudio_createStreamBuilder) (ma_AAudioStreamBuilder** ppBuilder);
30123 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_delete) (ma_AAudioStreamBuilder* pBuilder);
30124 typedef void (* MA_PFN_AAudioStreamBuilder_setDeviceId) (ma_AAudioStreamBuilder* pBuilder, int32_t deviceId);
30125 typedef void (* MA_PFN_AAudioStreamBuilder_setDirection) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_direction_t direction);
30126 typedef void (* MA_PFN_AAudioStreamBuilder_setSharingMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_sharing_mode_t sharingMode);
30127 typedef void (* MA_PFN_AAudioStreamBuilder_setFormat) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_format_t format);
30128 typedef void (* MA_PFN_AAudioStreamBuilder_setChannelCount) (ma_AAudioStreamBuilder* pBuilder, int32_t channelCount);
30129 typedef void (* MA_PFN_AAudioStreamBuilder_setSampleRate) (ma_AAudioStreamBuilder* pBuilder, int32_t sampleRate);
30130 typedef void (* MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)(ma_AAudioStreamBuilder* pBuilder, int32_t numFrames);
30131 typedef void (* MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback) (ma_AAudioStreamBuilder* pBuilder, int32_t numFrames);
30132 typedef void (* MA_PFN_AAudioStreamBuilder_setDataCallback) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream_dataCallback callback, void* pUserData);
30133 typedef void (* MA_PFN_AAudioStreamBuilder_setErrorCallback) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream_errorCallback callback, void* pUserData);
30134 typedef void (* MA_PFN_AAudioStreamBuilder_setPerformanceMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_performance_mode_t mode);
30135 typedef void (* MA_PFN_AAudioStreamBuilder_setUsage) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_usage_t contentType);
30136 typedef void (* MA_PFN_AAudioStreamBuilder_setContentType) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_content_type_t contentType);
30137 typedef void (* MA_PFN_AAudioStreamBuilder_setInputPreset) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_input_preset_t inputPreset);
30138 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_openStream) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream** ppStream);
30139 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_close) (ma_AAudioStream* pStream);
30140 typedef ma_aaudio_stream_state_t (* MA_PFN_AAudioStream_getState) (ma_AAudioStream* pStream);
30141 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);
30142 typedef ma_aaudio_format_t (* MA_PFN_AAudioStream_getFormat) (ma_AAudioStream* pStream);
30143 typedef int32_t (* MA_PFN_AAudioStream_getChannelCount) (ma_AAudioStream* pStream);
30144 typedef int32_t (* MA_PFN_AAudioStream_getSampleRate) (ma_AAudioStream* pStream);
30145 typedef int32_t (* MA_PFN_AAudioStream_getBufferCapacityInFrames) (ma_AAudioStream* pStream);
30146 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerDataCallback) (ma_AAudioStream* pStream);
30147 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerBurst) (ma_AAudioStream* pStream);
30148 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStart) (ma_AAudioStream* pStream);
30149 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStop) (ma_AAudioStream* pStream);
30150 
30151 static ma_result ma_result_from_aaudio(ma_aaudio_result_t resultAA)
30152 {
30153  switch (resultAA)
30154  {
30155  case MA_AAUDIO_OK: return MA_SUCCESS;
30156  default: break;
30157  }
30158 
30159  return MA_ERROR;
30160 }
30161 
30162 static ma_aaudio_usage_t ma_to_usage__aaudio(ma_aaudio_usage usage)
30163 {
30164  switch (usage) {
30165  case ma_aaudio_usage_announcement: return MA_AAUDIO_USAGE_MEDIA;
30166  case ma_aaudio_usage_emergency: return MA_AAUDIO_USAGE_VOICE_COMMUNICATION;
30167  case ma_aaudio_usage_safety: return MA_AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
30168  case ma_aaudio_usage_vehicle_status: return MA_AAUDIO_USAGE_ALARM;
30169  case ma_aaudio_usage_alarm: return MA_AAUDIO_USAGE_NOTIFICATION;
30170  case ma_aaudio_usage_assistance_accessibility: return MA_AAUDIO_USAGE_NOTIFICATION_RINGTONE;
30171  case ma_aaudio_usage_assistance_navigation_guidance: return MA_AAUDIO_USAGE_NOTIFICATION_EVENT;
30172  case ma_aaudio_usage_assistance_sonification: return MA_AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
30173  case ma_aaudio_usage_assitant: return MA_AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
30174  case ma_aaudio_usage_game: return MA_AAUDIO_USAGE_ASSISTANCE_SONIFICATION;
30175  case ma_aaudio_usage_media: return MA_AAUDIO_USAGE_GAME;
30176  case ma_aaudio_usage_notification: return MA_AAUDIO_USAGE_ASSISTANT;
30177  case ma_aaudio_usage_notification_event: return MA_AAUDIO_SYSTEM_USAGE_EMERGENCY;
30178  case ma_aaudio_usage_notification_ringtone: return MA_AAUDIO_SYSTEM_USAGE_SAFETY;
30179  case ma_aaudio_usage_voice_communication: return MA_AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS;
30180  case ma_aaudio_usage_voice_communication_signalling: return MA_AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT;
30181  default: break;
30182  }
30183 
30184  return MA_AAUDIO_USAGE_MEDIA;
30185 }
30186 
30187 static ma_aaudio_content_type_t ma_to_content_type__aaudio(ma_aaudio_content_type contentType)
30188 {
30189  switch (contentType) {
30190  case ma_aaudio_content_type_movie: return MA_AAUDIO_CONTENT_TYPE_MOVIE;
30191  case ma_aaudio_content_type_music: return MA_AAUDIO_CONTENT_TYPE_MUSIC;
30192  case ma_aaudio_content_type_sonification: return MA_AAUDIO_CONTENT_TYPE_SONIFICATION;
30193  case ma_aaudio_content_type_speech: return MA_AAUDIO_CONTENT_TYPE_SPEECH;
30194  default: break;
30195  }
30196 
30197  return MA_AAUDIO_CONTENT_TYPE_SPEECH;
30198 }
30199 
30200 static ma_aaudio_input_preset_t ma_to_input_preset__aaudio(ma_aaudio_input_preset inputPreset)
30201 {
30202  switch (inputPreset) {
30203  case ma_aaudio_input_preset_generic: return MA_AAUDIO_INPUT_PRESET_GENERIC;
30204  case ma_aaudio_input_preset_camcorder: return MA_AAUDIO_INPUT_PRESET_CAMCORDER;
30205  case ma_aaudio_input_preset_unprocessed: return MA_AAUDIO_INPUT_PRESET_UNPROCESSED;
30206  case ma_aaudio_input_preset_voice_recognition: return MA_AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
30207  case ma_aaudio_input_preset_voice_communication: return MA_AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION;
30208  case ma_aaudio_input_preset_voice_performance: return MA_AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE;
30209  default: break;
30210  }
30211 
30212  return MA_AAUDIO_INPUT_PRESET_GENERIC;
30213 }
30214 
30215 static void ma_stream_error_callback__aaudio(ma_AAudioStream* pStream, void* pUserData, ma_aaudio_result_t error)
30216 {
30217  ma_device* pDevice = (ma_device*)pUserData;
30218  MA_ASSERT(pDevice != NULL);
30219 
30220  (void)error;
30221 
30222  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));
30223 
30224  /*
30225  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
30226  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.
30227  */
30228  if (((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream) == MA_AAUDIO_STREAM_STATE_DISCONNECTED) {
30229  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[AAudio] Device Disconnected.\n");
30230  }
30231 }
30232 
30233 static ma_aaudio_data_callback_result_t ma_stream_data_callback_capture__aaudio(ma_AAudioStream* pStream, void* pUserData, void* pAudioData, int32_t frameCount)
30234 {
30235  ma_device* pDevice = (ma_device*)pUserData;
30236  MA_ASSERT(pDevice != NULL);
30237 
30238  ma_device_handle_backend_data_callback(pDevice, NULL, pAudioData, frameCount);
30239 
30240  (void)pStream;
30241  return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
30242 }
30243 
30244 static ma_aaudio_data_callback_result_t ma_stream_data_callback_playback__aaudio(ma_AAudioStream* pStream, void* pUserData, void* pAudioData, int32_t frameCount)
30245 {
30246  ma_device* pDevice = (ma_device*)pUserData;
30247  MA_ASSERT(pDevice != NULL);
30248 
30249  ma_device_handle_backend_data_callback(pDevice, pAudioData, NULL, frameCount);
30250 
30251  (void)pStream;
30252  return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
30253 }
30254 
30255 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)
30256 {
30257  ma_AAudioStreamBuilder* pBuilder;
30258  ma_aaudio_result_t resultAA;
30259  ma_uint32 bufferCapacityInFrames;
30260 
30261  /* Safety. */
30262  *ppBuilder = NULL;
30263 
30264  resultAA = ((MA_PFN_AAudio_createStreamBuilder)pContext->aaudio.AAudio_createStreamBuilder)(&pBuilder);
30265  if (resultAA != MA_AAUDIO_OK) {
30266  return ma_result_from_aaudio(resultAA);
30267  }
30268 
30269  if (pDeviceID != NULL) {
30270  ((MA_PFN_AAudioStreamBuilder_setDeviceId)pContext->aaudio.AAudioStreamBuilder_setDeviceId)(pBuilder, pDeviceID->aaudio);
30271  }
30272 
30273  ((MA_PFN_AAudioStreamBuilder_setDirection)pContext->aaudio.AAudioStreamBuilder_setDirection)(pBuilder, (deviceType == ma_device_type_playback) ? MA_AAUDIO_DIRECTION_OUTPUT : MA_AAUDIO_DIRECTION_INPUT);
30274  ((MA_PFN_AAudioStreamBuilder_setSharingMode)pContext->aaudio.AAudioStreamBuilder_setSharingMode)(pBuilder, (shareMode == ma_share_mode_shared) ? MA_AAUDIO_SHARING_MODE_SHARED : MA_AAUDIO_SHARING_MODE_EXCLUSIVE);
30275 
30276 
30277  /* If we have a device descriptor make sure we configure the stream builder to take our requested parameters. */
30278  if (pDescriptor != NULL) {
30279  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. */
30280 
30281  if (pDescriptor->sampleRate != 0) {
30282  ((MA_PFN_AAudioStreamBuilder_setSampleRate)pContext->aaudio.AAudioStreamBuilder_setSampleRate)(pBuilder, pDescriptor->sampleRate);
30283  }
30284 
30285  if (deviceType == ma_device_type_capture) {
30286  if (pDescriptor->channels != 0) {
30287  ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
30288  }
30289  if (pDescriptor->format != ma_format_unknown) {
30290  ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
30291  }
30292  } else {
30293  if (pDescriptor->channels != 0) {
30294  ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels);
30295  }
30296  if (pDescriptor->format != ma_format_unknown) {
30297  ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
30298  }
30299  }
30300 
30301  /*
30302  AAudio is annoying when it comes to it's buffer calculation stuff because it doesn't let you
30303  retrieve the actual sample rate until after you've opened the stream. But you need to configure
30304  the buffer capacity before you open the stream... :/
30305 
30306  To solve, we're just going to assume MA_DEFAULT_SAMPLE_RATE (48000) and move on.
30307  */
30308  bufferCapacityInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, pDescriptor->sampleRate, pConfig->performanceProfile) * pDescriptor->periodCount;
30309 
30310  ((MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames)(pBuilder, bufferCapacityInFrames);
30311  ((MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback)pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback)(pBuilder, bufferCapacityInFrames / pDescriptor->periodCount);
30312 
30313  if (deviceType == ma_device_type_capture) {
30314  if (pConfig->aaudio.inputPreset != ma_aaudio_input_preset_default && pContext->aaudio.AAudioStreamBuilder_setInputPreset != NULL) {
30315  ((MA_PFN_AAudioStreamBuilder_setInputPreset)pContext->aaudio.AAudioStreamBuilder_setInputPreset)(pBuilder, ma_to_input_preset__aaudio(pConfig->aaudio.inputPreset));
30316  }
30317 
30318  ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_capture__aaudio, (void*)pDevice);
30319  } else {
30320  if (pConfig->aaudio.usage != ma_aaudio_usage_default && pContext->aaudio.AAudioStreamBuilder_setUsage != NULL) {
30321  ((MA_PFN_AAudioStreamBuilder_setUsage)pContext->aaudio.AAudioStreamBuilder_setUsage)(pBuilder, ma_to_usage__aaudio(pConfig->aaudio.usage));
30322  }
30323 
30324  if (pConfig->aaudio.contentType != ma_aaudio_content_type_default && pContext->aaudio.AAudioStreamBuilder_setContentType != NULL) {
30325  ((MA_PFN_AAudioStreamBuilder_setContentType)pContext->aaudio.AAudioStreamBuilder_setContentType)(pBuilder, ma_to_content_type__aaudio(pConfig->aaudio.contentType));
30326  }
30327 
30328  ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_playback__aaudio, (void*)pDevice);
30329  }
30330 
30331  /* 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. */
30332  ((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);
30333 
30334  /* We need to set an error callback to detect device changes. */
30335  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. */
30336  ((MA_PFN_AAudioStreamBuilder_setErrorCallback)pContext->aaudio.AAudioStreamBuilder_setErrorCallback)(pBuilder, ma_stream_error_callback__aaudio, (void*)pDevice);
30337  }
30338  }
30339 
30340  *ppBuilder = pBuilder;
30341 
30342  return MA_SUCCESS;
30343 }
30344 
30345 static ma_result ma_open_stream_and_close_builder__aaudio(ma_context* pContext, ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream** ppStream)
30346 {
30347  ma_result result;
30348 
30349  result = ma_result_from_aaudio(((MA_PFN_AAudioStreamBuilder_openStream)pContext->aaudio.AAudioStreamBuilder_openStream)(pBuilder, ppStream));
30350  ((MA_PFN_AAudioStreamBuilder_delete)pContext->aaudio.AAudioStreamBuilder_delete)(pBuilder);
30351 
30352  return result;
30353 }
30354 
30355 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)
30356 {
30357  ma_result result;
30358  ma_AAudioStreamBuilder* pBuilder;
30359 
30360  *ppStream = NULL;
30361 
30362  result = ma_create_and_configure_AAudioStreamBuilder__aaudio(pContext, pDeviceID, deviceType, shareMode, NULL, NULL, NULL, &pBuilder);
30363  if (result != MA_SUCCESS) {
30364  return result;
30365  }
30366 
30367  return ma_open_stream_and_close_builder__aaudio(pContext, pBuilder, ppStream);
30368 }
30369 
30370 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)
30371 {
30372  ma_result result;
30373  ma_AAudioStreamBuilder* pBuilder;
30374 
30375  MA_ASSERT(pConfig != NULL);
30376  MA_ASSERT(pConfig->deviceType != ma_device_type_duplex); /* This function should not be called for a full-duplex device type. */
30377 
30378  *ppStream = NULL;
30379 
30380  result = ma_create_and_configure_AAudioStreamBuilder__aaudio(pDevice->pContext, pDescriptor->pDeviceID, deviceType, pDescriptor->shareMode, pDescriptor, pConfig, pDevice, &pBuilder);
30381  if (result != MA_SUCCESS) {
30382  return result;
30383  }
30384 
30385  return ma_open_stream_and_close_builder__aaudio(pDevice->pContext, pBuilder, ppStream);
30386 }
30387 
30388 static ma_result ma_close_stream__aaudio(ma_context* pContext, ma_AAudioStream* pStream)
30389 {
30390  return ma_result_from_aaudio(((MA_PFN_AAudioStream_close)pContext->aaudio.AAudioStream_close)(pStream));
30391 }
30392 
30393 static ma_bool32 ma_has_default_device__aaudio(ma_context* pContext, ma_device_type deviceType)
30394 {
30395  /* The only way to know this is to try creating a stream. */
30396  ma_AAudioStream* pStream;
30397  ma_result result = ma_open_stream_basic__aaudio(pContext, NULL, deviceType, ma_share_mode_shared, &pStream);
30398  if (result != MA_SUCCESS) {
30399  return MA_FALSE;
30400  }
30401 
30402  ma_close_stream__aaudio(pContext, pStream);
30403  return MA_TRUE;
30404 }
30405 
30406 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)
30407 {
30408  ma_aaudio_stream_state_t actualNewState;
30409  ma_aaudio_result_t resultAA = ((MA_PFN_AAudioStream_waitForStateChange)pContext->aaudio.AAudioStream_waitForStateChange)(pStream, oldState, &actualNewState, 5000000000); /* 5 second timeout. */
30410  if (resultAA != MA_AAUDIO_OK) {
30411  return ma_result_from_aaudio(resultAA);
30412  }
30413 
30414  if (newState != actualNewState) {
30415  return MA_ERROR; /* Failed to transition into the expected state. */
30416  }
30417 
30418  return MA_SUCCESS;
30419 }
30420 
30421 
30422 static ma_result ma_context_enumerate_devices__aaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
30423 {
30424  ma_bool32 cbResult = MA_TRUE;
30425 
30426  MA_ASSERT(pContext != NULL);
30427  MA_ASSERT(callback != NULL);
30428 
30429  /* 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. */
30430 
30431  /* Playback. */
30432  if (cbResult) {
30433  ma_device_info deviceInfo;
30434  MA_ZERO_OBJECT(&deviceInfo);
30435  deviceInfo.id.aaudio = MA_AAUDIO_UNSPECIFIED;
30436  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
30437 
30438  if (ma_has_default_device__aaudio(pContext, ma_device_type_playback)) {
30439  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
30440  }
30441  }
30442 
30443  /* Capture. */
30444  if (cbResult) {
30445  ma_device_info deviceInfo;
30446  MA_ZERO_OBJECT(&deviceInfo);
30447  deviceInfo.id.aaudio = MA_AAUDIO_UNSPECIFIED;
30448  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
30449 
30450  if (ma_has_default_device__aaudio(pContext, ma_device_type_capture)) {
30451  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
30452  }
30453  }
30454 
30455  return MA_SUCCESS;
30456 }
30457 
30458 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)
30459 {
30460  MA_ASSERT(pContext != NULL);
30461  MA_ASSERT(pStream != NULL);
30462  MA_ASSERT(pDeviceInfo != NULL);
30463 
30464  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
30465  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)(pStream);
30466  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)(pStream);
30467  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = flags;
30468  pDeviceInfo->nativeDataFormatCount += 1;
30469 }
30470 
30471 static void ma_context_add_native_data_format_from_AAudioStream__aaudio(ma_context* pContext, ma_AAudioStream* pStream, ma_uint32 flags, ma_device_info* pDeviceInfo)
30472 {
30473  /* AAudio supports s16 and f32. */
30474  ma_context_add_native_data_format_from_AAudioStream_ex__aaudio(pContext, pStream, ma_format_f32, flags, pDeviceInfo);
30475  ma_context_add_native_data_format_from_AAudioStream_ex__aaudio(pContext, pStream, ma_format_s16, flags, pDeviceInfo);
30476 }
30477 
30478 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)
30479 {
30480  ma_AAudioStream* pStream;
30481  ma_result result;
30482 
30483  MA_ASSERT(pContext != NULL);
30484 
30485  /* ID */
30486  if (pDeviceID != NULL) {
30487  pDeviceInfo->id.aaudio = pDeviceID->aaudio;
30488  } else {
30489  pDeviceInfo->id.aaudio = MA_AAUDIO_UNSPECIFIED;
30490  }
30491 
30492  /* Name */
30493  if (deviceType == ma_device_type_playback) {
30494  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
30495  } else {
30496  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
30497  }
30498 
30499 
30500  pDeviceInfo->nativeDataFormatCount = 0;
30501 
30502  /* We'll need to open the device to get accurate sample rate and channel count information. */
30503  result = ma_open_stream_basic__aaudio(pContext, pDeviceID, deviceType, ma_share_mode_shared, &pStream);
30504  if (result != MA_SUCCESS) {
30505  return result;
30506  }
30507 
30508  ma_context_add_native_data_format_from_AAudioStream__aaudio(pContext, pStream, 0, pDeviceInfo);
30509 
30510  ma_close_stream__aaudio(pContext, pStream);
30511  pStream = NULL;
30512 
30513  return MA_SUCCESS;
30514 }
30515 
30516 
30517 static ma_result ma_device_uninit__aaudio(ma_device* pDevice)
30518 {
30519  MA_ASSERT(pDevice != NULL);
30520 
30521  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
30522  ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
30523  pDevice->aaudio.pStreamCapture = NULL;
30524  }
30525 
30526  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
30527  ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
30528  pDevice->aaudio.pStreamPlayback = NULL;
30529  }
30530 
30531  return MA_SUCCESS;
30532 }
30533 
30534 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)
30535 {
30536  ma_result result;
30537  int32_t bufferCapacityInFrames;
30538  int32_t framesPerDataCallback;
30539  ma_AAudioStream* pStream;
30540 
30541  MA_ASSERT(pDevice != NULL);
30542  MA_ASSERT(pConfig != NULL);
30543  MA_ASSERT(pDescriptor != NULL);
30544 
30545  *ppStream = NULL; /* Safety. */
30546 
30547  /* First step is to open the stream. From there we'll be able to extract the internal configuration. */
30548  result = ma_open_stream__aaudio(pDevice, pConfig, deviceType, pDescriptor, &pStream);
30549  if (result != MA_SUCCESS) {
30550  return result; /* Failed to open the AAudio stream. */
30551  }
30552 
30553  /* Now extract the internal configuration. */
30554  pDescriptor->format = (((MA_PFN_AAudioStream_getFormat)pDevice->pContext->aaudio.AAudioStream_getFormat)(pStream) == MA_AAUDIO_FORMAT_PCM_I16) ? ma_format_s16 : ma_format_f32;
30555  pDescriptor->channels = ((MA_PFN_AAudioStream_getChannelCount)pDevice->pContext->aaudio.AAudioStream_getChannelCount)(pStream);
30556  pDescriptor->sampleRate = ((MA_PFN_AAudioStream_getSampleRate)pDevice->pContext->aaudio.AAudioStream_getSampleRate)(pStream);
30557 
30558  /* For the channel map we need to be sure we don't overflow any buffers. */
30559  if (pDescriptor->channels <= MA_MAX_CHANNELS) {
30560  ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptor->channels, pDescriptor->channelMap); /* <-- Cannot find info on channel order, so assuming a default. */
30561  } else {
30562  ma_channel_map_init_blank(MA_MAX_CHANNELS, pDescriptor->channelMap); /* Too many channels. Use a blank channel map. */
30563  }
30564 
30565  bufferCapacityInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pDevice->pContext->aaudio.AAudioStream_getBufferCapacityInFrames)(pStream);
30566  framesPerDataCallback = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pDevice->pContext->aaudio.AAudioStream_getFramesPerDataCallback)(pStream);
30567 
30568  if (framesPerDataCallback > 0) {
30569  pDescriptor->periodSizeInFrames = framesPerDataCallback;
30570  pDescriptor->periodCount = bufferCapacityInFrames / framesPerDataCallback;
30571  } else {
30572  pDescriptor->periodSizeInFrames = bufferCapacityInFrames;
30573  pDescriptor->periodCount = 1;
30574  }
30575 
30576  *ppStream = pStream;
30577 
30578  return MA_SUCCESS;
30579 }
30580 
30581 static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
30582 {
30583  ma_result result;
30584 
30585  MA_ASSERT(pDevice != NULL);
30586 
30587  if (pConfig->deviceType == ma_device_type_loopback) {
30589  }
30590 
30591  /* No exclusive mode with AAudio. */
30592  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
30593  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
30595  }
30596 
30597  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
30598  result = ma_device_init_by_type__aaudio(pDevice, pConfig, ma_device_type_capture, pDescriptorCapture, (ma_AAudioStream**)&pDevice->aaudio.pStreamCapture);
30599  if (result != MA_SUCCESS) {
30600  return result;
30601  }
30602  }
30603 
30604  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
30605  result = ma_device_init_by_type__aaudio(pDevice, pConfig, ma_device_type_playback, pDescriptorPlayback, (ma_AAudioStream**)&pDevice->aaudio.pStreamPlayback);
30606  if (result != MA_SUCCESS) {
30607  return result;
30608  }
30609  }
30610 
30611  return MA_SUCCESS;
30612 }
30613 
30614 static ma_result ma_device_start_stream__aaudio(ma_device* pDevice, ma_AAudioStream* pStream)
30615 {
30616  ma_aaudio_result_t resultAA;
30617  ma_aaudio_stream_state_t currentState;
30618 
30619  MA_ASSERT(pDevice != NULL);
30620 
30621  resultAA = ((MA_PFN_AAudioStream_requestStart)pDevice->pContext->aaudio.AAudioStream_requestStart)(pStream);
30622  if (resultAA != MA_AAUDIO_OK) {
30623  return ma_result_from_aaudio(resultAA);
30624  }
30625 
30626  /* Do we actually need to wait for the device to transition into it's started state? */
30627 
30628  /* 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. */
30629  currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
30630  if (currentState != MA_AAUDIO_STREAM_STATE_STARTED) {
30631  ma_result result;
30632 
30633  if (currentState != MA_AAUDIO_STREAM_STATE_STARTING) {
30634  return MA_ERROR; /* Expecting the stream to be a starting or started state. */
30635  }
30636 
30637  result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STARTED);
30638  if (result != MA_SUCCESS) {
30639  return result;
30640  }
30641  }
30642 
30643  return MA_SUCCESS;
30644 }
30645 
30646 static ma_result ma_device_stop_stream__aaudio(ma_device* pDevice, ma_AAudioStream* pStream)
30647 {
30648  ma_aaudio_result_t resultAA;
30649  ma_aaudio_stream_state_t currentState;
30650 
30651  MA_ASSERT(pDevice != NULL);
30652 
30653  /*
30654  From the AAudio documentation:
30655 
30656  The stream will stop after all of the data currently buffered has been played.
30657 
30658  This maps with miniaudio's requirement that device's be drained which means we don't need to implement any draining logic.
30659  */
30660 
30661  resultAA = ((MA_PFN_AAudioStream_requestStop)pDevice->pContext->aaudio.AAudioStream_requestStop)(pStream);
30662  if (resultAA != MA_AAUDIO_OK) {
30663  return ma_result_from_aaudio(resultAA);
30664  }
30665 
30666  /* 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. */
30667  currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
30668  if (currentState != MA_AAUDIO_STREAM_STATE_STOPPED) {
30669  ma_result result;
30670 
30671  if (currentState != MA_AAUDIO_STREAM_STATE_STOPPING) {
30672  return MA_ERROR; /* Expecting the stream to be a stopping or stopped state. */
30673  }
30674 
30675  result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STOPPED);
30676  if (result != MA_SUCCESS) {
30677  return result;
30678  }
30679  }
30680 
30681  return MA_SUCCESS;
30682 }
30683 
30684 static ma_result ma_device_start__aaudio(ma_device* pDevice)
30685 {
30686  MA_ASSERT(pDevice != NULL);
30687 
30688  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
30689  ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
30690  if (result != MA_SUCCESS) {
30691  return result;
30692  }
30693  }
30694 
30695  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
30696  ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
30697  if (result != MA_SUCCESS) {
30698  if (pDevice->type == ma_device_type_duplex) {
30699  ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
30700  }
30701  return result;
30702  }
30703  }
30704 
30705  return MA_SUCCESS;
30706 }
30707 
30708 static ma_result ma_device_stop__aaudio(ma_device* pDevice)
30709 {
30710  ma_stop_proc onStop;
30711 
30712  MA_ASSERT(pDevice != NULL);
30713 
30714  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
30715  ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
30716  if (result != MA_SUCCESS) {
30717  return result;
30718  }
30719  }
30720 
30721  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
30722  ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
30723  if (result != MA_SUCCESS) {
30724  return result;
30725  }
30726  }
30727 
30728  onStop = pDevice->onStop;
30729  if (onStop) {
30730  onStop(pDevice);
30731  }
30732 
30733  return MA_SUCCESS;
30734 }
30735 
30736 
30737 static ma_result ma_context_uninit__aaudio(ma_context* pContext)
30738 {
30739  MA_ASSERT(pContext != NULL);
30740  MA_ASSERT(pContext->backend == ma_backend_aaudio);
30741 
30742  ma_dlclose(pContext, pContext->aaudio.hAAudio);
30743  pContext->aaudio.hAAudio = NULL;
30744 
30745  return MA_SUCCESS;
30746 }
30747 
30748 static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
30749 {
30750  size_t i;
30751  const char* libNames[] = {
30752  "libaaudio.so"
30753  };
30754 
30755  for (i = 0; i < ma_countof(libNames); ++i) {
30756  pContext->aaudio.hAAudio = ma_dlopen(pContext, libNames[i]);
30757  if (pContext->aaudio.hAAudio != NULL) {
30758  break;
30759  }
30760  }
30761 
30762  if (pContext->aaudio.hAAudio == NULL) {
30764  }
30765 
30766  pContext->aaudio.AAudio_createStreamBuilder = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudio_createStreamBuilder");
30767  pContext->aaudio.AAudioStreamBuilder_delete = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_delete");
30768  pContext->aaudio.AAudioStreamBuilder_setDeviceId = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDeviceId");
30769  pContext->aaudio.AAudioStreamBuilder_setDirection = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDirection");
30770  pContext->aaudio.AAudioStreamBuilder_setSharingMode = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setSharingMode");
30771  pContext->aaudio.AAudioStreamBuilder_setFormat = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setFormat");
30772  pContext->aaudio.AAudioStreamBuilder_setChannelCount = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setChannelCount");
30773  pContext->aaudio.AAudioStreamBuilder_setSampleRate = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setSampleRate");
30774  pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setBufferCapacityInFrames");
30775  pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setFramesPerDataCallback");
30776  pContext->aaudio.AAudioStreamBuilder_setDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDataCallback");
30777  pContext->aaudio.AAudioStreamBuilder_setErrorCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setErrorCallback");
30778  pContext->aaudio.AAudioStreamBuilder_setPerformanceMode = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setPerformanceMode");
30779  pContext->aaudio.AAudioStreamBuilder_setUsage = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setUsage");
30780  pContext->aaudio.AAudioStreamBuilder_setContentType = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setContentType");
30781  pContext->aaudio.AAudioStreamBuilder_setInputPreset = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setInputPreset");
30782  pContext->aaudio.AAudioStreamBuilder_openStream = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_openStream");
30783  pContext->aaudio.AAudioStream_close = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_close");
30784  pContext->aaudio.AAudioStream_getState = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getState");
30785  pContext->aaudio.AAudioStream_waitForStateChange = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_waitForStateChange");
30786  pContext->aaudio.AAudioStream_getFormat = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFormat");
30787  pContext->aaudio.AAudioStream_getChannelCount = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getChannelCount");
30788  pContext->aaudio.AAudioStream_getSampleRate = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getSampleRate");
30789  pContext->aaudio.AAudioStream_getBufferCapacityInFrames = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getBufferCapacityInFrames");
30790  pContext->aaudio.AAudioStream_getFramesPerDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerDataCallback");
30791  pContext->aaudio.AAudioStream_getFramesPerBurst = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerBurst");
30792  pContext->aaudio.AAudioStream_requestStart = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStart");
30793  pContext->aaudio.AAudioStream_requestStop = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStop");
30794 
30795 
30796  pCallbacks->onContextInit = ma_context_init__aaudio;
30797  pCallbacks->onContextUninit = ma_context_uninit__aaudio;
30798  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__aaudio;
30799  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__aaudio;
30800  pCallbacks->onDeviceInit = ma_device_init__aaudio;
30801  pCallbacks->onDeviceUninit = ma_device_uninit__aaudio;
30802  pCallbacks->onDeviceStart = ma_device_start__aaudio;
30803  pCallbacks->onDeviceStop = ma_device_stop__aaudio;
30804  pCallbacks->onDeviceRead = NULL; /* Not used because AAudio is asynchronous. */
30805  pCallbacks->onDeviceWrite = NULL; /* Not used because AAudio is asynchronous. */
30806  pCallbacks->onDeviceDataLoop = NULL; /* Not used because AAudio is asynchronous. */
30807 
30808  (void)pConfig;
30809  return MA_SUCCESS;
30810 }
30811 #endif /* AAudio */
30812 
30813 
30814 /******************************************************************************
30815 
30816 OpenSL|ES Backend
30817 
30818 ******************************************************************************/
30819 #ifdef MA_HAS_OPENSL
30820 #include <SLES/OpenSLES.h>
30821 #ifdef MA_ANDROID
30822 #include <SLES/OpenSLES_Android.h>
30823 #endif
30824 
30825 typedef SLresult (SLAPIENTRY * ma_slCreateEngine_proc)(SLObjectItf* pEngine, SLuint32 numOptions, SLEngineOption* pEngineOptions, SLuint32 numInterfaces, SLInterfaceID* pInterfaceIds, SLboolean* pInterfaceRequired);
30826 
30827 /* OpenSL|ES has one-per-application objects :( */
30828 static SLObjectItf g_maEngineObjectSL = NULL;
30829 static SLEngineItf g_maEngineSL = NULL;
30830 static ma_uint32 g_maOpenSLInitCounter = 0;
30831 static ma_spinlock g_maOpenSLSpinlock = 0; /* For init/uninit. */
30832 
30833 #define MA_OPENSL_OBJ(p) (*((SLObjectItf)(p)))
30834 #define MA_OPENSL_OUTPUTMIX(p) (*((SLOutputMixItf)(p)))
30835 #define MA_OPENSL_PLAY(p) (*((SLPlayItf)(p)))
30836 #define MA_OPENSL_RECORD(p) (*((SLRecordItf)(p)))
30837 
30838 #ifdef MA_ANDROID
30839 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLAndroidSimpleBufferQueueItf)(p)))
30840 #else
30841 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLBufferQueueItf)(p)))
30842 #endif
30843 
30844 static ma_result ma_result_from_OpenSL(SLuint32 result)
30845 {
30846  switch (result)
30847  {
30848  case SL_RESULT_SUCCESS: return MA_SUCCESS;
30849  case SL_RESULT_PRECONDITIONS_VIOLATED: return MA_ERROR;
30850  case SL_RESULT_PARAMETER_INVALID: return MA_INVALID_ARGS;
30851  case SL_RESULT_MEMORY_FAILURE: return MA_OUT_OF_MEMORY;
30852  case SL_RESULT_RESOURCE_ERROR: return MA_INVALID_DATA;
30853  case SL_RESULT_RESOURCE_LOST: return MA_ERROR;
30854  case SL_RESULT_IO_ERROR: return MA_IO_ERROR;
30855  case SL_RESULT_BUFFER_INSUFFICIENT: return MA_NO_SPACE;
30856  case SL_RESULT_CONTENT_CORRUPTED: return MA_INVALID_DATA;
30857  case SL_RESULT_CONTENT_UNSUPPORTED: return MA_FORMAT_NOT_SUPPORTED;
30858  case SL_RESULT_CONTENT_NOT_FOUND: return MA_ERROR;
30859  case SL_RESULT_PERMISSION_DENIED: return MA_ACCESS_DENIED;
30860  case SL_RESULT_FEATURE_UNSUPPORTED: return MA_NOT_IMPLEMENTED;
30861  case SL_RESULT_INTERNAL_ERROR: return MA_ERROR;
30862  case SL_RESULT_UNKNOWN_ERROR: return MA_ERROR;
30863  case SL_RESULT_OPERATION_ABORTED: return MA_ERROR;
30864  case SL_RESULT_CONTROL_LOST: return MA_ERROR;
30865  default: return MA_ERROR;
30866  }
30867 }
30868 
30869 /* Converts an individual OpenSL-style channel identifier (SL_SPEAKER_FRONT_LEFT, etc.) to miniaudio. */
30870 static ma_uint8 ma_channel_id_to_ma__opensl(SLuint32 id)
30871 {
30872  switch (id)
30873  {
30874  case SL_SPEAKER_FRONT_LEFT: return MA_CHANNEL_FRONT_LEFT;
30875  case SL_SPEAKER_FRONT_RIGHT: return MA_CHANNEL_FRONT_RIGHT;
30876  case SL_SPEAKER_FRONT_CENTER: return MA_CHANNEL_FRONT_CENTER;
30877  case SL_SPEAKER_LOW_FREQUENCY: return MA_CHANNEL_LFE;
30878  case SL_SPEAKER_BACK_LEFT: return MA_CHANNEL_BACK_LEFT;
30879  case SL_SPEAKER_BACK_RIGHT: return MA_CHANNEL_BACK_RIGHT;
30880  case SL_SPEAKER_FRONT_LEFT_OF_CENTER: return MA_CHANNEL_FRONT_LEFT_CENTER;
30881  case SL_SPEAKER_FRONT_RIGHT_OF_CENTER: return MA_CHANNEL_FRONT_RIGHT_CENTER;
30882  case SL_SPEAKER_BACK_CENTER: return MA_CHANNEL_BACK_CENTER;
30883  case SL_SPEAKER_SIDE_LEFT: return MA_CHANNEL_SIDE_LEFT;
30884  case SL_SPEAKER_SIDE_RIGHT: return MA_CHANNEL_SIDE_RIGHT;
30885  case SL_SPEAKER_TOP_CENTER: return MA_CHANNEL_TOP_CENTER;
30886  case SL_SPEAKER_TOP_FRONT_LEFT: return MA_CHANNEL_TOP_FRONT_LEFT;
30887  case SL_SPEAKER_TOP_FRONT_CENTER: return MA_CHANNEL_TOP_FRONT_CENTER;
30888  case SL_SPEAKER_TOP_FRONT_RIGHT: return MA_CHANNEL_TOP_FRONT_RIGHT;
30889  case SL_SPEAKER_TOP_BACK_LEFT: return MA_CHANNEL_TOP_BACK_LEFT;
30890  case SL_SPEAKER_TOP_BACK_CENTER: return MA_CHANNEL_TOP_BACK_CENTER;
30891  case SL_SPEAKER_TOP_BACK_RIGHT: return MA_CHANNEL_TOP_BACK_RIGHT;
30892  default: return 0;
30893  }
30894 }
30895 
30896 /* Converts an individual miniaudio channel identifier (MA_CHANNEL_FRONT_LEFT, etc.) to OpenSL-style. */
30897 static SLuint32 ma_channel_id_to_opensl(ma_uint8 id)
30898 {
30899  switch (id)
30900  {
30901  case MA_CHANNEL_MONO: return SL_SPEAKER_FRONT_CENTER;
30902  case MA_CHANNEL_FRONT_LEFT: return SL_SPEAKER_FRONT_LEFT;
30903  case MA_CHANNEL_FRONT_RIGHT: return SL_SPEAKER_FRONT_RIGHT;
30904  case MA_CHANNEL_FRONT_CENTER: return SL_SPEAKER_FRONT_CENTER;
30905  case MA_CHANNEL_LFE: return SL_SPEAKER_LOW_FREQUENCY;
30906  case MA_CHANNEL_BACK_LEFT: return SL_SPEAKER_BACK_LEFT;
30907  case MA_CHANNEL_BACK_RIGHT: return SL_SPEAKER_BACK_RIGHT;
30908  case MA_CHANNEL_FRONT_LEFT_CENTER: return SL_SPEAKER_FRONT_LEFT_OF_CENTER;
30909  case MA_CHANNEL_FRONT_RIGHT_CENTER: return SL_SPEAKER_FRONT_RIGHT_OF_CENTER;
30910  case MA_CHANNEL_BACK_CENTER: return SL_SPEAKER_BACK_CENTER;
30911  case MA_CHANNEL_SIDE_LEFT: return SL_SPEAKER_SIDE_LEFT;
30912  case MA_CHANNEL_SIDE_RIGHT: return SL_SPEAKER_SIDE_RIGHT;
30913  case MA_CHANNEL_TOP_CENTER: return SL_SPEAKER_TOP_CENTER;
30914  case MA_CHANNEL_TOP_FRONT_LEFT: return SL_SPEAKER_TOP_FRONT_LEFT;
30915  case MA_CHANNEL_TOP_FRONT_CENTER: return SL_SPEAKER_TOP_FRONT_CENTER;
30916  case MA_CHANNEL_TOP_FRONT_RIGHT: return SL_SPEAKER_TOP_FRONT_RIGHT;
30917  case MA_CHANNEL_TOP_BACK_LEFT: return SL_SPEAKER_TOP_BACK_LEFT;
30918  case MA_CHANNEL_TOP_BACK_CENTER: return SL_SPEAKER_TOP_BACK_CENTER;
30919  case MA_CHANNEL_TOP_BACK_RIGHT: return SL_SPEAKER_TOP_BACK_RIGHT;
30920  default: return 0;
30921  }
30922 }
30923 
30924 /* Converts a channel mapping to an OpenSL-style channel mask. */
30925 static SLuint32 ma_channel_map_to_channel_mask__opensl(const ma_channel* pChannelMap, ma_uint32 channels)
30926 {
30927  SLuint32 channelMask = 0;
30928  ma_uint32 iChannel;
30929  for (iChannel = 0; iChannel < channels; ++iChannel) {
30930  channelMask |= ma_channel_id_to_opensl(pChannelMap[iChannel]);
30931  }
30932 
30933  return channelMask;
30934 }
30935 
30936 /* Converts an OpenSL-style channel mask to a miniaudio channel map. */
30937 static void ma_channel_mask_to_channel_map__opensl(SLuint32 channelMask, ma_uint32 channels, ma_channel* pChannelMap)
30938 {
30939  if (channels == 1 && channelMask == 0) {
30940  pChannelMap[0] = MA_CHANNEL_MONO;
30941  } else if (channels == 2 && channelMask == 0) {
30942  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
30943  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
30944  } else {
30945  if (channels == 1 && (channelMask & SL_SPEAKER_FRONT_CENTER) != 0) {
30946  pChannelMap[0] = MA_CHANNEL_MONO;
30947  } else {
30948  /* Just iterate over each bit. */
30949  ma_uint32 iChannel = 0;
30950  ma_uint32 iBit;
30951  for (iBit = 0; iBit < 32 && iChannel < channels; ++iBit) {
30952  SLuint32 bitValue = (channelMask & (1UL << iBit));
30953  if (bitValue != 0) {
30954  /* The bit is set. */
30955  pChannelMap[iChannel] = ma_channel_id_to_ma__opensl(bitValue);
30956  iChannel += 1;
30957  }
30958  }
30959  }
30960  }
30961 }
30962 
30963 static SLuint32 ma_round_to_standard_sample_rate__opensl(SLuint32 samplesPerSec)
30964 {
30965  if (samplesPerSec <= SL_SAMPLINGRATE_8) {
30966  return SL_SAMPLINGRATE_8;
30967  }
30968  if (samplesPerSec <= SL_SAMPLINGRATE_11_025) {
30969  return SL_SAMPLINGRATE_11_025;
30970  }
30971  if (samplesPerSec <= SL_SAMPLINGRATE_12) {
30972  return SL_SAMPLINGRATE_12;
30973  }
30974  if (samplesPerSec <= SL_SAMPLINGRATE_16) {
30975  return SL_SAMPLINGRATE_16;
30976  }
30977  if (samplesPerSec <= SL_SAMPLINGRATE_22_05) {
30978  return SL_SAMPLINGRATE_22_05;
30979  }
30980  if (samplesPerSec <= SL_SAMPLINGRATE_24) {
30981  return SL_SAMPLINGRATE_24;
30982  }
30983  if (samplesPerSec <= SL_SAMPLINGRATE_32) {
30984  return SL_SAMPLINGRATE_32;
30985  }
30986  if (samplesPerSec <= SL_SAMPLINGRATE_44_1) {
30987  return SL_SAMPLINGRATE_44_1;
30988  }
30989  if (samplesPerSec <= SL_SAMPLINGRATE_48) {
30990  return SL_SAMPLINGRATE_48;
30991  }
30992 
30993  /* Android doesn't support more than 48000. */
30994 #ifndef MA_ANDROID
30995  if (samplesPerSec <= SL_SAMPLINGRATE_64) {
30996  return SL_SAMPLINGRATE_64;
30997  }
30998  if (samplesPerSec <= SL_SAMPLINGRATE_88_2) {
30999  return SL_SAMPLINGRATE_88_2;
31000  }
31001  if (samplesPerSec <= SL_SAMPLINGRATE_96) {
31002  return SL_SAMPLINGRATE_96;
31003  }
31004  if (samplesPerSec <= SL_SAMPLINGRATE_192) {
31005  return SL_SAMPLINGRATE_192;
31006  }
31007 #endif
31008 
31009  return SL_SAMPLINGRATE_16;
31010 }
31011 
31012 
31013 static SLint32 ma_to_stream_type__opensl(ma_opensl_stream_type streamType)
31014 {
31015  switch (streamType) {
31016  case ma_opensl_stream_type_voice: return SL_ANDROID_STREAM_VOICE;
31017  case ma_opensl_stream_type_system: return SL_ANDROID_STREAM_SYSTEM;
31018  case ma_opensl_stream_type_ring: return SL_ANDROID_STREAM_RING;
31019  case ma_opensl_stream_type_media: return SL_ANDROID_STREAM_MEDIA;
31020  case ma_opensl_stream_type_alarm: return SL_ANDROID_STREAM_ALARM;
31021  case ma_opensl_stream_type_notification: return SL_ANDROID_STREAM_NOTIFICATION;
31022  default: break;
31023  }
31024 
31025  return SL_ANDROID_STREAM_VOICE;
31026 }
31027 
31028 static SLint32 ma_to_recording_preset__opensl(ma_opensl_recording_preset recordingPreset)
31029 {
31030  switch (recordingPreset) {
31031  case ma_opensl_recording_preset_generic: return SL_ANDROID_RECORDING_PRESET_GENERIC;
31032  case ma_opensl_recording_preset_camcorder: return SL_ANDROID_RECORDING_PRESET_CAMCORDER;
31033  case ma_opensl_recording_preset_voice_recognition: return SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
31034  case ma_opensl_recording_preset_voice_communication: return SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
31035  case ma_opensl_recording_preset_voice_unprocessed: return SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
31036  default: break;
31037  }
31038 
31039  return SL_ANDROID_RECORDING_PRESET_NONE;
31040 }
31041 
31042 
31043 static ma_result ma_context_enumerate_devices__opensl(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
31044 {
31045  ma_bool32 cbResult;
31046 
31047  MA_ASSERT(pContext != NULL);
31048  MA_ASSERT(callback != NULL);
31049 
31050  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. */
31051  if (g_maOpenSLInitCounter == 0) {
31052  return MA_INVALID_OPERATION;
31053  }
31054 
31055  /*
31056  TODO: Test Me.
31057 
31058  This is currently untested, so for now we are just returning default devices.
31059  */
31060 #if 0 && !defined(MA_ANDROID)
31061  ma_bool32 isTerminated = MA_FALSE;
31062 
31063  SLuint32 pDeviceIDs[128];
31064  SLint32 deviceCount = sizeof(pDeviceIDs) / sizeof(pDeviceIDs[0]);
31065 
31066  SLAudioIODeviceCapabilitiesItf deviceCaps;
31067  SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
31068  if (resultSL != SL_RESULT_SUCCESS) {
31069  /* The interface may not be supported so just report a default device. */
31070  goto return_default_device;
31071  }
31072 
31073  /* Playback */
31074  if (!isTerminated) {
31075  resultSL = (*deviceCaps)->GetAvailableAudioOutputs(deviceCaps, &deviceCount, pDeviceIDs);
31076  if (resultSL != SL_RESULT_SUCCESS) {
31077  return ma_result_from_OpenSL(resultSL);
31078  }
31079 
31080  for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
31081  ma_device_info deviceInfo;
31082  MA_ZERO_OBJECT(&deviceInfo);
31083  deviceInfo.id.opensl = pDeviceIDs[iDevice];
31084 
31085  SLAudioOutputDescriptor desc;
31086  resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, deviceInfo.id.opensl, &desc);
31087  if (resultSL == SL_RESULT_SUCCESS) {
31088  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), (const char*)desc.pDeviceName, (size_t)-1);
31089 
31090  ma_bool32 cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
31091  if (cbResult == MA_FALSE) {
31092  isTerminated = MA_TRUE;
31093  break;
31094  }
31095  }
31096  }
31097  }
31098 
31099  /* Capture */
31100  if (!isTerminated) {
31101  resultSL = (*deviceCaps)->GetAvailableAudioInputs(deviceCaps, &deviceCount, pDeviceIDs);
31102  if (resultSL != SL_RESULT_SUCCESS) {
31103  return ma_result_from_OpenSL(resultSL);
31104  }
31105 
31106  for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
31107  ma_device_info deviceInfo;
31108  MA_ZERO_OBJECT(&deviceInfo);
31109  deviceInfo.id.opensl = pDeviceIDs[iDevice];
31110 
31111  SLAudioInputDescriptor desc;
31112  resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, deviceInfo.id.opensl, &desc);
31113  if (resultSL == SL_RESULT_SUCCESS) {
31114  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), (const char*)desc.deviceName, (size_t)-1);
31115 
31116  ma_bool32 cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
31117  if (cbResult == MA_FALSE) {
31118  isTerminated = MA_TRUE;
31119  break;
31120  }
31121  }
31122  }
31123  }
31124 
31125  return MA_SUCCESS;
31126 #else
31127  goto return_default_device;
31128 #endif
31129 
31130 return_default_device:;
31131  cbResult = MA_TRUE;
31132 
31133  /* Playback. */
31134  if (cbResult) {
31135  ma_device_info deviceInfo;
31136  MA_ZERO_OBJECT(&deviceInfo);
31137  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
31138  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
31139  }
31140 
31141  /* Capture. */
31142  if (cbResult) {
31143  ma_device_info deviceInfo;
31144  MA_ZERO_OBJECT(&deviceInfo);
31145  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
31146  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
31147  }
31148 
31149  return MA_SUCCESS;
31150 }
31151 
31152 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)
31153 {
31154  MA_ASSERT(pContext != NULL);
31155  MA_ASSERT(pDeviceInfo != NULL);
31156 
31157  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
31158  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
31159  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
31160  pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
31161  pDeviceInfo->nativeDataFormatCount += 1;
31162 }
31163 
31164 static void ma_context_add_data_format__opensl(ma_context* pContext, ma_format format, ma_device_info* pDeviceInfo)
31165 {
31166  ma_uint32 minChannels = 1;
31167  ma_uint32 maxChannels = 2;
31170  ma_uint32 iChannel;
31171  ma_uint32 iSampleRate;
31172 
31173  MA_ASSERT(pContext != NULL);
31174  MA_ASSERT(pDeviceInfo != NULL);
31175 
31176  /*
31177  Each sample format can support mono and stereo, and we'll support a small subset of standard
31178  rates (up to 48000). A better solution would be to somehow find a native sample rate.
31179  */
31180  for (iChannel = minChannels; iChannel < maxChannels; iChannel += 1) {
31181  for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); iSampleRate += 1) {
31182  ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iSampleRate];
31183  if (standardSampleRate >= minSampleRate && standardSampleRate <= maxSampleRate) {
31184  ma_context_add_data_format_ex__opensl(pContext, format, iChannel, standardSampleRate, pDeviceInfo);
31185  }
31186  }
31187  }
31188 }
31189 
31190 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)
31191 {
31192  MA_ASSERT(pContext != NULL);
31193 
31194  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. */
31195  if (g_maOpenSLInitCounter == 0) {
31196  return MA_INVALID_OPERATION;
31197  }
31198 
31199  /*
31200  TODO: Test Me.
31201 
31202  This is currently untested, so for now we are just returning default devices.
31203  */
31204 #if 0 && !defined(MA_ANDROID)
31205  SLAudioIODeviceCapabilitiesItf deviceCaps;
31206  SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
31207  if (resultSL != SL_RESULT_SUCCESS) {
31208  /* The interface may not be supported so just report a default device. */
31209  goto return_default_device;
31210  }
31211 
31212  if (deviceType == ma_device_type_playback) {
31213  SLAudioOutputDescriptor desc;
31214  resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
31215  if (resultSL != SL_RESULT_SUCCESS) {
31216  return ma_result_from_OpenSL(resultSL);
31217  }
31218 
31219  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), (const char*)desc.pDeviceName, (size_t)-1);
31220  } else {
31221  SLAudioInputDescriptor desc;
31222  resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
31223  if (resultSL != SL_RESULT_SUCCESS) {
31224  return ma_result_from_OpenSL(resultSL);
31225  }
31226 
31227  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), (const char*)desc.deviceName, (size_t)-1);
31228  }
31229 
31230  goto return_detailed_info;
31231 #else
31232  goto return_default_device;
31233 #endif
31234 
31235 return_default_device:
31236  if (pDeviceID != NULL) {
31237  if ((deviceType == ma_device_type_playback && pDeviceID->opensl != SL_DEFAULTDEVICEID_AUDIOOUTPUT) ||
31238  (deviceType == ma_device_type_capture && pDeviceID->opensl != SL_DEFAULTDEVICEID_AUDIOINPUT)) {
31239  return MA_NO_DEVICE; /* Don't know the device. */
31240  }
31241  }
31242 
31243  /* Name / Description */
31244  if (deviceType == ma_device_type_playback) {
31245  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
31246  } else {
31247  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
31248  }
31249 
31250  pDeviceInfo->isDefault = MA_TRUE;
31251 
31252  goto return_detailed_info;
31253 
31254 
31255 return_detailed_info:
31256 
31257  /*
31258  For now we're just outputting a set of values that are supported by the API but not necessarily supported
31259  by the device natively. Later on we should work on this so that it more closely reflects the device's
31260  actual native format.
31261  */
31262  pDeviceInfo->nativeDataFormatCount = 0;
31263 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
31264  ma_context_add_data_format__opensl(pContext, ma_format_f32, pDeviceInfo);
31265 #endif
31266  ma_context_add_data_format__opensl(pContext, ma_format_s16, pDeviceInfo);
31267  ma_context_add_data_format__opensl(pContext, ma_format_u8, pDeviceInfo);
31268 
31269  return MA_SUCCESS;
31270 }
31271 
31272 
31273 #ifdef MA_ANDROID
31274 /*void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue, SLuint32 eventFlags, const void* pBuffer, SLuint32 bufferSize, SLuint32 dataUsed, void* pContext)*/
31275 static void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue, void* pUserData)
31276 {
31277  ma_device* pDevice = (ma_device*)pUserData;
31278  size_t periodSizeInBytes;
31279  ma_uint8* pBuffer;
31280  SLresult resultSL;
31281 
31282  MA_ASSERT(pDevice != NULL);
31283 
31284  (void)pBufferQueue;
31285 
31286  /*
31287  For now, don't do anything unless the buffer was fully processed. From what I can tell, it looks like
31288  OpenSL|ES 1.1 improves on buffer queues to the point that we could much more intelligently handle this,
31289  but unfortunately it looks like Android is only supporting OpenSL|ES 1.0.1 for now :(
31290  */
31291 
31292  /* Don't do anything if the device is not started. */
31293  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
31294  return;
31295  }
31296 
31297  /* Don't do anything if the device is being drained. */
31298  if (pDevice->opensl.isDrainingCapture) {
31299  return;
31300  }
31301 
31302  periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
31303  pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
31304 
31306 
31307  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pBuffer, periodSizeInBytes);
31308  if (resultSL != SL_RESULT_SUCCESS) {
31309  return;
31310  }
31311 
31312  pDevice->opensl.currentBufferIndexCapture = (pDevice->opensl.currentBufferIndexCapture + 1) % pDevice->capture.internalPeriods;
31313 }
31314 
31315 static void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue, void* pUserData)
31316 {
31317  ma_device* pDevice = (ma_device*)pUserData;
31318  size_t periodSizeInBytes;
31319  ma_uint8* pBuffer;
31320  SLresult resultSL;
31321 
31322  MA_ASSERT(pDevice != NULL);
31323 
31324  (void)pBufferQueue;
31325 
31326  /* Don't do anything if the device is not started. */
31327  if (ma_device_get_state(pDevice) != MA_STATE_STARTED) {
31328  return;
31329  }
31330 
31331  /* Don't do anything if the device is being drained. */
31332  if (pDevice->opensl.isDrainingPlayback) {
31333  return;
31334  }
31335 
31337  pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
31338 
31340 
31341  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pBuffer, periodSizeInBytes);
31342  if (resultSL != SL_RESULT_SUCCESS) {
31343  return;
31344  }
31345 
31346  pDevice->opensl.currentBufferIndexPlayback = (pDevice->opensl.currentBufferIndexPlayback + 1) % pDevice->playback.internalPeriods;
31347 }
31348 #endif
31349 
31350 static ma_result ma_device_uninit__opensl(ma_device* pDevice)
31351 {
31352  MA_ASSERT(pDevice != NULL);
31353 
31354  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. */
31355  if (g_maOpenSLInitCounter == 0) {
31356  return MA_INVALID_OPERATION;
31357  }
31358 
31359  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
31360  if (pDevice->opensl.pAudioRecorderObj) {
31361  MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioRecorderObj);
31362  }
31363 
31364  ma__free_from_callbacks(pDevice->opensl.pBufferCapture, &pDevice->pContext->allocationCallbacks);
31365  }
31366 
31367  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
31368  if (pDevice->opensl.pAudioPlayerObj) {
31369  MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioPlayerObj);
31370  }
31371  if (pDevice->opensl.pOutputMixObj) {
31372  MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Destroy((SLObjectItf)pDevice->opensl.pOutputMixObj);
31373  }
31374 
31375  ma__free_from_callbacks(pDevice->opensl.pBufferPlayback, &pDevice->pContext->allocationCallbacks);
31376  }
31377 
31378  return MA_SUCCESS;
31379 }
31380 
31381 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
31382 typedef SLAndroidDataFormat_PCM_EX ma_SLDataFormat_PCM;
31383 #else
31384 typedef SLDataFormat_PCM ma_SLDataFormat_PCM;
31385 #endif
31386 
31387 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)
31388 {
31389  /* We need to convert our format/channels/rate so that they aren't set to default. */
31390  if (format == ma_format_unknown) {
31391  format = MA_DEFAULT_FORMAT;
31392  }
31393  if (channels == 0) {
31394  channels = MA_DEFAULT_CHANNELS;
31395  }
31396  if (sampleRate == 0) {
31397  sampleRate = MA_DEFAULT_SAMPLE_RATE;
31398  }
31399 
31400 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
31401  if (format == ma_format_f32) {
31402  pDataFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
31403  pDataFormat->representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
31404  } else {
31405  pDataFormat->formatType = SL_DATAFORMAT_PCM;
31406  }
31407 #else
31408  pDataFormat->formatType = SL_DATAFORMAT_PCM;
31409 #endif
31410 
31411  pDataFormat->numChannels = channels;
31412  ((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 */
31413  pDataFormat->bitsPerSample = ma_get_bytes_per_sample(format)*8;
31414  pDataFormat->channelMask = ma_channel_map_to_channel_mask__opensl(channelMap, channels);
31415  pDataFormat->endianness = (ma_is_little_endian()) ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
31416 
31417  /*
31418  Android has a few restrictions on the format as documented here: https://developer.android.com/ndk/guides/audio/opensl-for-android.html
31419  - Only mono and stereo is supported.
31420  - Only u8 and s16 formats are supported.
31421  - Maximum sample rate of 48000.
31422  */
31423 #ifdef MA_ANDROID
31424  if (pDataFormat->numChannels > 2) {
31425  pDataFormat->numChannels = 2;
31426  }
31427 #if __ANDROID_API__ >= 21
31428  if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
31429  /* It's floating point. */
31430  MA_ASSERT(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
31431  if (pDataFormat->bitsPerSample > 32) {
31432  pDataFormat->bitsPerSample = 32;
31433  }
31434  } else {
31435  if (pDataFormat->bitsPerSample > 16) {
31436  pDataFormat->bitsPerSample = 16;
31437  }
31438  }
31439 #else
31440  if (pDataFormat->bitsPerSample > 16) {
31441  pDataFormat->bitsPerSample = 16;
31442  }
31443 #endif
31444  if (((SLDataFormat_PCM*)pDataFormat)->samplesPerSec > SL_SAMPLINGRATE_48) {
31445  ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = SL_SAMPLINGRATE_48;
31446  }
31447 #endif
31448 
31449  pDataFormat->containerSize = pDataFormat->bitsPerSample; /* Always tightly packed for now. */
31450 
31451  return MA_SUCCESS;
31452 }
31453 
31454 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)
31455 {
31456  ma_bool32 isFloatingPoint = MA_FALSE;
31457 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
31458  if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
31459  MA_ASSERT(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
31460  isFloatingPoint = MA_TRUE;
31461  }
31462 #endif
31463  if (isFloatingPoint) {
31464  if (pDataFormat->bitsPerSample == 32) {
31465  *pFormat = ma_format_f32;
31466  }
31467  } else {
31468  if (pDataFormat->bitsPerSample == 8) {
31469  *pFormat = ma_format_u8;
31470  } else if (pDataFormat->bitsPerSample == 16) {
31471  *pFormat = ma_format_s16;
31472  } else if (pDataFormat->bitsPerSample == 24) {
31473  *pFormat = ma_format_s24;
31474  } else if (pDataFormat->bitsPerSample == 32) {
31475  *pFormat = ma_format_s32;
31476  }
31477  }
31478 
31479  *pChannels = pDataFormat->numChannels;
31480  *pSampleRate = ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec / 1000;
31481  ma_channel_mask_to_channel_map__opensl(pDataFormat->channelMask, ma_min(pDataFormat->numChannels, channelMapCap), pChannelMap);
31482 
31483  return MA_SUCCESS;
31484 }
31485 
31486 static ma_result ma_device_init__opensl(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
31487 {
31488 #ifdef MA_ANDROID
31489  SLDataLocator_AndroidSimpleBufferQueue queue;
31490  SLresult resultSL;
31491  size_t bufferSizeInBytes;
31492  SLInterfaceID itfIDs[2];
31493  const SLboolean itfIDsRequired[] = {
31494  SL_BOOLEAN_TRUE, /* SL_IID_ANDROIDSIMPLEBUFFERQUEUE */
31495  SL_BOOLEAN_FALSE /* SL_IID_ANDROIDCONFIGURATION */
31496  };
31497 #endif
31498 
31499  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. */
31500  if (g_maOpenSLInitCounter == 0) {
31501  return MA_INVALID_OPERATION;
31502  }
31503 
31504  if (pConfig->deviceType == ma_device_type_loopback) {
31506  }
31507 
31508  /*
31509  For now, only supporting Android implementations of OpenSL|ES since that's the only one I've
31510  been able to test with and I currently depend on Android-specific extensions (simple buffer
31511  queues).
31512  */
31513 #ifdef MA_ANDROID
31514  itfIDs[0] = (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
31515  itfIDs[1] = (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION;
31516 
31517  /* No exclusive mode with OpenSL|ES. */
31518  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
31519  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
31521  }
31522 
31523  /* Now we can start initializing the device properly. */
31524  MA_ASSERT(pDevice != NULL);
31525  MA_ZERO_OBJECT(&pDevice->opensl);
31526 
31527  queue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
31528 
31529  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
31530  ma_SLDataFormat_PCM pcm;
31531  SLDataLocator_IODevice locatorDevice;
31532  SLDataSource source;
31533  SLDataSink sink;
31534  SLAndroidConfigurationItf pRecorderConfig;
31535 
31536  ma_SLDataFormat_PCM_init__opensl(pDescriptorCapture->format, pDescriptorCapture->channels, pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, &pcm);
31537 
31538  locatorDevice.locatorType = SL_DATALOCATOR_IODEVICE;
31539  locatorDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
31540  locatorDevice.deviceID = (pDescriptorCapture->pDeviceID == NULL) ? SL_DEFAULTDEVICEID_AUDIOINPUT : pDescriptorCapture->pDeviceID->opensl;
31541  locatorDevice.device = NULL;
31542 
31543  source.pLocator = &locatorDevice;
31544  source.pFormat = NULL;
31545 
31546  queue.numBuffers = pDescriptorCapture->periodCount;
31547 
31548  sink.pLocator = &queue;
31549  sink.pFormat = (SLDataFormat_PCM*)&pcm;
31550 
31551  resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
31552  if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
31553  /* Unsupported format. Fall back to something safer and try again. If this fails, just abort. */
31554  pcm.formatType = SL_DATAFORMAT_PCM;
31555  pcm.numChannels = 1;
31556  ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16; /* The name of the sample rate variable is different between SLAndroidDataFormat_PCM_EX and SLDataFormat_PCM. */
31557  pcm.bitsPerSample = 16;
31558  pcm.containerSize = pcm.bitsPerSample; /* Always tightly packed for now. */
31559  pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
31560  resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
31561  }
31562 
31563  if (resultSL != SL_RESULT_SUCCESS) {
31564  ma_device_uninit__opensl(pDevice);
31565  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to create audio recorder.", ma_result_from_OpenSL(resultSL));
31566  }
31567 
31568 
31569  /* Set the recording preset before realizing the player. */
31571  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pRecorderConfig);
31572  if (resultSL == SL_RESULT_SUCCESS) {
31573  SLint32 recordingPreset = ma_to_recording_preset__opensl(pConfig->opensl.recordingPreset);
31574  resultSL = (*pRecorderConfig)->SetConfiguration(pRecorderConfig, SL_ANDROID_KEY_RECORDING_PRESET, &recordingPreset, sizeof(SLint32));
31575  if (resultSL != SL_RESULT_SUCCESS) {
31576  /* Failed to set the configuration. Just keep going. */
31577  }
31578  }
31579  }
31580 
31581  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Realize((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_BOOLEAN_FALSE);
31582  if (resultSL != SL_RESULT_SUCCESS) {
31583  ma_device_uninit__opensl(pDevice);
31584  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize audio recorder.", ma_result_from_OpenSL(resultSL));
31585  }
31586 
31587  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_RECORD, &pDevice->opensl.pAudioRecorder);
31588  if (resultSL != SL_RESULT_SUCCESS) {
31589  ma_device_uninit__opensl(pDevice);
31590  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_RECORD interface.", ma_result_from_OpenSL(resultSL));
31591  }
31592 
31593  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueueCapture);
31594  if (resultSL != SL_RESULT_SUCCESS) {
31595  ma_device_uninit__opensl(pDevice);
31596  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_ANDROIDSIMPLEBUFFERQUEUE interface.", ma_result_from_OpenSL(resultSL));
31597  }
31598 
31599  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, ma_buffer_queue_callback_capture__opensl_android, pDevice);
31600  if (resultSL != SL_RESULT_SUCCESS) {
31601  ma_device_uninit__opensl(pDevice);
31602  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to register buffer queue callback.", ma_result_from_OpenSL(resultSL));
31603  }
31604 
31605  /* The internal format is determined by the "pcm" object. */
31606  ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDescriptorCapture->format, &pDescriptorCapture->channels, &pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, ma_countof(pDescriptorCapture->channelMap));
31607 
31608  /* Buffer. */
31609  pDescriptorCapture->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorCapture, pDescriptorCapture->sampleRate, pConfig->performanceProfile);
31610  pDevice->opensl.currentBufferIndexCapture = 0;
31611 
31612  bufferSizeInBytes = pDescriptorCapture->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) * pDescriptorCapture->periodCount;
31613  pDevice->opensl.pBufferCapture = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pDevice->pContext->allocationCallbacks);
31614  if (pDevice->opensl.pBufferCapture == NULL) {
31615  ma_device_uninit__opensl(pDevice);
31616  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to allocate memory for data buffer.", MA_OUT_OF_MEMORY);
31617  }
31618  MA_ZERO_MEMORY(pDevice->opensl.pBufferCapture, bufferSizeInBytes);
31619  }
31620 
31621  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
31622  ma_SLDataFormat_PCM pcm;
31623  SLDataSource source;
31624  SLDataLocator_OutputMix outmixLocator;
31625  SLDataSink sink;
31626  SLAndroidConfigurationItf pPlayerConfig;
31627 
31628  ma_SLDataFormat_PCM_init__opensl(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &pcm);
31629 
31630  resultSL = (*g_maEngineSL)->CreateOutputMix(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pOutputMixObj, 0, NULL, NULL);
31631  if (resultSL != SL_RESULT_SUCCESS) {
31632  ma_device_uninit__opensl(pDevice);
31633  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to create output mix.", ma_result_from_OpenSL(resultSL));
31634  }
31635 
31636  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Realize((SLObjectItf)pDevice->opensl.pOutputMixObj, SL_BOOLEAN_FALSE);
31637  if (resultSL != SL_RESULT_SUCCESS) {
31638  ma_device_uninit__opensl(pDevice);
31639  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize output mix object.", ma_result_from_OpenSL(resultSL));
31640  }
31641 
31642  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->GetInterface((SLObjectItf)pDevice->opensl.pOutputMixObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_OUTPUTMIX, &pDevice->opensl.pOutputMix);
31643  if (resultSL != SL_RESULT_SUCCESS) {
31644  ma_device_uninit__opensl(pDevice);
31645  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_OUTPUTMIX interface.", ma_result_from_OpenSL(resultSL));
31646  }
31647 
31648  /* Set the output device. */
31649  if (pDescriptorPlayback->pDeviceID != NULL) {
31650  SLuint32 deviceID_OpenSL = pDescriptorPlayback->pDeviceID->opensl;
31651  MA_OPENSL_OUTPUTMIX(pDevice->opensl.pOutputMix)->ReRoute((SLOutputMixItf)pDevice->opensl.pOutputMix, 1, &deviceID_OpenSL);
31652  }
31653 
31654  queue.numBuffers = pDescriptorPlayback->periodCount;
31655 
31656  source.pLocator = &queue;
31657  source.pFormat = (SLDataFormat_PCM*)&pcm;
31658 
31659  outmixLocator.locatorType = SL_DATALOCATOR_OUTPUTMIX;
31660  outmixLocator.outputMix = (SLObjectItf)pDevice->opensl.pOutputMixObj;
31661 
31662  sink.pLocator = &outmixLocator;
31663  sink.pFormat = NULL;
31664 
31665  resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
31666  if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
31667  /* Unsupported format. Fall back to something safer and try again. If this fails, just abort. */
31668  pcm.formatType = SL_DATAFORMAT_PCM;
31669  pcm.numChannels = 2;
31670  ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16;
31671  pcm.bitsPerSample = 16;
31672  pcm.containerSize = pcm.bitsPerSample; /* Always tightly packed for now. */
31673  pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
31674  resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &source, &sink, ma_countof(itfIDs), itfIDs, itfIDsRequired);
31675  }
31676 
31677  if (resultSL != SL_RESULT_SUCCESS) {
31678  ma_device_uninit__opensl(pDevice);
31679  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to create audio player.", ma_result_from_OpenSL(resultSL));
31680  }
31681 
31682 
31683  /* Set the stream type before realizing the player. */
31685  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pPlayerConfig);
31686  if (resultSL == SL_RESULT_SUCCESS) {
31687  SLint32 streamType = ma_to_stream_type__opensl(pConfig->opensl.streamType);
31688  resultSL = (*pPlayerConfig)->SetConfiguration(pPlayerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
31689  if (resultSL != SL_RESULT_SUCCESS) {
31690  /* Failed to set the configuration. Just keep going. */
31691  }
31692  }
31693  }
31694 
31695  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Realize((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_BOOLEAN_FALSE);
31696  if (resultSL != SL_RESULT_SUCCESS) {
31697  ma_device_uninit__opensl(pDevice);
31698  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize audio player.", ma_result_from_OpenSL(resultSL));
31699  }
31700 
31701  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_PLAY, &pDevice->opensl.pAudioPlayer);
31702  if (resultSL != SL_RESULT_SUCCESS) {
31703  ma_device_uninit__opensl(pDevice);
31704  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_PLAY interface.", ma_result_from_OpenSL(resultSL));
31705  }
31706 
31707  resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueuePlayback);
31708  if (resultSL != SL_RESULT_SUCCESS) {
31709  ma_device_uninit__opensl(pDevice);
31710  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_ANDROIDSIMPLEBUFFERQUEUE interface.", ma_result_from_OpenSL(resultSL));
31711  }
31712 
31713  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, ma_buffer_queue_callback_playback__opensl_android, pDevice);
31714  if (resultSL != SL_RESULT_SUCCESS) {
31715  ma_device_uninit__opensl(pDevice);
31716  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to register buffer queue callback.", ma_result_from_OpenSL(resultSL));
31717  }
31718 
31719  /* The internal format is determined by the "pcm" object. */
31720  ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDescriptorPlayback->format, &pDescriptorPlayback->channels, &pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap));
31721 
31722  /* Buffer. */
31723  pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
31724  pDevice->opensl.currentBufferIndexPlayback = 0;
31725 
31726  bufferSizeInBytes = pDescriptorPlayback->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) * pDescriptorPlayback->periodCount;
31727  pDevice->opensl.pBufferPlayback = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pDevice->pContext->allocationCallbacks);
31728  if (pDevice->opensl.pBufferPlayback == NULL) {
31729  ma_device_uninit__opensl(pDevice);
31730  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to allocate memory for data buffer.", MA_OUT_OF_MEMORY);
31731  }
31732  MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, bufferSizeInBytes);
31733  }
31734 
31735  return MA_SUCCESS;
31736 #else
31737  return MA_NO_BACKEND; /* Non-Android implementations are not supported. */
31738 #endif
31739 }
31740 
31741 static ma_result ma_device_start__opensl(ma_device* pDevice)
31742 {
31743  SLresult resultSL;
31744  size_t periodSizeInBytes;
31745  ma_uint32 iPeriod;
31746 
31747  MA_ASSERT(pDevice != NULL);
31748 
31749  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. */
31750  if (g_maOpenSLInitCounter == 0) {
31751  return MA_INVALID_OPERATION;
31752  }
31753 
31754  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
31755  resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_RECORDING);
31756  if (resultSL != SL_RESULT_SUCCESS) {
31757  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to start internal capture device.", ma_result_from_OpenSL(resultSL));
31758  }
31759 
31760  periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
31761  for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
31762  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pDevice->opensl.pBufferCapture + (periodSizeInBytes * iPeriod), periodSizeInBytes);
31763  if (resultSL != SL_RESULT_SUCCESS) {
31764  MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
31765  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to enqueue buffer for capture device.", ma_result_from_OpenSL(resultSL));
31766  }
31767  }
31768  }
31769 
31770  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
31771  resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_PLAYING);
31772  if (resultSL != SL_RESULT_SUCCESS) {
31773  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to start internal playback device.", ma_result_from_OpenSL(resultSL));
31774  }
31775 
31776  /* In playback mode (no duplex) we need to load some initial buffers. In duplex mode we need to enqueu silent buffers. */
31777  if (pDevice->type == ma_device_type_duplex) {
31778  MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, pDevice->playback.internalPeriodSizeInFrames * pDevice->playback.internalPeriods * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
31779  } else {
31780  ma_device__read_frames_from_client(pDevice, pDevice->playback.internalPeriodSizeInFrames * pDevice->playback.internalPeriods, pDevice->opensl.pBufferPlayback);
31781  }
31782 
31784  for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
31785  resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pDevice->opensl.pBufferPlayback + (periodSizeInBytes * iPeriod), periodSizeInBytes);
31786  if (resultSL != SL_RESULT_SUCCESS) {
31787  MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
31788  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to enqueue buffer for playback device.", ma_result_from_OpenSL(resultSL));
31789  }
31790  }
31791  }
31792 
31793  return MA_SUCCESS;
31794 }
31795 
31796 static ma_result ma_device_drain__opensl(ma_device* pDevice, ma_device_type deviceType)
31797 {
31798  SLAndroidSimpleBufferQueueItf pBufferQueue;
31799 
31800  MA_ASSERT(deviceType == ma_device_type_capture || deviceType == ma_device_type_playback);
31801 
31802  if (pDevice->type == ma_device_type_capture) {
31803  pBufferQueue = (SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture;
31804  pDevice->opensl.isDrainingCapture = MA_TRUE;
31805  } else {
31806  pBufferQueue = (SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback;
31807  pDevice->opensl.isDrainingPlayback = MA_TRUE;
31808  }
31809 
31810  for (;;) {
31811  SLAndroidSimpleBufferQueueState state;
31812 
31813  MA_OPENSL_BUFFERQUEUE(pBufferQueue)->GetState(pBufferQueue, &state);
31814  if (state.count == 0) {
31815  break;
31816  }
31817 
31818  ma_sleep(10);
31819  }
31820 
31821  if (pDevice->type == ma_device_type_capture) {
31822  pDevice->opensl.isDrainingCapture = MA_FALSE;
31823  } else {
31824  pDevice->opensl.isDrainingPlayback = MA_FALSE;
31825  }
31826 
31827  return MA_SUCCESS;
31828 }
31829 
31830 static ma_result ma_device_stop__opensl(ma_device* pDevice)
31831 {
31832  SLresult resultSL;
31833  ma_stop_proc onStop;
31834 
31835  MA_ASSERT(pDevice != NULL);
31836 
31837  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. */
31838  if (g_maOpenSLInitCounter == 0) {
31839  return MA_INVALID_OPERATION;
31840  }
31841 
31842  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
31843  ma_device_drain__opensl(pDevice, ma_device_type_capture);
31844 
31845  resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
31846  if (resultSL != SL_RESULT_SUCCESS) {
31847  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal capture device.", ma_result_from_OpenSL(resultSL));
31848  }
31849 
31850  MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture);
31851  }
31852 
31853  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
31854  ma_device_drain__opensl(pDevice, ma_device_type_playback);
31855 
31856  resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
31857  if (resultSL != SL_RESULT_SUCCESS) {
31858  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to stop internal playback device.", ma_result_from_OpenSL(resultSL));
31859  }
31860 
31861  MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback);
31862  }
31863 
31864  /* 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. */
31865  onStop = pDevice->onStop;
31866  if (onStop) {
31867  onStop(pDevice);
31868  }
31869 
31870  return MA_SUCCESS;
31871 }
31872 
31873 
31874 static ma_result ma_context_uninit__opensl(ma_context* pContext)
31875 {
31876  MA_ASSERT(pContext != NULL);
31877  MA_ASSERT(pContext->backend == ma_backend_opensl);
31878  (void)pContext;
31879 
31880  /* Uninit global data. */
31881  ma_spinlock_lock(&g_maOpenSLSpinlock);
31882  {
31883  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(). */
31884 
31885  g_maOpenSLInitCounter -= 1;
31886  if (g_maOpenSLInitCounter == 0) {
31887  (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
31888  }
31889  }
31890  ma_spinlock_unlock(&g_maOpenSLSpinlock);
31891 
31892  return MA_SUCCESS;
31893 }
31894 
31895 static ma_result ma_dlsym_SLInterfaceID__opensl(ma_context* pContext, const char* pName, ma_handle* pHandle)
31896 {
31897  /* 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. */
31898  ma_handle* p = (ma_handle*)ma_dlsym(pContext, pContext->opensl.libOpenSLES, pName);
31899  if (p == NULL) {
31900  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_INFO, "[OpenSL|ES] Cannot find symbol %s", pName);
31901  return MA_NO_BACKEND;
31902  }
31903 
31904  *pHandle = *p;
31905  return MA_SUCCESS;
31906 }
31907 
31908 static ma_result ma_context_init_engine_nolock__opensl(ma_context* pContext)
31909 {
31910  g_maOpenSLInitCounter += 1;
31911  if (g_maOpenSLInitCounter == 1) {
31912  SLresult resultSL;
31913 
31914  resultSL = ((ma_slCreateEngine_proc)pContext->opensl.slCreateEngine)(&g_maEngineObjectSL, 0, NULL, 0, NULL, NULL);
31915  if (resultSL != SL_RESULT_SUCCESS) {
31916  g_maOpenSLInitCounter -= 1;
31917  return ma_result_from_OpenSL(resultSL);
31918  }
31919 
31920  (*g_maEngineObjectSL)->Realize(g_maEngineObjectSL, SL_BOOLEAN_FALSE);
31921 
31922  resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_ENGINE, &g_maEngineSL);
31923  if (resultSL != SL_RESULT_SUCCESS) {
31924  (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
31925  g_maOpenSLInitCounter -= 1;
31926  return ma_result_from_OpenSL(resultSL);
31927  }
31928  }
31929 
31930  return MA_SUCCESS;
31931 }
31932 
31933 static ma_result ma_context_init__opensl(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
31934 {
31935  ma_result result;
31936 
31937 #if !defined(MA_NO_RUNTIME_LINKING)
31938  size_t i;
31939  const char* libOpenSLESNames[] = {
31940  "libOpenSLES.so"
31941  };
31942 #endif
31943 
31944  MA_ASSERT(pContext != NULL);
31945 
31946  (void)pConfig;
31947 
31948 #if !defined(MA_NO_RUNTIME_LINKING)
31949  /*
31950  Dynamically link against libOpenSLES.so. I have now had multiple reports that SL_IID_ANDROIDSIMPLEBUFFERQUEUE cannot be found. One
31951  report was happening at compile time and another at runtime. To try working around this, I'm going to link to libOpenSLES at runtime
31952  and extract the symbols rather than reference them directly. This should, hopefully, fix these issues as the compiler won't see any
31953  references to the symbols and will hopefully skip the checks.
31954  */
31955  for (i = 0; i < ma_countof(libOpenSLESNames); i += 1) {
31956  pContext->opensl.libOpenSLES = ma_dlopen(pContext, libOpenSLESNames[i]);
31957  if (pContext->opensl.libOpenSLES != NULL) {
31958  break;
31959  }
31960  }
31961 
31962  if (pContext->opensl.libOpenSLES == NULL) {
31963  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_INFO, "[OpenSL|ES] Could not find libOpenSLES.so");
31964  return MA_NO_BACKEND;
31965  }
31966 
31967  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ENGINE", &pContext->opensl.SL_IID_ENGINE);
31968  if (result != MA_SUCCESS) {
31969  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
31970  return result;
31971  }
31972 
31973  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_AUDIOIODEVICECAPABILITIES", &pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES);
31974  if (result != MA_SUCCESS) {
31975  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
31976  return result;
31977  }
31978 
31979  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ANDROIDSIMPLEBUFFERQUEUE", &pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE);
31980  if (result != MA_SUCCESS) {
31981  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
31982  return result;
31983  }
31984 
31985  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_RECORD", &pContext->opensl.SL_IID_RECORD);
31986  if (result != MA_SUCCESS) {
31987  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
31988  return result;
31989  }
31990 
31991  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_PLAY", &pContext->opensl.SL_IID_PLAY);
31992  if (result != MA_SUCCESS) {
31993  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
31994  return result;
31995  }
31996 
31997  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_OUTPUTMIX", &pContext->opensl.SL_IID_OUTPUTMIX);
31998  if (result != MA_SUCCESS) {
31999  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
32000  return result;
32001  }
32002 
32003  result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ANDROIDCONFIGURATION", &pContext->opensl.SL_IID_ANDROIDCONFIGURATION);
32004  if (result != MA_SUCCESS) {
32005  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
32006  return result;
32007  }
32008 
32009  pContext->opensl.slCreateEngine = (ma_proc)ma_dlsym(pContext, pContext->opensl.libOpenSLES, "slCreateEngine");
32010  if (pContext->opensl.slCreateEngine == NULL) {
32011  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
32012  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_INFO, "[OpenSL|ES] Cannot find symbol slCreateEngine.");
32013  return MA_NO_BACKEND;
32014  }
32015 #else
32016  pContext->opensl.SL_IID_ENGINE = (ma_handle)SL_IID_ENGINE;
32017  pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES = (ma_handle)SL_IID_AUDIOIODEVICECAPABILITIES;
32018  pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE = (ma_handle)SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
32019  pContext->opensl.SL_IID_RECORD = (ma_handle)SL_IID_RECORD;
32020  pContext->opensl.SL_IID_PLAY = (ma_handle)SL_IID_PLAY;
32021  pContext->opensl.SL_IID_OUTPUTMIX = (ma_handle)SL_IID_OUTPUTMIX;
32022  pContext->opensl.SL_IID_ANDROIDCONFIGURATION = (ma_handle)SL_IID_ANDROIDCONFIGURATION;
32023  pContext->opensl.slCreateEngine = (ma_proc)slCreateEngine;
32024 #endif
32025 
32026 
32027  /* Initialize global data first if applicable. */
32028  ma_spinlock_lock(&g_maOpenSLSpinlock);
32029  {
32030  result = ma_context_init_engine_nolock__opensl(pContext);
32031  }
32032  ma_spinlock_unlock(&g_maOpenSLSpinlock);
32033 
32034  if (result != MA_SUCCESS) {
32035  ma_dlclose(pContext, pContext->opensl.libOpenSLES);
32036  ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_INFO, "[OpenSL|ES] Failed to initialize OpenSL engine.");
32037  return result;
32038  }
32039 
32040  pCallbacks->onContextInit = ma_context_init__opensl;
32041  pCallbacks->onContextUninit = ma_context_uninit__opensl;
32042  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__opensl;
32043  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__opensl;
32044  pCallbacks->onDeviceInit = ma_device_init__opensl;
32045  pCallbacks->onDeviceUninit = ma_device_uninit__opensl;
32046  pCallbacks->onDeviceStart = ma_device_start__opensl;
32047  pCallbacks->onDeviceStop = ma_device_stop__opensl;
32048  pCallbacks->onDeviceRead = NULL; /* Not needed because OpenSL|ES is asynchronous. */
32049  pCallbacks->onDeviceWrite = NULL; /* Not needed because OpenSL|ES is asynchronous. */
32050  pCallbacks->onDeviceDataLoop = NULL; /* Not needed because OpenSL|ES is asynchronous. */
32051 
32052  return MA_SUCCESS;
32053 }
32054 #endif /* OpenSL|ES */
32055 
32056 
32057 /******************************************************************************
32058 
32059 Web Audio Backend
32060 
32061 ******************************************************************************/
32062 #ifdef MA_HAS_WEBAUDIO
32063 #include <emscripten/emscripten.h>
32064 
32065 static ma_bool32 ma_is_capture_supported__webaudio()
32066 {
32067  return EM_ASM_INT({
32068  return (navigator.mediaDevices !== undefined && navigator.mediaDevices.getUserMedia !== undefined);
32069  }, 0) != 0; /* Must pass in a dummy argument for C99 compatibility. */
32070 }
32071 
32072 #ifdef __cplusplus
32073 extern "C" {
32074 #endif
32075 void EMSCRIPTEN_KEEPALIVE ma_device_process_pcm_frames_capture__webaudio(ma_device* pDevice, int frameCount, float* pFrames)
32076 {
32077  ma_device_handle_backend_data_callback(pDevice, NULL, pFrames, (ma_uint32)frameCount);
32078 }
32079 
32080 void EMSCRIPTEN_KEEPALIVE ma_device_process_pcm_frames_playback__webaudio(ma_device* pDevice, int frameCount, float* pFrames)
32081 {
32082  ma_device_handle_backend_data_callback(pDevice, pFrames, NULL, (ma_uint32)frameCount);
32083 }
32084 #ifdef __cplusplus
32085 }
32086 #endif
32087 
32088 static ma_result ma_context_enumerate_devices__webaudio(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
32089 {
32090  ma_bool32 cbResult = MA_TRUE;
32091 
32092  MA_ASSERT(pContext != NULL);
32093  MA_ASSERT(callback != NULL);
32094 
32095  /* Only supporting default devices for now. */
32096 
32097  /* Playback. */
32098  if (cbResult) {
32099  ma_device_info deviceInfo;
32100  MA_ZERO_OBJECT(&deviceInfo);
32101  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
32102  deviceInfo.isDefault = MA_TRUE; /* Only supporting default devices. */
32103  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
32104  }
32105 
32106  /* Capture. */
32107  if (cbResult) {
32108  if (ma_is_capture_supported__webaudio()) {
32109  ma_device_info deviceInfo;
32110  MA_ZERO_OBJECT(&deviceInfo);
32111  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
32112  deviceInfo.isDefault = MA_TRUE; /* Only supporting default devices. */
32113  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
32114  }
32115  }
32116 
32117  return MA_SUCCESS;
32118 }
32119 
32120 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)
32121 {
32122  MA_ASSERT(pContext != NULL);
32123 
32124  if (deviceType == ma_device_type_capture && !ma_is_capture_supported__webaudio()) {
32125  return MA_NO_DEVICE;
32126  }
32127 
32128  MA_ZERO_MEMORY(pDeviceInfo->id.webaudio, sizeof(pDeviceInfo->id.webaudio));
32129 
32130  /* Only supporting default devices for now. */
32131  (void)pDeviceID;
32132  if (deviceType == ma_device_type_playback) {
32133  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
32134  } else {
32135  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
32136  }
32137 
32138  /* Only supporting default devices. */
32139  pDeviceInfo->isDefault = MA_TRUE;
32140 
32141  /* Web Audio can support any number of channels and sample rates. It only supports f32 formats, however. */
32142  pDeviceInfo->nativeDataFormats[0].flags = 0;
32143  pDeviceInfo->nativeDataFormats[0].format = ma_format_unknown;
32144  pDeviceInfo->nativeDataFormats[0].channels = 0; /* All channels are supported. */
32145  pDeviceInfo->nativeDataFormats[0].sampleRate = EM_ASM_INT({
32146  try {
32147  var temp = new (window.AudioContext || window.webkitAudioContext)();
32148  var sampleRate = temp.sampleRate;
32149  temp.close();
32150  return sampleRate;
32151  } catch(e) {
32152  return 0;
32153  }
32154  }, 0); /* Must pass in a dummy argument for C99 compatibility. */
32155 
32156  if (pDeviceInfo->nativeDataFormats[0].sampleRate == 0) {
32157  return MA_NO_DEVICE;
32158  }
32159 
32160  pDeviceInfo->nativeDataFormatCount = 1;
32161 
32162  return MA_SUCCESS;
32163 }
32164 
32165 
32166 static void ma_device_uninit_by_index__webaudio(ma_device* pDevice, ma_device_type deviceType, int deviceIndex)
32167 {
32168  MA_ASSERT(pDevice != NULL);
32169 
32170  EM_ASM({
32171  var device = miniaudio.get_device_by_index($0);
32172 
32173  /* Make sure all nodes are disconnected and marked for collection. */
32174  if (device.scriptNode !== undefined) {
32175  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... */
32176  device.scriptNode.disconnect();
32177  device.scriptNode = undefined;
32178  }
32179  if (device.streamNode !== undefined) {
32180  device.streamNode.disconnect();
32181  device.streamNode = undefined;
32182  }
32183 
32184  /*
32185  Stop the device. I think there is a chance the callback could get fired after calling this, hence why we want
32186  to clear the callback before closing.
32187  */
32188  device.webaudio.close();
32189  device.webaudio = undefined;
32190 
32191  /* Can't forget to free the intermediary buffer. This is the buffer that's shared between JavaScript and C. */
32192  if (device.intermediaryBuffer !== undefined) {
32193  Module._free(device.intermediaryBuffer);
32194  device.intermediaryBuffer = undefined;
32195  device.intermediaryBufferView = undefined;
32196  device.intermediaryBufferSizeInBytes = undefined;
32197  }
32198 
32199  /* Make sure the device is untracked so the slot can be reused later. */
32200  miniaudio.untrack_device_by_index($0);
32201  }, deviceIndex, deviceType);
32202 }
32203 
32204 static ma_result ma_device_uninit__webaudio(ma_device* pDevice)
32205 {
32206  MA_ASSERT(pDevice != NULL);
32207 
32208  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
32209  ma_device_uninit_by_index__webaudio(pDevice, ma_device_type_capture, pDevice->webaudio.indexCapture);
32210  }
32211 
32212  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
32213  ma_device_uninit_by_index__webaudio(pDevice, ma_device_type_playback, pDevice->webaudio.indexPlayback);
32214  }
32215 
32216  return MA_SUCCESS;
32217 }
32218 
32219 static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(const ma_device_descriptor* pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
32220 {
32221  /*
32222  There have been reports of the default buffer size being too small on some browsers. There have been reports of the default buffer
32223  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
32224  standard defaults.
32225  */
32226  ma_uint32 periodSizeInFrames;
32227 
32228  if (pDescriptor->periodSizeInFrames == 0) {
32229  if (pDescriptor->periodSizeInMilliseconds == 0) {
32230  if (performanceProfile == ma_performance_profile_low_latency) {
32231  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(33, nativeSampleRate); /* 1 frame @ 30 FPS */
32232  } else {
32233  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(333, nativeSampleRate);
32234  }
32235  } else {
32236  periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptor->periodSizeInMilliseconds, nativeSampleRate);
32237  }
32238  } else {
32239  periodSizeInFrames = pDescriptor->periodSizeInFrames;
32240  }
32241 
32242  /* The size of the buffer must be a power of 2 and between 256 and 16384. */
32243  if (periodSizeInFrames < 256) {
32244  periodSizeInFrames = 256;
32245  } else if (periodSizeInFrames > 16384) {
32246  periodSizeInFrames = 16384;
32247  } else {
32248  periodSizeInFrames = ma_next_power_of_2(periodSizeInFrames);
32249  }
32250 
32251  return periodSizeInFrames;
32252 }
32253 
32254 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)
32255 {
32256  int deviceIndex;
32257  ma_uint32 channels;
32258  ma_uint32 sampleRate;
32259  ma_uint32 periodSizeInFrames;
32260 
32261  MA_ASSERT(pDevice != NULL);
32262  MA_ASSERT(pConfig != NULL);
32263  MA_ASSERT(deviceType != ma_device_type_duplex);
32264 
32265  if (deviceType == ma_device_type_capture && !ma_is_capture_supported__webaudio()) {
32266  return MA_NO_DEVICE;
32267  }
32268 
32269  /* We're going to calculate some stuff in C just to simplify the JS code. */
32270  channels = (pDescriptor->channels > 0) ? pDescriptor->channels : MA_DEFAULT_CHANNELS;
32271  sampleRate = (pDescriptor->sampleRate > 0) ? pDescriptor->sampleRate : MA_DEFAULT_SAMPLE_RATE;
32272  periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__webaudio(pDescriptor, sampleRate, pConfig->performanceProfile);
32273 
32274 
32275  /* 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. */
32276  deviceIndex = EM_ASM_INT({
32277  var channels = $0;
32278  var sampleRate = $1;
32279  var bufferSize = $2; /* In PCM frames. */
32280  var isCapture = $3;
32281  var pDevice = $4;
32282 
32283  if (typeof(miniaudio) === 'undefined') {
32284  return -1; /* Context not initialized. */
32285  }
32286 
32287  var device = {};
32288 
32289  /* The AudioContext must be created in a suspended state. */
32290  device.webaudio = new (window.AudioContext || window.webkitAudioContext)({sampleRate:sampleRate});
32291  device.webaudio.suspend();
32292  device.state = 1; /* MA_STATE_STOPPED */
32293 
32294  /*
32295  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
32296  JavaScript and C it needs to be allocated and freed using Module._malloc() and Module._free().
32297  */
32298  device.intermediaryBufferSizeInBytes = channels * bufferSize * 4;
32299  device.intermediaryBuffer = Module._malloc(device.intermediaryBufferSizeInBytes);
32300  device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
32301 
32302  /*
32303  Both playback and capture devices use a ScriptProcessorNode for performing per-sample operations.
32304 
32305  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
32306  that's periodically fired, just like a normal audio callback function. But apparently this design is "flawed" and is now deprecated in favour of
32307  something called AudioWorklets which _forces_ you to load a _separate_ .js file at run time... nice... Hopefully ScriptProcessorNode will continue to
32308  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
32309  implementation. I'll be avoiding that insane AudioWorklet API like the plague...
32310 
32311  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
32312  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
32313  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
32314  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
32315  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
32316  this for now. If anyone knows how I could get raw PCM data using the MediaRecorder API please let me know!
32317  */
32318  device.scriptNode = device.webaudio.createScriptProcessor(bufferSize, channels, channels);
32319 
32320  if (isCapture) {
32321  device.scriptNode.onaudioprocess = function(e) {
32322  if (device.intermediaryBuffer === undefined) {
32323  return; /* This means the device has been uninitialized. */
32324  }
32325 
32326  if(device.intermediaryBufferView.length == 0) {
32327  /* Recreate intermediaryBufferView when losing reference to the underlying buffer, probably due to emscripten resizing heap. */
32328  device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
32329  }
32330 
32331  /* Make sure silence it output to the AudioContext destination. Not doing this will cause sound to come out of the speakers! */
32332  for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
32333  e.outputBuffer.getChannelData(iChannel).fill(0.0);
32334  }
32335 
32336  /* There are some situations where we may want to send silence to the client. */
32337  var sendSilence = false;
32338  if (device.streamNode === undefined) {
32339  sendSilence = true;
32340  }
32341 
32342  /* Sanity check. This will never happen, right? */
32343  if (e.inputBuffer.numberOfChannels != channels) {
32344  console.log("Capture: Channel count mismatch. " + e.inputBufer.numberOfChannels + " != " + channels + ". Sending silence.");
32345  sendSilence = true;
32346  }
32347 
32348  /* This looped design guards against the situation where e.inputBuffer is a different size to the original buffer size. Should never happen in practice. */
32349  var totalFramesProcessed = 0;
32350  while (totalFramesProcessed < e.inputBuffer.length) {
32351  var framesRemaining = e.inputBuffer.length - totalFramesProcessed;
32352  var framesToProcess = framesRemaining;
32353  if (framesToProcess > (device.intermediaryBufferSizeInBytes/channels/4)) {
32354  framesToProcess = (device.intermediaryBufferSizeInBytes/channels/4);
32355  }
32356 
32357  /* 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. */
32358  if (sendSilence) {
32359  device.intermediaryBufferView.fill(0.0);
32360  } else {
32361  for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
32362  for (var iChannel = 0; iChannel < e.inputBuffer.numberOfChannels; ++iChannel) {
32363  device.intermediaryBufferView[iFrame*channels + iChannel] = e.inputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame];
32364  }
32365  }
32366  }
32367 
32368  /* Send data to the client from our intermediary buffer. */
32369  ccall("ma_device_process_pcm_frames_capture__webaudio", "undefined", ["number", "number", "number"], [pDevice, framesToProcess, device.intermediaryBuffer]);
32370 
32371  totalFramesProcessed += framesToProcess;
32372  }
32373  };
32374 
32375  navigator.mediaDevices.getUserMedia({audio:true, video:false})
32376  .then(function(stream) {
32377  device.streamNode = device.webaudio.createMediaStreamSource(stream);
32378  device.streamNode.connect(device.scriptNode);
32379  device.scriptNode.connect(device.webaudio.destination);
32380  })
32381  .catch(function(error) {
32382  /* I think this should output silence... */
32383  device.scriptNode.connect(device.webaudio.destination);
32384  });
32385  } else {
32386  device.scriptNode.onaudioprocess = function(e) {
32387  if (device.intermediaryBuffer === undefined) {
32388  return; /* This means the device has been uninitialized. */
32389  }
32390 
32391  if(device.intermediaryBufferView.length == 0) {
32392  /* Recreate intermediaryBufferView when losing reference to the underlying buffer, probably due to emscripten resizing heap. */
32393  device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
32394  }
32395 
32396  var outputSilence = false;
32397 
32398  /* Sanity check. This will never happen, right? */
32399  if (e.outputBuffer.numberOfChannels != channels) {
32400  console.log("Playback: Channel count mismatch. " + e.outputBufer.numberOfChannels + " != " + channels + ". Outputting silence.");
32401  outputSilence = true;
32402  return;
32403  }
32404 
32405  /* This looped design guards against the situation where e.outputBuffer is a different size to the original buffer size. Should never happen in practice. */
32406  var totalFramesProcessed = 0;
32407  while (totalFramesProcessed < e.outputBuffer.length) {
32408  var framesRemaining = e.outputBuffer.length - totalFramesProcessed;
32409  var framesToProcess = framesRemaining;
32410  if (framesToProcess > (device.intermediaryBufferSizeInBytes/channels/4)) {
32411  framesToProcess = (device.intermediaryBufferSizeInBytes/channels/4);
32412  }
32413 
32414  /* Read data from the client into our intermediary buffer. */
32415  ccall("ma_device_process_pcm_frames_playback__webaudio", "undefined", ["number", "number", "number"], [pDevice, framesToProcess, device.intermediaryBuffer]);
32416 
32417  /* At this point we'll have data in our intermediary buffer which we now need to deinterleave and copy over to the output buffers. */
32418  if (outputSilence) {
32419  for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
32420  e.outputBuffer.getChannelData(iChannel).fill(0.0);
32421  }
32422  } else {
32423  for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
32424  for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
32425  e.outputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame] = device.intermediaryBufferView[iFrame*channels + iChannel];
32426  }
32427  }
32428  }
32429 
32430  totalFramesProcessed += framesToProcess;
32431  }
32432  };
32433 
32434  device.scriptNode.connect(device.webaudio.destination);
32435  }
32436 
32437  return miniaudio.track_device(device);
32438  }, channels, sampleRate, periodSizeInFrames, deviceType == ma_device_type_capture, pDevice);
32439 
32440  if (deviceIndex < 0) {
32442  }
32443 
32444  if (deviceType == ma_device_type_capture) {
32445  pDevice->webaudio.indexCapture = deviceIndex;
32446  } else {
32447  pDevice->webaudio.indexPlayback = deviceIndex;
32448  }
32449 
32450  pDescriptor->format = ma_format_f32;
32451  pDescriptor->channels = channels;
32453  pDescriptor->sampleRate = EM_ASM_INT({ return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
32454  pDescriptor->periodSizeInFrames = periodSizeInFrames;
32455  pDescriptor->periodCount = 1;
32456 
32457  return MA_SUCCESS;
32458 }
32459 
32460 static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
32461 {
32462  ma_result result;
32463 
32464  if (pConfig->deviceType == ma_device_type_loopback) {
32466  }
32467 
32468  /* No exclusive mode with Web Audio. */
32469  if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
32470  ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
32472  }
32473 
32474  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
32475  result = ma_device_init_by_type__webaudio(pDevice, pConfig, pDescriptorCapture, ma_device_type_capture);
32476  if (result != MA_SUCCESS) {
32477  return result;
32478  }
32479  }
32480 
32481  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
32482  result = ma_device_init_by_type__webaudio(pDevice, pConfig, pDescriptorPlayback, ma_device_type_playback);
32483  if (result != MA_SUCCESS) {
32484  if (pConfig->deviceType == ma_device_type_duplex) {
32485  ma_device_uninit_by_index__webaudio(pDevice, ma_device_type_capture, pDevice->webaudio.indexCapture);
32486  }
32487  return result;
32488  }
32489  }
32490 
32491  return MA_SUCCESS;
32492 }
32493 
32494 static ma_result ma_device_start__webaudio(ma_device* pDevice)
32495 {
32496  MA_ASSERT(pDevice != NULL);
32497 
32498  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
32499  EM_ASM({
32500  var device = miniaudio.get_device_by_index($0);
32501  device.webaudio.resume();
32502  device.state = 2; /* MA_STATE_STARTED */
32503  }, pDevice->webaudio.indexCapture);
32504  }
32505 
32506  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
32507  EM_ASM({
32508  var device = miniaudio.get_device_by_index($0);
32509  device.webaudio.resume();
32510  device.state = 2; /* MA_STATE_STARTED */
32511  }, pDevice->webaudio.indexPlayback);
32512  }
32513 
32514  return MA_SUCCESS;
32515 }
32516 
32517 static ma_result ma_device_stop__webaudio(ma_device* pDevice)
32518 {
32519  MA_ASSERT(pDevice != NULL);
32520 
32521  /*
32522  From the WebAudio API documentation for AudioContext.suspend():
32523 
32524  Suspends the progression of AudioContext's currentTime, allows any current context processing blocks that are already processed to be played to the
32525  destination, and then allows the system to release its claim on audio hardware.
32526 
32527  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
32528  do any kind of explicit draining.
32529  */
32530 
32531  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
32532  EM_ASM({
32533  var device = miniaudio.get_device_by_index($0);
32534  device.webaudio.suspend();
32535  device.state = 1; /* MA_STATE_STOPPED */
32536  }, pDevice->webaudio.indexCapture);
32537  }
32538 
32539  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
32540  EM_ASM({
32541  var device = miniaudio.get_device_by_index($0);
32542  device.webaudio.suspend();
32543  device.state = 1; /* MA_STATE_STOPPED */
32544  }, pDevice->webaudio.indexPlayback);
32545  }
32546 
32547  ma_stop_proc onStop = pDevice->onStop;
32548  if (onStop) {
32549  onStop(pDevice);
32550  }
32551 
32552  return MA_SUCCESS;
32553 }
32554 
32555 static ma_result ma_context_uninit__webaudio(ma_context* pContext)
32556 {
32557  MA_ASSERT(pContext != NULL);
32558  MA_ASSERT(pContext->backend == ma_backend_webaudio);
32559 
32560  /* Nothing needs to be done here. */
32561  (void)pContext;
32562 
32563  return MA_SUCCESS;
32564 }
32565 
32566 static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
32567 {
32568  int resultFromJS;
32569 
32570  MA_ASSERT(pContext != NULL);
32571 
32572  (void)pConfig; /* Unused. */
32573 
32574  /* Here is where our global JavaScript object is initialized. */
32575  resultFromJS = EM_ASM_INT({
32576  if ((window.AudioContext || window.webkitAudioContext) === undefined) {
32577  return 0; /* Web Audio not supported. */
32578  }
32579 
32580  if (typeof(miniaudio) === 'undefined') {
32581  miniaudio = {};
32582  miniaudio.devices = []; /* Device cache for mapping devices to indexes for JavaScript/C interop. */
32583 
32584  miniaudio.track_device = function(device) {
32585  /* Try inserting into a free slot first. */
32586  for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
32587  if (miniaudio.devices[iDevice] == null) {
32588  miniaudio.devices[iDevice] = device;
32589  return iDevice;
32590  }
32591  }
32592 
32593  /* Getting here means there is no empty slots in the array so we just push to the end. */
32594  miniaudio.devices.push(device);
32595  return miniaudio.devices.length - 1;
32596  };
32597 
32598  miniaudio.untrack_device_by_index = function(deviceIndex) {
32599  /* We just set the device's slot to null. The slot will get reused in the next call to ma_track_device. */
32600  miniaudio.devices[deviceIndex] = null;
32601 
32602  /* Trim the array if possible. */
32603  while (miniaudio.devices.length > 0) {
32604  if (miniaudio.devices[miniaudio.devices.length-1] == null) {
32605  miniaudio.devices.pop();
32606  } else {
32607  break;
32608  }
32609  }
32610  };
32611 
32612  miniaudio.untrack_device = function(device) {
32613  for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
32614  if (miniaudio.devices[iDevice] == device) {
32615  return miniaudio.untrack_device_by_index(iDevice);
32616  }
32617  }
32618  };
32619 
32620  miniaudio.get_device_by_index = function(deviceIndex) {
32621  return miniaudio.devices[deviceIndex];
32622  };
32623 
32624  miniaudio.unlock_event_types = (function(){
32625  return ['touchstart', 'touchend', 'click'];
32626  })();
32627 
32628  miniaudio.unlock = function() {
32629  for(var i = 0; i < miniaudio.devices.length; ++i) {
32630  var device = miniaudio.devices[i];
32631  if (device != null && device.webaudio != null && device.state === 2 /* MA_STATE_STARTED */) {
32632  device.webaudio.resume();
32633  }
32634  }
32635  miniaudio.unlock_event_types.map(function(event_type) {
32636  document.removeEventListener(event_type, miniaudio.unlock, true);
32637  });
32638  };
32639 
32640  miniaudio.unlock_event_types.map(function(event_type) {
32641  document.addEventListener(event_type, miniaudio.unlock, true);
32642  });
32643  }
32644 
32645  return 1;
32646  }, 0); /* Must pass in a dummy argument for C99 compatibility. */
32647 
32648  if (resultFromJS != 1) {
32650  }
32651 
32652  pCallbacks->onContextInit = ma_context_init__webaudio;
32653  pCallbacks->onContextUninit = ma_context_uninit__webaudio;
32654  pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__webaudio;
32655  pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__webaudio;
32656  pCallbacks->onDeviceInit = ma_device_init__webaudio;
32657  pCallbacks->onDeviceUninit = ma_device_uninit__webaudio;
32658  pCallbacks->onDeviceStart = ma_device_start__webaudio;
32659  pCallbacks->onDeviceStop = ma_device_stop__webaudio;
32660  pCallbacks->onDeviceRead = NULL; /* Not needed because WebAudio is asynchronous. */
32661  pCallbacks->onDeviceWrite = NULL; /* Not needed because WebAudio is asynchronous. */
32662  pCallbacks->onDeviceDataLoop = NULL; /* Not needed because WebAudio is asynchronous. */
32663 
32664  return MA_SUCCESS;
32665 }
32666 #endif /* Web Audio */
32667 
32668 
32669 
32670 static ma_bool32 ma__is_channel_map_valid(const ma_channel* channelMap, ma_uint32 channels)
32671 {
32672  /* A blank channel map should be allowed, in which case it should use an appropriate default which will depend on context. */
32673  if (channelMap[0] != MA_CHANNEL_NONE) {
32674  ma_uint32 iChannel;
32675 
32676  if (channels == 0 || channels > MA_MAX_CHANNELS) {
32677  return MA_FALSE; /* Channel count out of range. */
32678  }
32679 
32680  /* A channel cannot be present in the channel map more than once. */
32681  for (iChannel = 0; iChannel < channels; ++iChannel) {
32682  ma_uint32 jChannel;
32683  for (jChannel = iChannel + 1; jChannel < channels; ++jChannel) {
32684  if (channelMap[iChannel] == channelMap[jChannel]) {
32685  return MA_FALSE;
32686  }
32687  }
32688  }
32689  }
32690 
32691  return MA_TRUE;
32692 }
32693 
32694 
32695 static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType)
32696 {
32697  ma_result result;
32698 
32699  MA_ASSERT(pDevice != NULL);
32700 
32701  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
32702  if (pDevice->capture.format == ma_format_unknown) {
32703  pDevice->capture.format = pDevice->capture.internalFormat;
32704  }
32705  if (pDevice->capture.channels == 0) {
32706  pDevice->capture.channels = pDevice->capture.internalChannels;
32707  }
32708  if (pDevice->capture.channelMap[0] == MA_CHANNEL_NONE) {
32710  if (pDevice->capture.internalChannels == pDevice->capture.channels) {
32712  } else {
32715  } else {
32717  }
32718  }
32719  }
32720  }
32721 
32722  if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
32723  if (pDevice->playback.format == ma_format_unknown) {
32724  pDevice->playback.format = pDevice->playback.internalFormat;
32725  }
32726  if (pDevice->playback.channels == 0) {
32727  pDevice->playback.channels = pDevice->playback.internalChannels;
32728  }
32729  if (pDevice->playback.channelMap[0] == MA_CHANNEL_NONE) {
32731  if (pDevice->playback.internalChannels == pDevice->playback.channels) {
32733  } else {
32736  } else {
32738  }
32739  }
32740  }
32741  }
32742 
32743  if (pDevice->sampleRate == 0) {
32744  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
32745  pDevice->sampleRate = pDevice->capture.internalSampleRate;
32746  } else {
32747  pDevice->sampleRate = pDevice->playback.internalSampleRate;
32748  }
32749  }
32750 
32751  /* Data converters. */
32752  if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
32753  /* Converting from internal device format to client format. */
32755  converterConfig.formatIn = pDevice->capture.internalFormat;
32756  converterConfig.channelsIn = pDevice->capture.internalChannels;
32757  converterConfig.sampleRateIn = pDevice->capture.internalSampleRate;
32759  converterConfig.formatOut = pDevice->capture.format;
32760  converterConfig.channelsOut = pDevice->capture.channels;
32761  converterConfig.sampleRateOut = pDevice->sampleRate;
32763  converterConfig.channelMixMode = pDevice->capture.channelMixMode;
32764  converterConfig.resampling.allowDynamicSampleRate = MA_FALSE;
32765  converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
32766  converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
32767  converterConfig.resampling.speex.quality = pDevice->resampling.speex.quality;
32768 
32769  result = ma_data_converter_init(&converterConfig, &pDevice->capture.converter);
32770  if (result != MA_SUCCESS) {
32771  return result;
32772  }
32773  }
32774 
32775  if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
32776  /* Converting from client format to device format. */
32778  converterConfig.formatIn = pDevice->playback.format;
32779  converterConfig.channelsIn = pDevice->playback.channels;
32780  converterConfig.sampleRateIn = pDevice->sampleRate;
32782  converterConfig.formatOut = pDevice->playback.internalFormat;
32783  converterConfig.channelsOut = pDevice->playback.internalChannels;
32784  converterConfig.sampleRateOut = pDevice->playback.internalSampleRate;
32786  converterConfig.channelMixMode = pDevice->playback.channelMixMode;
32787  converterConfig.resampling.allowDynamicSampleRate = MA_FALSE;
32788  converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
32789  converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
32790  converterConfig.resampling.speex.quality = pDevice->resampling.speex.quality;
32791 
32792  result = ma_data_converter_init(&converterConfig, &pDevice->playback.converter);
32793  if (result != MA_SUCCESS) {
32794  return result;
32795  }
32796  }
32797 
32798  return MA_SUCCESS;
32799 }
32800 
32801 
32803 {
32804  ma_device* pDevice = (ma_device*)pData;
32805  MA_ASSERT(pDevice != NULL);
32806 
32807 #ifdef MA_WIN32
32808  ma_CoInitializeEx(pDevice->pContext, NULL, MA_COINIT_VALUE);
32809 #endif
32810 
32811  /*
32812  When the device is being initialized it's initial state is set to MA_STATE_UNINITIALIZED. Before returning from
32813  ma_device_init(), the state needs to be set to something valid. In miniaudio the device's default state immediately
32814  after initialization is stopped, so therefore we need to mark the device as such. miniaudio will wait on the worker
32815  thread to signal an event to know when the worker thread is ready for action.
32816  */
32818  ma_event_signal(&pDevice->stopEvent);
32819 
32820  for (;;) { /* <-- This loop just keeps the thread alive. The main audio loop is inside. */
32821  ma_result startResult;
32822  ma_result stopResult; /* <-- This will store the result from onDeviceStop(). If it returns an error, we don't fire the onStop callback. */
32823 
32824  /* We wait on an event to know when something has requested that the device be started and the main loop entered. */
32825  ma_event_wait(&pDevice->wakeupEvent);
32826 
32827  /* Default result code. */
32828  pDevice->workResult = MA_SUCCESS;
32829 
32830  /* If the reason for the wake up is that we are terminating, just break from the loop. */
32831  if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
32832  break;
32833  }
32834 
32835  /*
32836  Getting to this point means the device is wanting to get started. The function that has requested that the device
32837  be started will be waiting on an event (pDevice->startEvent) which means we need to make sure we signal the event
32838  in both the success and error case. It's important that the state of the device is set _before_ signaling the event.
32839  */
32841 
32842  /* If the device has a start callback, start it now. */
32843  if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
32844  startResult = pDevice->pContext->callbacks.onDeviceStart(pDevice);
32845  } else {
32846  startResult = MA_SUCCESS;
32847  }
32848 
32849  if (startResult != MA_SUCCESS) {
32850  pDevice->workResult = startResult;
32851  continue; /* Failed to start. Loop back to the start and wait for something to happen (pDevice->wakeupEvent). */
32852  }
32853 
32854  /* Make sure the state is set appropriately. */
32856  ma_event_signal(&pDevice->startEvent);
32857 
32858  if (pDevice->pContext->callbacks.onDeviceDataLoop != NULL) {
32859  pDevice->pContext->callbacks.onDeviceDataLoop(pDevice);
32860  } else {
32861  /* The backend is not using a custom main loop implementation, so now fall back to the blocking read-write implementation. */
32863  }
32864 
32865  /* Getting here means we have broken from the main loop which happens the application has requested that device be stopped. */
32866  if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
32867  stopResult = pDevice->pContext->callbacks.onDeviceStop(pDevice);
32868  } else {
32869  stopResult = MA_SUCCESS; /* No stop callback with the backend. Just assume successful. */
32870  }
32871 
32872  /*
32873  After the device has stopped, make sure an event is posted. Don't post an onStop event if
32874  stopping failed. This can happen on some backends when the underlying stream has been
32875  stopped due to the device being physically unplugged or disabled via an OS setting.
32876  */
32877  if (pDevice->onStop && stopResult != MA_SUCCESS) {
32878  pDevice->onStop(pDevice);
32879  }
32880 
32881  /* 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. */
32883  ma_event_signal(&pDevice->stopEvent);
32884  }
32885 
32886 #ifdef MA_WIN32
32887  ma_CoUninitialize(pDevice->pContext);
32888 #endif
32889 
32890  return (ma_thread_result)0;
32891 }
32892 
32893 
32894 /* Helper for determining whether or not the given device is initialized. */
32896 {
32897  if (pDevice == NULL) {
32898  return MA_FALSE;
32899  }
32900 
32901  return ma_device_get_state(pDevice) != MA_STATE_UNINITIALIZED;
32902 }
32903 
32904 
32905 #ifdef MA_WIN32
32906 static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
32907 {
32908  ma_CoUninitialize(pContext);
32909  ma_dlclose(pContext, pContext->win32.hUser32DLL);
32910  ma_dlclose(pContext, pContext->win32.hOle32DLL);
32911  ma_dlclose(pContext, pContext->win32.hAdvapi32DLL);
32912 
32913  return MA_SUCCESS;
32914 }
32915 
32916 static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
32917 {
32918 #ifdef MA_WIN32_DESKTOP
32919  /* Ole32.dll */
32920  pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
32921  if (pContext->win32.hOle32DLL == NULL) {
32923  }
32924 
32925  pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoInitializeEx");
32926  pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoUninitialize");
32927  pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoCreateInstance");
32928  pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "CoTaskMemFree");
32929  pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "PropVariantClear");
32930  pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL, "StringFromGUID2");
32931 
32932 
32933  /* User32.dll */
32934  pContext->win32.hUser32DLL = ma_dlopen(pContext, "user32.dll");
32935  if (pContext->win32.hUser32DLL == NULL) {
32937  }
32938 
32939  pContext->win32.GetForegroundWindow = (ma_proc)ma_dlsym(pContext, pContext->win32.hUser32DLL, "GetForegroundWindow");
32940  pContext->win32.GetDesktopWindow = (ma_proc)ma_dlsym(pContext, pContext->win32.hUser32DLL, "GetDesktopWindow");
32941 
32942 
32943  /* Advapi32.dll */
32944  pContext->win32.hAdvapi32DLL = ma_dlopen(pContext, "advapi32.dll");
32945  if (pContext->win32.hAdvapi32DLL == NULL) {
32947  }
32948 
32949  pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegOpenKeyExA");
32950  pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegCloseKey");
32951  pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL, "RegQueryValueExA");
32952 #endif
32953 
32954  ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
32955  return MA_SUCCESS;
32956 }
32957 #else
32959 {
32960 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
32961  ma_dlclose(pContext, pContext->posix.pthreadSO);
32962 #else
32963  (void)pContext;
32964 #endif
32965 
32966  return MA_SUCCESS;
32967 }
32968 
32970 {
32971  /* pthread */
32972 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
32973  const char* libpthreadFileNames[] = {
32974  "libpthread.so",
32975  "libpthread.so.0",
32976  "libpthread.dylib"
32977  };
32978  size_t i;
32979 
32980  for (i = 0; i < sizeof(libpthreadFileNames) / sizeof(libpthreadFileNames[0]); ++i) {
32981  pContext->posix.pthreadSO = ma_dlopen(pContext, libpthreadFileNames[i]);
32982  if (pContext->posix.pthreadSO != NULL) {
32983  break;
32984  }
32985  }
32986 
32987  if (pContext->posix.pthreadSO == NULL) {
32989  }
32990 
32991  pContext->posix.pthread_create = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_create");
32992  pContext->posix.pthread_join = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_join");
32993  pContext->posix.pthread_mutex_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_init");
32994  pContext->posix.pthread_mutex_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_destroy");
32995  pContext->posix.pthread_mutex_lock = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_lock");
32996  pContext->posix.pthread_mutex_unlock = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_mutex_unlock");
32997  pContext->posix.pthread_cond_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_init");
32998  pContext->posix.pthread_cond_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_destroy");
32999  pContext->posix.pthread_cond_wait = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_wait");
33000  pContext->posix.pthread_cond_signal = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_signal");
33001  pContext->posix.pthread_attr_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_init");
33002  pContext->posix.pthread_attr_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_destroy");
33003  pContext->posix.pthread_attr_setschedpolicy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_setschedpolicy");
33004  pContext->posix.pthread_attr_getschedparam = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_getschedparam");
33005  pContext->posix.pthread_attr_setschedparam = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_setschedparam");
33006 #else
33007  pContext->posix.pthread_create = (ma_proc)pthread_create;
33008  pContext->posix.pthread_join = (ma_proc)pthread_join;
33009  pContext->posix.pthread_mutex_init = (ma_proc)pthread_mutex_init;
33010  pContext->posix.pthread_mutex_destroy = (ma_proc)pthread_mutex_destroy;
33011  pContext->posix.pthread_mutex_lock = (ma_proc)pthread_mutex_lock;
33012  pContext->posix.pthread_mutex_unlock = (ma_proc)pthread_mutex_unlock;
33013  pContext->posix.pthread_cond_init = (ma_proc)pthread_cond_init;
33014  pContext->posix.pthread_cond_destroy = (ma_proc)pthread_cond_destroy;
33015  pContext->posix.pthread_cond_wait = (ma_proc)pthread_cond_wait;
33016  pContext->posix.pthread_cond_signal = (ma_proc)pthread_cond_signal;
33017  pContext->posix.pthread_attr_init = (ma_proc)pthread_attr_init;
33018  pContext->posix.pthread_attr_destroy = (ma_proc)pthread_attr_destroy;
33019 #if !defined(__EMSCRIPTEN__)
33020  pContext->posix.pthread_attr_setschedpolicy = (ma_proc)pthread_attr_setschedpolicy;
33021  pContext->posix.pthread_attr_getschedparam = (ma_proc)pthread_attr_getschedparam;
33022  pContext->posix.pthread_attr_setschedparam = (ma_proc)pthread_attr_setschedparam;
33023 #endif
33024 #endif
33025 
33026  return MA_SUCCESS;
33027 }
33028 #endif
33029 
33031 {
33032  ma_result result;
33033 #ifdef MA_WIN32
33034  result = ma_context_init_backend_apis__win32(pContext);
33035 #else
33036  result = ma_context_init_backend_apis__nix(pContext);
33037 #endif
33038 
33039  return result;
33040 }
33041 
33043 {
33044  ma_result result;
33045 #ifdef MA_WIN32
33046  result = ma_context_uninit_backend_apis__win32(pContext);
33047 #else
33048  result = ma_context_uninit_backend_apis__nix(pContext);
33049 #endif
33050 
33051  return result;
33052 }
33053 
33054 
33056 {
33057  MA_ASSERT(pContext != NULL);
33058 
33059  if (pContext->callbacks.onDeviceRead == NULL && pContext->callbacks.onDeviceWrite == NULL) {
33060  if (pContext->callbacks.onDeviceDataLoop == NULL) {
33061  return MA_TRUE;
33062  } else {
33063  return MA_FALSE;
33064  }
33065  } else {
33066  return MA_FALSE;
33067  }
33068 }
33069 
33070 
33072 {
33075 
33076  return config;
33077 }
33078 
33079 MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config* pConfig, ma_context* pContext)
33080 {
33081  ma_result result;
33082  ma_context_config defaultConfig;
33083  ma_backend defaultBackends[ma_backend_null+1];
33084  ma_uint32 iBackend;
33085  ma_backend* pBackendsToIterate;
33086  ma_uint32 backendsToIterateCount;
33087 
33088  if (pContext == NULL) {
33089  return MA_INVALID_ARGS;
33090  }
33091 
33092  MA_ZERO_OBJECT(pContext);
33093 
33094  /* Always make sure the config is set first to ensure properties are available as soon as possible. */
33095  if (pConfig == NULL) {
33096  defaultConfig = ma_context_config_init();
33097  pConfig = &defaultConfig;
33098  }
33099 
33100  /* Allocation callbacks need to come first because they'll be passed around to other areas. */
33102  if (result != MA_SUCCESS) {
33103  return result;
33104  }
33105 
33106  /* Get a lot set up first so we can start logging ASAP. */
33107  if (pConfig->pLog != NULL) {
33108  pContext->pLog = pConfig->pLog;
33109  } else {
33110  result = ma_log_init(&pContext->allocationCallbacks, &pContext->log);
33111  if (result == MA_SUCCESS) {
33112  pContext->pLog = &pContext->log;
33113  } else {
33114  pContext->pLog = NULL; /* Logging is not available. */
33115  }
33116  }
33117 
33118  pContext->logCallback = pConfig->logCallback;
33119  pContext->threadPriority = pConfig->threadPriority;
33120  pContext->threadStackSize = pConfig->threadStackSize;
33121  pContext->pUserData = pConfig->pUserData;
33122 
33123  /* Backend APIs need to be initialized first. This is where external libraries will be loaded and linked. */
33124  result = ma_context_init_backend_apis(pContext);
33125  if (result != MA_SUCCESS) {
33126  return result;
33127  }
33128 
33129  for (iBackend = 0; iBackend <= ma_backend_null; ++iBackend) {
33130  defaultBackends[iBackend] = (ma_backend)iBackend;
33131  }
33132 
33133  pBackendsToIterate = (ma_backend*)backends;
33134  backendsToIterateCount = backendCount;
33135  if (pBackendsToIterate == NULL) {
33136  pBackendsToIterate = (ma_backend*)defaultBackends;
33137  backendsToIterateCount = ma_countof(defaultBackends);
33138  }
33139 
33140  MA_ASSERT(pBackendsToIterate != NULL);
33141 
33142  for (iBackend = 0; iBackend < backendsToIterateCount; iBackend += 1) {
33143  ma_backend backend = pBackendsToIterate[iBackend];
33144 
33145  /* Make sure all callbacks are reset so we don't accidentally drag in any from previously failed initialization attempts. */
33146  MA_ZERO_OBJECT(&pContext->callbacks);
33147 
33148  /* These backends are using the new callback system. */
33149  switch (backend) {
33150  #ifdef MA_HAS_WASAPI
33151  case ma_backend_wasapi:
33152  {
33153  pContext->callbacks.onContextInit = ma_context_init__wasapi;
33154  } break;
33155  #endif
33156  #ifdef MA_HAS_DSOUND
33157  case ma_backend_dsound:
33158  {
33159  pContext->callbacks.onContextInit = ma_context_init__dsound;
33160  } break;
33161  #endif
33162  #ifdef MA_HAS_WINMM
33163  case ma_backend_winmm:
33164  {
33165  pContext->callbacks.onContextInit = ma_context_init__winmm;
33166  } break;
33167  #endif
33168  #ifdef MA_HAS_COREAUDIO
33169  case ma_backend_coreaudio:
33170  {
33171  pContext->callbacks.onContextInit = ma_context_init__coreaudio;
33172  } break;
33173  #endif
33174  #ifdef MA_HAS_SNDIO
33175  case ma_backend_sndio:
33176  {
33177  pContext->callbacks.onContextInit = ma_context_init__sndio;
33178  } break;
33179  #endif
33180  #ifdef MA_HAS_AUDIO4
33181  case ma_backend_audio4:
33182  {
33183  pContext->callbacks.onContextInit = ma_context_init__audio4;
33184  } break;
33185  #endif
33186  #ifdef MA_HAS_OSS
33187  case ma_backend_oss:
33188  {
33189  pContext->callbacks.onContextInit = ma_context_init__oss;
33190  } break;
33191  #endif
33192  #ifdef MA_HAS_PULSEAUDIO
33193  case ma_backend_pulseaudio:
33194  {
33195  pContext->callbacks.onContextInit = ma_context_init__pulse;
33196  } break;
33197  #endif
33198  #ifdef MA_HAS_ALSA
33199  case ma_backend_alsa:
33200  {
33201  pContext->callbacks.onContextInit = ma_context_init__alsa;
33202  } break;
33203  #endif
33204  #ifdef MA_HAS_JACK
33205  case ma_backend_jack:
33206  {
33207  pContext->callbacks.onContextInit = ma_context_init__jack;
33208  } break;
33209  #endif
33210  #ifdef MA_HAS_AAUDIO
33211  case ma_backend_aaudio:
33212  {
33213  pContext->callbacks.onContextInit = ma_context_init__aaudio;
33214  } break;
33215  #endif
33216  #ifdef MA_HAS_OPENSL
33217  case ma_backend_opensl:
33218  {
33219  pContext->callbacks.onContextInit = ma_context_init__opensl;
33220  } break;
33221  #endif
33222  #ifdef MA_HAS_WEBAUDIO
33223  case ma_backend_webaudio:
33224  {
33225  pContext->callbacks.onContextInit = ma_context_init__webaudio;
33226  } break;
33227  #endif
33228  #ifdef MA_HAS_CUSTOM
33229  case ma_backend_custom:
33230  {
33231  /* Slightly different logic for custom backends. Custom backends can optionally set all of their callbacks in the config. */
33232  pContext->callbacks = pConfig->custom;
33233  } break;
33234  #endif
33235  #ifdef MA_HAS_NULL
33236  case ma_backend_null:
33237  {
33239  } break;
33240  #endif
33241 
33242  default: break;
33243  }
33244 
33245  if (pContext->callbacks.onContextInit != NULL) {
33246  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Attempting to initialize %s backend...\n", ma_get_backend_name(backend));
33247  result = pContext->callbacks.onContextInit(pContext, pConfig, &pContext->callbacks);
33248  } else {
33249  result = MA_NO_BACKEND;
33250  }
33251 
33252  /* If this iteration was successful, return. */
33253  if (result == MA_SUCCESS) {
33254  result = ma_mutex_init(&pContext->deviceEnumLock);
33255  if (result != MA_SUCCESS) {
33256  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);
33257  }
33258 
33259  result = ma_mutex_init(&pContext->deviceInfoLock);
33260  if (result != MA_SUCCESS) {
33261  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);
33262  }
33263 
33264  #ifdef MA_DEBUG_OUTPUT
33265  {
33266  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] Endian: %s\n", ma_is_little_endian() ? "LE" : "BE");
33267  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] SSE2: %s\n", ma_has_sse2() ? "YES" : "NO");
33268  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] AVX2: %s\n", ma_has_avx2() ? "YES" : "NO");
33269  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] AVX512F: %s\n", ma_has_avx512f() ? "YES" : "NO");
33270  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[miniaudio] NEON: %s\n", ma_has_neon() ? "YES" : "NO");
33271  }
33272  #endif
33273 
33274  pContext->backend = backend;
33275  return result;
33276  } else {
33277  ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Failed to initialize %s backend.\n", ma_get_backend_name(backend));
33278  }
33279  }
33280 
33281  /* If we get here it means an error occurred. */
33282  MA_ZERO_OBJECT(pContext); /* Safety. */
33283  return MA_NO_BACKEND;
33284 }
33285 
33287 {
33288  if (pContext == NULL) {
33289  return MA_INVALID_ARGS;
33290  }
33291 
33292  if (pContext->callbacks.onContextUninit != NULL) {
33293  pContext->callbacks.onContextUninit(pContext);
33294  }
33295 
33296  ma_mutex_uninit(&pContext->deviceEnumLock);
33297  ma_mutex_uninit(&pContext->deviceInfoLock);
33300 
33301  if (pContext->pLog == &pContext->log) {
33302  ma_log_uninit(&pContext->log);
33303  }
33304 
33305  return MA_SUCCESS;
33306 }
33307 
33308 MA_API size_t ma_context_sizeof()
33309 {
33310  return sizeof(ma_context);
33311 }
33312 
33313 
33315 {
33316  if (pContext == NULL) {
33317  return NULL;
33318  }
33319 
33320  return pContext->pLog;
33321 }
33322 
33323 
33325 {
33326  ma_result result;
33327 
33328  if (pContext == NULL || callback == NULL) {
33329  return MA_INVALID_ARGS;
33330  }
33331 
33332  if (pContext->callbacks.onContextEnumerateDevices == NULL) {
33333  return MA_INVALID_OPERATION;
33334  }
33335 
33336  ma_mutex_lock(&pContext->deviceEnumLock);
33337  {
33338  result = pContext->callbacks.onContextEnumerateDevices(pContext, callback, pUserData);
33339  }
33340  ma_mutex_unlock(&pContext->deviceEnumLock);
33341 
33342  return result;
33343 }
33344 
33345 
33346 static ma_bool32 ma_context_get_devices__enum_callback(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData)
33347 {
33348  /*
33349  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
33350  it's just appended to the end. If it's a playback device it's inserted just before the first capture device.
33351  */
33352 
33353  /*
33354  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
33355  simple fixed size increment for buffer expansion.
33356  */
33357  const ma_uint32 bufferExpansionCount = 2;
33358  const ma_uint32 totalDeviceInfoCount = pContext->playbackDeviceInfoCount + pContext->captureDeviceInfoCount;
33359 
33360  if (totalDeviceInfoCount >= pContext->deviceInfoCapacity) {
33361  ma_uint32 oldCapacity = pContext->deviceInfoCapacity;
33362  ma_uint32 newCapacity = oldCapacity + bufferExpansionCount;
33363  ma_device_info* pNewInfos = (ma_device_info*)ma__realloc_from_callbacks(pContext->pDeviceInfos, sizeof(*pContext->pDeviceInfos)*newCapacity, sizeof(*pContext->pDeviceInfos)*oldCapacity, &pContext->allocationCallbacks);
33364  if (pNewInfos == NULL) {
33365  return MA_FALSE; /* Out of memory. */
33366  }
33367 
33368  pContext->pDeviceInfos = pNewInfos;
33369  pContext->deviceInfoCapacity = newCapacity;
33370  }
33371 
33372  if (deviceType == ma_device_type_playback) {
33373  /* Playback. Insert just before the first capture device. */
33374 
33375  /* The first thing to do is move all of the capture devices down a slot. */
33376  ma_uint32 iFirstCaptureDevice = pContext->playbackDeviceInfoCount;
33377  size_t iCaptureDevice;
33378  for (iCaptureDevice = totalDeviceInfoCount; iCaptureDevice > iFirstCaptureDevice; --iCaptureDevice) {
33379  pContext->pDeviceInfos[iCaptureDevice] = pContext->pDeviceInfos[iCaptureDevice-1];
33380  }
33381 
33382  /* Now just insert where the first capture device was before moving it down a slot. */
33383  pContext->pDeviceInfos[iFirstCaptureDevice] = *pInfo;
33384  pContext->playbackDeviceInfoCount += 1;
33385  } else {
33386  /* Capture. Insert at the end. */
33387  pContext->pDeviceInfos[totalDeviceInfoCount] = *pInfo;
33388  pContext->captureDeviceInfoCount += 1;
33389  }
33390 
33391  (void)pUserData;
33392  return MA_TRUE;
33393 }
33394 
33395 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)
33396 {
33397  ma_result result;
33398 
33399  /* Safety. */
33400  if (ppPlaybackDeviceInfos != NULL) *ppPlaybackDeviceInfos = NULL;
33401  if (pPlaybackDeviceCount != NULL) *pPlaybackDeviceCount = 0;
33402  if (ppCaptureDeviceInfos != NULL) *ppCaptureDeviceInfos = NULL;
33403  if (pCaptureDeviceCount != NULL) *pCaptureDeviceCount = 0;
33404 
33405  if (pContext == NULL) {
33406  return MA_INVALID_ARGS;
33407  }
33408 
33409  if (pContext->callbacks.onContextEnumerateDevices == NULL) {
33410  return MA_INVALID_OPERATION;
33411  }
33412 
33413  /* Note that we don't use ma_context_enumerate_devices() here because we want to do locking at a higher level. */
33414  ma_mutex_lock(&pContext->deviceEnumLock);
33415  {
33416  /* Reset everything first. */
33417  pContext->playbackDeviceInfoCount = 0;
33418  pContext->captureDeviceInfoCount = 0;
33419 
33420  /* Now enumerate over available devices. */
33422  if (result == MA_SUCCESS) {
33423  /* Playback devices. */
33424  if (ppPlaybackDeviceInfos != NULL) {
33425  *ppPlaybackDeviceInfos = pContext->pDeviceInfos;
33426  }
33427  if (pPlaybackDeviceCount != NULL) {
33428  *pPlaybackDeviceCount = pContext->playbackDeviceInfoCount;
33429  }
33430 
33431  /* Capture devices. */
33432  if (ppCaptureDeviceInfos != NULL) {
33433  *ppCaptureDeviceInfos = pContext->pDeviceInfos + pContext->playbackDeviceInfoCount; /* Capture devices come after playback devices. */
33434  }
33435  if (pCaptureDeviceCount != NULL) {
33436  *pCaptureDeviceCount = pContext->captureDeviceInfoCount;
33437  }
33438  }
33439  }
33440  ma_mutex_unlock(&pContext->deviceEnumLock);
33441 
33442  return result;
33443 }
33444 
33445 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)
33446 {
33447  ma_result result;
33448  ma_device_info deviceInfo;
33449 
33450  (void)shareMode; /* Unused. This parameter will be removed in version 0.11. */
33451 
33452  /* NOTE: Do not clear pDeviceInfo on entry. The reason is the pDeviceID may actually point to pDeviceInfo->id which will break things. */
33453  if (pContext == NULL || pDeviceInfo == NULL) {
33454  return MA_INVALID_ARGS;
33455  }
33456 
33457  MA_ZERO_OBJECT(&deviceInfo);
33458 
33459  /* Help the backend out by copying over the device ID if we have one. */
33460  if (pDeviceID != NULL) {
33461  MA_COPY_MEMORY(&deviceInfo.id, pDeviceID, sizeof(*pDeviceID));
33462  }
33463 
33464  if (pContext->callbacks.onContextGetDeviceInfo == NULL) {
33465  return MA_INVALID_OPERATION;
33466  }
33467 
33468  ma_mutex_lock(&pContext->deviceInfoLock);
33469  {
33470  result = pContext->callbacks.onContextGetDeviceInfo(pContext, deviceType, pDeviceID, &deviceInfo);
33471  }
33472  ma_mutex_unlock(&pContext->deviceInfoLock);
33473 
33474  /*
33475  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
33476  the future when all backends have implemented the new device info system.
33477  */
33478  if (deviceInfo.nativeDataFormatCount > 0) {
33479  ma_uint32 iNativeFormat;
33480  ma_uint32 iSampleFormat;
33481 
33482  deviceInfo.minChannels = 0xFFFFFFFF;
33483  deviceInfo.maxChannels = 0;
33484  deviceInfo.minSampleRate = 0xFFFFFFFF;
33485  deviceInfo.maxSampleRate = 0;
33486 
33487  for (iNativeFormat = 0; iNativeFormat < deviceInfo.nativeDataFormatCount; iNativeFormat += 1) {
33488  /* Formats. */
33489  if (deviceInfo.nativeDataFormats[iNativeFormat].format == ma_format_unknown) {
33490  /* All formats are supported. */
33491  deviceInfo.formats[0] = ma_format_u8;
33492  deviceInfo.formats[1] = ma_format_s16;
33493  deviceInfo.formats[2] = ma_format_s24;
33494  deviceInfo.formats[3] = ma_format_s32;
33495  deviceInfo.formats[4] = ma_format_f32;
33496  deviceInfo.formatCount = 5;
33497  } else {
33498  /* Make sure the format isn't already in the list. If so, skip. */
33499  ma_bool32 alreadyExists = MA_FALSE;
33500  for (iSampleFormat = 0; iSampleFormat < deviceInfo.formatCount; iSampleFormat += 1) {
33501  if (deviceInfo.formats[iSampleFormat] == deviceInfo.nativeDataFormats[iNativeFormat].format) {
33502  alreadyExists = MA_TRUE;
33503  break;
33504  }
33505  }
33506 
33507  if (!alreadyExists) {
33508  deviceInfo.formats[deviceInfo.formatCount++] = deviceInfo.nativeDataFormats[iNativeFormat].format;
33509  }
33510  }
33511 
33512  /* Channels. */
33513  if (deviceInfo.nativeDataFormats[iNativeFormat].channels == 0) {
33514  /* All channels supported. */
33515  deviceInfo.minChannels = MA_MIN_CHANNELS;
33516  deviceInfo.maxChannels = MA_MAX_CHANNELS;
33517  } else {
33518  if (deviceInfo.minChannels > deviceInfo.nativeDataFormats[iNativeFormat].channels) {
33519  deviceInfo.minChannels = deviceInfo.nativeDataFormats[iNativeFormat].channels;
33520  }
33521  if (deviceInfo.maxChannels < deviceInfo.nativeDataFormats[iNativeFormat].channels) {
33522  deviceInfo.maxChannels = deviceInfo.nativeDataFormats[iNativeFormat].channels;
33523  }
33524  }
33525 
33526  /* Sample rate. */
33527  if (deviceInfo.nativeDataFormats[iNativeFormat].sampleRate == 0) {
33528  /* All sample rates supported. */
33529  deviceInfo.minSampleRate = (ma_uint32)ma_standard_sample_rate_min;
33530  deviceInfo.maxSampleRate = (ma_uint32)ma_standard_sample_rate_max;
33531  } else {
33532  if (deviceInfo.minSampleRate > deviceInfo.nativeDataFormats[iNativeFormat].sampleRate) {
33533  deviceInfo.minSampleRate = deviceInfo.nativeDataFormats[iNativeFormat].sampleRate;
33534  }
33535  if (deviceInfo.maxSampleRate < deviceInfo.nativeDataFormats[iNativeFormat].sampleRate) {
33536  deviceInfo.maxSampleRate = deviceInfo.nativeDataFormats[iNativeFormat].sampleRate;
33537  }
33538  }
33539  }
33540  }
33541 
33542 
33543  /* Clamp ranges. */
33544  deviceInfo.minChannels = ma_max(deviceInfo.minChannels, MA_MIN_CHANNELS);
33545  deviceInfo.maxChannels = ma_min(deviceInfo.maxChannels, MA_MAX_CHANNELS);
33548 
33549  *pDeviceInfo = deviceInfo;
33550  return result;
33551 }
33552 
33554 {
33555  if (pContext == NULL) {
33556  return MA_FALSE;
33557  }
33558 
33559  return ma_is_loopback_supported(pContext->backend);
33560 }
33561 
33562 
33564 {
33567  config.deviceType = deviceType;
33568 
33569  /* Resampling defaults. We must never use the Speex backend by default because it uses licensed third party code. */
33570  config.resampling.algorithm = ma_resample_algorithm_linear;
33571  config.resampling.linear.lpfOrder = ma_min(MA_DEFAULT_RESAMPLER_LPF_ORDER, MA_MAX_FILTER_ORDER);
33572  config.resampling.speex.quality = 3;
33573 
33574  return config;
33575 }
33576 
33577 MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice)
33578 {
33579  ma_result result;
33580  ma_device_descriptor descriptorPlayback;
33581  ma_device_descriptor descriptorCapture;
33582 
33583  /* The context can be null, in which case we self-manage it. */
33584  if (pContext == NULL) {
33585  return ma_device_init_ex(NULL, 0, NULL, pConfig, pDevice);
33586  }
33587 
33588  if (pDevice == NULL) {
33589  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid arguments (pDevice == NULL).", MA_INVALID_ARGS);
33590  }
33591 
33592  MA_ZERO_OBJECT(pDevice);
33593 
33594  if (pConfig == NULL) {
33595  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid arguments (pConfig == NULL).", MA_INVALID_ARGS);
33596  }
33597 
33598 
33599  /* Check that we have our callbacks defined. */
33600  if (pContext->callbacks.onDeviceInit == NULL) {
33601  return MA_INVALID_OPERATION;
33602  }
33603 
33604 
33605  /* Basic config validation. */
33607  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);
33608  }
33609 
33610  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
33611  if (pConfig->capture.channels > MA_MAX_CHANNELS) {
33612  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);
33613  }
33614  if (!ma__is_channel_map_valid(pConfig->capture.channelMap, pConfig->capture.channels)) {
33615  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);
33616  }
33617  }
33618 
33620  if (pConfig->playback.channels > MA_MAX_CHANNELS) {
33621  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);
33622  }
33623  if (!ma__is_channel_map_valid(pConfig->playback.channelMap, pConfig->playback.channels)) {
33624  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);
33625  }
33626  }
33627 
33628  pDevice->pContext = pContext;
33629 
33630  /* Set the user data and log callback ASAP to ensure it is available for the entire initialization process. */
33631  pDevice->pUserData = pConfig->pUserData;
33632  pDevice->onData = pConfig->dataCallback;
33633  pDevice->onStop = pConfig->stopCallback;
33634 
33635  if (((ma_uintptr)pDevice % sizeof(pDevice)) != 0) {
33636  if (pContext->logCallback) {
33637  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.");
33638  }
33639  }
33640 
33641  if (pConfig->playback.pDeviceID != NULL) {
33642  MA_COPY_MEMORY(&pDevice->playback.id, pConfig->playback.pDeviceID, sizeof(pDevice->playback.id));
33643  }
33644 
33645  if (pConfig->capture.pDeviceID != NULL) {
33646  MA_COPY_MEMORY(&pDevice->capture.id, pConfig->capture.pDeviceID, sizeof(pDevice->capture.id));
33647  }
33648 
33650  pDevice->noClip = pConfig->noClip;
33651  pDevice->masterVolumeFactor = 1;
33652 
33653  pDevice->type = pConfig->deviceType;
33654  pDevice->sampleRate = pConfig->sampleRate;
33655  pDevice->resampling.algorithm = pConfig->resampling.algorithm;
33656  pDevice->resampling.linear.lpfOrder = pConfig->resampling.linear.lpfOrder;
33657  pDevice->resampling.speex.quality = pConfig->resampling.speex.quality;
33658 
33659  pDevice->capture.shareMode = pConfig->capture.shareMode;
33660  pDevice->capture.format = pConfig->capture.format;
33661  pDevice->capture.channels = pConfig->capture.channels;
33663  pDevice->capture.channelMixMode = pConfig->capture.channelMixMode;
33664 
33665  pDevice->playback.shareMode = pConfig->playback.shareMode;
33666  pDevice->playback.format = pConfig->playback.format;
33667  pDevice->playback.channels = pConfig->playback.channels;
33669  pDevice->playback.channelMixMode = pConfig->playback.channelMixMode;
33670 
33671 
33672  result = ma_mutex_init(&pDevice->startStopLock);
33673  if (result != MA_SUCCESS) {
33674  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create mutex.", result);
33675  }
33676 
33677  /*
33678  When the device is started, the worker thread is the one that does the actual startup of the backend device. We
33679  use a semaphore to wait for the background thread to finish the work. The same applies for stopping the device.
33680 
33681  Each of these semaphores is released internally by the worker thread when the work is completed. The start
33682  semaphore is also used to wake up the worker thread.
33683  */
33684  result = ma_event_init(&pDevice->wakeupEvent);
33685  if (result != MA_SUCCESS) {
33686  ma_mutex_uninit(&pDevice->startStopLock);
33687  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread wakeup event.", result);
33688  }
33689 
33690  result = ma_event_init(&pDevice->startEvent);
33691  if (result != MA_SUCCESS) {
33692  ma_event_uninit(&pDevice->wakeupEvent);
33693  ma_mutex_uninit(&pDevice->startStopLock);
33694  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread start event.", result);
33695  }
33696 
33697  result = ma_event_init(&pDevice->stopEvent);
33698  if (result != MA_SUCCESS) {
33699  ma_event_uninit(&pDevice->startEvent);
33700  ma_event_uninit(&pDevice->wakeupEvent);
33701  ma_mutex_uninit(&pDevice->startStopLock);
33702  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread stop event.", result);
33703  }
33704 
33705 
33706  MA_ZERO_OBJECT(&descriptorPlayback);
33707  descriptorPlayback.pDeviceID = pConfig->playback.pDeviceID;
33708  descriptorPlayback.shareMode = pConfig->playback.shareMode;
33709  descriptorPlayback.format = pConfig->playback.format;
33710  descriptorPlayback.channels = pConfig->playback.channels;
33711  descriptorPlayback.sampleRate = pConfig->sampleRate;
33712  ma_channel_map_copy(descriptorPlayback.channelMap, pConfig->playback.channelMap, pConfig->playback.channels);
33713  descriptorPlayback.periodSizeInFrames = pConfig->periodSizeInFrames;
33714  descriptorPlayback.periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
33715  descriptorPlayback.periodCount = pConfig->periods;
33716 
33717  if (descriptorPlayback.periodCount == 0) {
33718  descriptorPlayback.periodCount = MA_DEFAULT_PERIODS;
33719  }
33720 
33721 
33722  MA_ZERO_OBJECT(&descriptorCapture);
33723  descriptorCapture.pDeviceID = pConfig->capture.pDeviceID;
33724  descriptorCapture.shareMode = pConfig->capture.shareMode;
33725  descriptorCapture.format = pConfig->capture.format;
33726  descriptorCapture.channels = pConfig->capture.channels;
33727  descriptorCapture.sampleRate = pConfig->sampleRate;
33728  ma_channel_map_copy(descriptorCapture.channelMap, pConfig->capture.channelMap, pConfig->capture.channels);
33729  descriptorCapture.periodSizeInFrames = pConfig->periodSizeInFrames;
33730  descriptorCapture.periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
33731  descriptorCapture.periodCount = pConfig->periods;
33732 
33733  if (descriptorCapture.periodCount == 0) {
33734  descriptorCapture.periodCount = MA_DEFAULT_PERIODS;
33735  }
33736 
33737 
33738  result = pContext->callbacks.onDeviceInit(pDevice, pConfig, &descriptorPlayback, &descriptorCapture);
33739  if (result != MA_SUCCESS) {
33740  ma_event_uninit(&pDevice->startEvent);
33741  ma_event_uninit(&pDevice->wakeupEvent);
33742  ma_mutex_uninit(&pDevice->startStopLock);
33743  return result;
33744  }
33745 
33746 
33747  /*
33748  On output the descriptors will contain the *actual* data format of the device. We need this to know how to convert the data between
33749  the requested format and the internal format.
33750  */
33752  if (!ma_device_descriptor_is_valid(&descriptorCapture)) {
33753  ma_device_uninit(pDevice);
33754  return MA_INVALID_ARGS;
33755  }
33756 
33757  pDevice->capture.internalFormat = descriptorCapture.format;
33758  pDevice->capture.internalChannels = descriptorCapture.channels;
33759  pDevice->capture.internalSampleRate = descriptorCapture.sampleRate;
33760  ma_channel_map_copy(pDevice->capture.internalChannelMap, descriptorCapture.channelMap, descriptorCapture.channels);
33761  pDevice->capture.internalPeriodSizeInFrames = descriptorCapture.periodSizeInFrames;
33762  pDevice->capture.internalPeriods = descriptorCapture.periodCount;
33763 
33764  if (pDevice->capture.internalPeriodSizeInFrames == 0) {
33766  }
33767  }
33768 
33769  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
33770  if (!ma_device_descriptor_is_valid(&descriptorPlayback)) {
33771  ma_device_uninit(pDevice);
33772  return MA_INVALID_ARGS;
33773  }
33774 
33775  pDevice->playback.internalFormat = descriptorPlayback.format;
33776  pDevice->playback.internalChannels = descriptorPlayback.channels;
33777  pDevice->playback.internalSampleRate = descriptorPlayback.sampleRate;
33778  ma_channel_map_copy(pDevice->playback.internalChannelMap, descriptorPlayback.channelMap, descriptorPlayback.channels);
33779  pDevice->playback.internalPeriodSizeInFrames = descriptorPlayback.periodSizeInFrames;
33780  pDevice->playback.internalPeriods = descriptorPlayback.periodCount;
33781 
33782  if (pDevice->playback.internalPeriodSizeInFrames == 0) {
33784  }
33785  }
33786 
33787 
33788  /*
33789  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.
33790  For loopback devices, we need to retrieve the name of the playback device.
33791  */
33792  {
33793  ma_device_info deviceInfo;
33794 
33796  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);
33797  if (result == MA_SUCCESS) {
33798  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), deviceInfo.name, (size_t)-1);
33799  } else {
33800  /* We failed to retrieve the device info. Fall back to a default name. */
33801  if (descriptorCapture.pDeviceID == NULL) {
33802  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
33803  } else {
33804  ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), "Capture Device", (size_t)-1);
33805  }
33806  }
33807  }
33808 
33809  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
33810  result = ma_context_get_device_info(pContext, ma_device_type_playback, descriptorPlayback.pDeviceID, descriptorPlayback.shareMode, &deviceInfo);
33811  if (result == MA_SUCCESS) {
33812  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), deviceInfo.name, (size_t)-1);
33813  } else {
33814  /* We failed to retrieve the device info. Fall back to a default name. */
33815  if (descriptorPlayback.pDeviceID == NULL) {
33816  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
33817  } else {
33818  ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), "Playback Device", (size_t)-1);
33819  }
33820  }
33821  }
33822  }
33823 
33824 
33825  ma_device__post_init_setup(pDevice, pConfig->deviceType);
33826 
33827 
33828  /* Some backends don't require the worker thread. */
33829  if (!ma_context_is_backend_asynchronous(pContext)) {
33830  /* The worker thread. */
33831  result = ma_thread_create(&pDevice->thread, pContext->threadPriority, pContext->threadStackSize, ma_worker_thread, pDevice, &pContext->allocationCallbacks);
33832  if (result != MA_SUCCESS) {
33833  ma_device_uninit(pDevice);
33834  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread.", result);
33835  }
33836 
33837  /* Wait for the worker thread to put the device into it's stopped state for real. */
33838  ma_event_wait(&pDevice->stopEvent);
33840  } else {
33841  /*
33842  If the backend is asynchronous and the device is duplex, we'll need an intermediary ring buffer. Note that this needs to be done
33843  after ma_device__post_init_setup().
33844  */
33845  if (ma_context_is_backend_asynchronous(pContext)) {
33846  if (pConfig->deviceType == ma_device_type_duplex) {
33847  result = ma_duplex_rb_init(pDevice->capture.format, pDevice->capture.channels, pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalPeriodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->duplexRB);
33848  if (result != MA_SUCCESS) {
33849  ma_device_uninit(pDevice);
33850  return result;
33851  }
33852  }
33853  }
33854 
33856  }
33857 
33858 
33860  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
33861  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", pDevice->capture.name, "Capture");
33863  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channels: %d -> %d\n", pDevice->capture.internalChannels, pDevice->capture.channels);
33864  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Sample Rate: %d -> %d\n", pDevice->capture.internalSampleRate, pDevice->sampleRate);
33866  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Conversion:\n");
33867  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Pre Format Conversion: %s\n", pDevice->capture.converter.hasPreFormatConversion ? "YES" : "NO");
33868  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Post Format Conversion: %s\n", pDevice->capture.converter.hasPostFormatConversion ? "YES" : "NO");
33869  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Routing: %s\n", pDevice->capture.converter.hasChannelConverter ? "YES" : "NO");
33870  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s\n", pDevice->capture.converter.hasResampler ? "YES" : "NO");
33871  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s\n", pDevice->capture.converter.isPassthrough ? "YES" : "NO");
33872  }
33873  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
33874  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", pDevice->playback.name, "Playback");
33876  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channels: %d -> %d\n", pDevice->playback.channels, pDevice->playback.internalChannels);
33877  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->playback.internalSampleRate);
33879  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Conversion:\n");
33880  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Pre Format Conversion: %s\n", pDevice->playback.converter.hasPreFormatConversion ? "YES" : "NO");
33881  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Post Format Conversion: %s\n", pDevice->playback.converter.hasPostFormatConversion ? "YES" : "NO");
33882  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Routing: %s\n", pDevice->playback.converter.hasChannelConverter ? "YES" : "NO");
33883  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s\n", pDevice->playback.converter.hasResampler ? "YES" : "NO");
33884  ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s\n", pDevice->playback.converter.isPassthrough ? "YES" : "NO");
33885  }
33886 
33888  return MA_SUCCESS;
33889 }
33890 
33891 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)
33892 {
33893  ma_result result;
33894  ma_context* pContext;
33895  ma_backend defaultBackends[ma_backend_null+1];
33896  ma_uint32 iBackend;
33897  ma_backend* pBackendsToIterate;
33898  ma_uint32 backendsToIterateCount;
33899  ma_allocation_callbacks allocationCallbacks;
33900 
33901  if (pConfig == NULL) {
33902  return MA_INVALID_ARGS;
33903  }
33904 
33905  if (pContextConfig != NULL) {
33906  result = ma_allocation_callbacks_init_copy(&allocationCallbacks, &pContextConfig->allocationCallbacks);
33907  if (result != MA_SUCCESS) {
33908  return result;
33909  }
33910  } else {
33911  allocationCallbacks = ma_allocation_callbacks_init_default();
33912  }
33913 
33914 
33915  pContext = (ma_context*)ma__malloc_from_callbacks(sizeof(*pContext), &allocationCallbacks);
33916  if (pContext == NULL) {
33917  return MA_OUT_OF_MEMORY;
33918  }
33919 
33920  for (iBackend = 0; iBackend <= ma_backend_null; ++iBackend) {
33921  defaultBackends[iBackend] = (ma_backend)iBackend;
33922  }
33923 
33924  pBackendsToIterate = (ma_backend*)backends;
33925  backendsToIterateCount = backendCount;
33926  if (pBackendsToIterate == NULL) {
33927  pBackendsToIterate = (ma_backend*)defaultBackends;
33928  backendsToIterateCount = ma_countof(defaultBackends);
33929  }
33930 
33931  result = MA_NO_BACKEND;
33932 
33933  for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
33934  result = ma_context_init(&pBackendsToIterate[iBackend], 1, pContextConfig, pContext);
33935  if (result == MA_SUCCESS) {
33936  result = ma_device_init(pContext, pConfig, pDevice);
33937  if (result == MA_SUCCESS) {
33938  break; /* Success. */
33939  } else {
33940  ma_context_uninit(pContext); /* Failure. */
33941  }
33942  }
33943  }
33944 
33945  if (result != MA_SUCCESS) {
33946  ma__free_from_callbacks(pContext, &allocationCallbacks);
33947  return result;
33948  }
33949 
33950  pDevice->isOwnerOfContext = MA_TRUE;
33951  return result;
33952 }
33953 
33954 MA_API void ma_device_uninit(ma_device* pDevice)
33955 {
33956  if (!ma_device__is_initialized(pDevice)) {
33957  return;
33958  }
33959 
33960  /* 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. */
33961  if (ma_device_is_started(pDevice)) {
33962  ma_device_stop(pDevice);
33963  }
33964 
33965  /* Putting the device into an uninitialized state will make the worker thread return. */
33967 
33968  /* Wake up the worker thread and wait for it to properly terminate. */
33970  ma_event_signal(&pDevice->wakeupEvent);
33971  ma_thread_wait(&pDevice->thread);
33972  }
33973 
33974  if (pDevice->pContext->callbacks.onDeviceUninit != NULL) {
33975  pDevice->pContext->callbacks.onDeviceUninit(pDevice);
33976  }
33977 
33978 
33979  ma_event_uninit(&pDevice->stopEvent);
33980  ma_event_uninit(&pDevice->startEvent);
33981  ma_event_uninit(&pDevice->wakeupEvent);
33982  ma_mutex_uninit(&pDevice->startStopLock);
33983 
33985  if (pDevice->type == ma_device_type_duplex) {
33986  ma_duplex_rb_uninit(&pDevice->duplexRB);
33987  }
33988  }
33989 
33990  if (pDevice->isOwnerOfContext) {
33991  ma_allocation_callbacks allocationCallbacks = pDevice->pContext->allocationCallbacks;
33992 
33993  ma_context_uninit(pDevice->pContext);
33994  ma__free_from_callbacks(pDevice->pContext, &allocationCallbacks);
33995  }
33996 
33997  MA_ZERO_OBJECT(pDevice);
33998 }
33999 
34001 {
34002  if (pDevice == NULL) {
34003  return NULL;
34004  }
34005 
34006  return pDevice->pContext;
34007 }
34008 
34010 {
34011  return ma_context_get_log(ma_device_get_context(pDevice));
34012 }
34013 
34015 {
34016  ma_result result;
34017 
34018  if (pDevice == NULL) {
34019  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_start() called with invalid arguments (pDevice == NULL).", MA_INVALID_ARGS);
34020  }
34021 
34022  if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
34023  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_start() called for an uninitialized device.", MA_DEVICE_NOT_INITIALIZED);
34024  }
34025 
34026  if (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
34027  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. */
34028  }
34029 
34030  ma_mutex_lock(&pDevice->startStopLock);
34031  {
34032  /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
34034 
34036 
34037  /* Asynchronous backends need to be handled differently. */
34039  if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
34040  result = pDevice->pContext->callbacks.onDeviceStart(pDevice);
34041  } else {
34042  result = MA_INVALID_OPERATION;
34043  }
34044 
34045  if (result == MA_SUCCESS) {
34047  }
34048  } else {
34049  /*
34050  Synchronous backends are started by signaling an event that's being waited on in the worker thread. We first wake up the
34051  thread and then wait for the start event.
34052  */
34053  ma_event_signal(&pDevice->wakeupEvent);
34054 
34055  /*
34056  Wait for the worker thread to finish starting the device. Note that the worker thread will be the one who puts the device
34057  into the started state. Don't call ma_device__set_state() here.
34058  */
34059  ma_event_wait(&pDevice->startEvent);
34060  result = pDevice->workResult;
34061  }
34062 
34063  /* We changed the state from stopped to started, so if we failed, make sure we put the state back to stopped. */
34064  if (result != MA_SUCCESS) {
34066  }
34067  }
34068  ma_mutex_unlock(&pDevice->startStopLock);
34069 
34070  return result;
34071 }
34072 
34074 {
34075  ma_result result;
34076 
34077  if (pDevice == NULL) {
34078  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_stop() called with invalid arguments (pDevice == NULL).", MA_INVALID_ARGS);
34079  }
34080 
34081  if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
34082  return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "ma_device_stop() called for an uninitialized device.", MA_DEVICE_NOT_INITIALIZED);
34083  }
34084 
34085  if (ma_device_get_state(pDevice) == MA_STATE_STOPPED) {
34086  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. */
34087  }
34088 
34089  ma_mutex_lock(&pDevice->startStopLock);
34090  {
34091  /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */
34093 
34095 
34096  /* Asynchronous backends need to be handled differently. */
34098  /* Asynchronous backends must have a stop operation. */
34099  if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
34100  result = pDevice->pContext->callbacks.onDeviceStop(pDevice);
34101  } else {
34102  result = MA_INVALID_OPERATION;
34103  }
34104 
34106  } else {
34107  /*
34108  Synchronous backends. The stop callback is always called from the worker thread. Do not call the stop callback here. If
34109  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
34110  sure the state of the device is *not* playing right now, which it shouldn't be since we set it above. This is super
34111  important though, so I'm asserting it here as well for extra safety in case we accidentally change something later.
34112  */
34114 
34115  if (pDevice->pContext->callbacks.onDeviceDataLoopWakeup != NULL) {
34116  pDevice->pContext->callbacks.onDeviceDataLoopWakeup(pDevice);
34117  }
34118 
34119  /*
34120  We need to wait for the worker thread to become available for work before returning. Note that the worker thread will be
34121  the one who puts the device into the stopped state. Don't call ma_device__set_state() here.
34122  */
34123  ma_event_wait(&pDevice->stopEvent);
34124  result = MA_SUCCESS;
34125  }
34126  }
34127  ma_mutex_unlock(&pDevice->startStopLock);
34128 
34129  return result;
34130 }
34131 
34133 {
34134  return ma_device_get_state(pDevice) == MA_STATE_STARTED;
34135 }
34136 
34138 {
34139  if (pDevice == NULL) {
34140  return MA_STATE_UNINITIALIZED;
34141  }
34142 
34143  return c89atomic_load_32((ma_uint32*)&pDevice->state); /* Naughty cast to get rid of a const warning. */
34144 }
34145 
34146 MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume)
34147 {
34148  if (pDevice == NULL) {
34149  return MA_INVALID_ARGS;
34150  }
34151 
34152  if (volume < 0.0f || volume > 1.0f) {
34153  return MA_INVALID_ARGS;
34154  }
34155 
34156  c89atomic_exchange_f32(&pDevice->masterVolumeFactor, volume);
34157 
34158  return MA_SUCCESS;
34159 }
34160 
34161 MA_API ma_result ma_device_get_master_volume(ma_device* pDevice, float* pVolume)
34162 {
34163  if (pVolume == NULL) {
34164  return MA_INVALID_ARGS;
34165  }
34166 
34167  if (pDevice == NULL) {
34168  *pVolume = 0;
34169  return MA_INVALID_ARGS;
34170  }
34171 
34172  *pVolume = c89atomic_load_f32(&pDevice->masterVolumeFactor);
34173 
34174  return MA_SUCCESS;
34175 }
34176 
34178 {
34179  if (gainDB > 0) {
34180  return MA_INVALID_ARGS;
34181  }
34182 
34183  return ma_device_set_master_volume(pDevice, ma_gain_db_to_factor(gainDB));
34184 }
34185 
34186 MA_API ma_result ma_device_get_master_gain_db(ma_device* pDevice, float* pGainDB)
34187 {
34188  float factor;
34189  ma_result result;
34190 
34191  if (pGainDB == NULL) {
34192  return MA_INVALID_ARGS;
34193  }
34194 
34195  result = ma_device_get_master_volume(pDevice, &factor);
34196  if (result != MA_SUCCESS) {
34197  *pGainDB = 0;
34198  return result;
34199  }
34200 
34201  *pGainDB = ma_factor_to_gain_db(factor);
34202 
34203  return MA_SUCCESS;
34204 }
34205 
34206 
34207 MA_API ma_result ma_device_handle_backend_data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
34208 {
34209  if (pDevice == NULL) {
34210  return MA_INVALID_ARGS;
34211  }
34212 
34213  if (pOutput == NULL && pInput == NULL) {
34214  return MA_INVALID_ARGS;
34215  }
34216 
34217  if (pDevice->type == ma_device_type_duplex) {
34218  if (pInput != NULL) {
34219  ma_device__handle_duplex_callback_capture(pDevice, frameCount, pInput, &pDevice->duplexRB.rb);
34220  }
34221 
34222  if (pOutput != NULL) {
34223  ma_device__handle_duplex_callback_playback(pDevice, frameCount, pOutput, &pDevice->duplexRB.rb);
34224  }
34225  } else {
34226  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_loopback) {
34227  if (pInput == NULL) {
34228  return MA_INVALID_ARGS;
34229  }
34230 
34231  ma_device__send_frames_to_client(pDevice, frameCount, pInput);
34232  }
34233 
34234  if (pDevice->type == ma_device_type_playback) {
34235  if (pOutput == NULL) {
34236  return MA_INVALID_ARGS;
34237  }
34238 
34239  ma_device__read_frames_from_client(pDevice, frameCount, pOutput);
34240  }
34241  }
34242 
34243  return MA_SUCCESS;
34244 }
34245 
34247 {
34248  if (pDescriptor == NULL) {
34249  return 0;
34250  }
34251 
34252  /*
34253  We must have a non-0 native sample rate, but some backends don't allow retrieval of this at the
34254  time when the size of the buffer needs to be determined. In this case we need to just take a best
34255  guess and move on. We'll try using the sample rate in pDescriptor first. If that's not set we'll
34256  just fall back to MA_DEFAULT_SAMPLE_RATE.
34257  */
34258  if (nativeSampleRate == 0) {
34259  nativeSampleRate = pDescriptor->sampleRate;
34260  }
34261  if (nativeSampleRate == 0) {
34262  nativeSampleRate = MA_DEFAULT_SAMPLE_RATE;
34263  }
34264 
34265  MA_ASSERT(nativeSampleRate != 0);
34266 
34267  if (pDescriptor->periodSizeInFrames == 0) {
34268  if (pDescriptor->periodSizeInMilliseconds == 0) {
34269  if (performanceProfile == ma_performance_profile_low_latency) {
34271  } else {
34273  }
34274  } else {
34276  }
34277  } else {
34278  return pDescriptor->periodSizeInFrames;
34279  }
34280 }
34281 #endif /* MA_NO_DEVICE_IO */
34282 
34283 
34284 MA_API ma_uint32 ma_scale_buffer_size(ma_uint32 baseBufferSize, float scale)
34285 {
34286  return ma_max(1, (ma_uint32)(baseBufferSize*scale));
34287 }
34288 
34290 {
34291  /* Prevent a division by zero. */
34292  if (sampleRate == 0) {
34293  return 0;
34294  }
34295 
34296  return bufferSizeInFrames*1000 / sampleRate;
34297 }
34298 
34300 {
34301  /* Prevent a division by zero. */
34302  if (sampleRate == 0) {
34303  return 0;
34304  }
34305 
34306  return bufferSizeInMilliseconds*sampleRate / 1000;
34307 }
34308 
34309 MA_API void ma_copy_pcm_frames(void* dst, const void* src, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
34310 {
34311  if (dst == src) {
34312  return; /* No-op. */
34313  }
34314 
34315  ma_copy_memory_64(dst, src, frameCount * ma_get_bytes_per_frame(format, channels));
34316 }
34317 
34318 MA_API void ma_silence_pcm_frames(void* p, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
34319 {
34320  if (format == ma_format_u8) {
34321  ma_uint64 sampleCount = frameCount * channels;
34322  ma_uint64 iSample;
34323  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34324  ((ma_uint8*)p)[iSample] = 128;
34325  }
34326  } else {
34327  ma_zero_memory_64(p, frameCount * ma_get_bytes_per_frame(format, channels));
34328  }
34329 }
34330 
34331 MA_API void* ma_offset_pcm_frames_ptr(void* p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels)
34332 {
34333  return ma_offset_ptr(p, offsetInFrames * ma_get_bytes_per_frame(format, channels));
34334 }
34335 
34336 MA_API const void* ma_offset_pcm_frames_const_ptr(const void* p, ma_uint64 offsetInFrames, ma_format format, ma_uint32 channels)
34337 {
34338  return ma_offset_ptr(p, offsetInFrames * ma_get_bytes_per_frame(format, channels));
34339 }
34340 
34341 
34342 MA_API void ma_clip_samples_f32(float* p, ma_uint64 sampleCount)
34343 {
34344  ma_uint32 iSample;
34345 
34346  /* TODO: Research a branchless SSE implementation. */
34347  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34348  p[iSample] = ma_clip_f32(p[iSample]);
34349  }
34350 }
34351 
34352 
34353 MA_API void ma_copy_and_apply_volume_factor_u8(ma_uint8* pSamplesOut, const ma_uint8* pSamplesIn, ma_uint64 sampleCount, float factor)
34354 {
34355  ma_uint64 iSample;
34356 
34357  if (pSamplesOut == NULL || pSamplesIn == NULL) {
34358  return;
34359  }
34360 
34361  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34362  pSamplesOut[iSample] = (ma_uint8)(pSamplesIn[iSample] * factor);
34363  }
34364 }
34365 
34366 MA_API void ma_copy_and_apply_volume_factor_s16(ma_int16* pSamplesOut, const ma_int16* pSamplesIn, ma_uint64 sampleCount, float factor)
34367 {
34368  ma_uint64 iSample;
34369 
34370  if (pSamplesOut == NULL || pSamplesIn == NULL) {
34371  return;
34372  }
34373 
34374  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34375  pSamplesOut[iSample] = (ma_int16)(pSamplesIn[iSample] * factor);
34376  }
34377 }
34378 
34379 MA_API void ma_copy_and_apply_volume_factor_s24(void* pSamplesOut, const void* pSamplesIn, ma_uint64 sampleCount, float factor)
34380 {
34381  ma_uint64 iSample;
34382  ma_uint8* pSamplesOut8;
34383  ma_uint8* pSamplesIn8;
34384 
34385  if (pSamplesOut == NULL || pSamplesIn == NULL) {
34386  return;
34387  }
34388 
34389  pSamplesOut8 = (ma_uint8*)pSamplesOut;
34390  pSamplesIn8 = (ma_uint8*)pSamplesIn;
34391 
34392  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34393  ma_int32 sampleS32;
34394 
34395  sampleS32 = (ma_int32)(((ma_uint32)(pSamplesIn8[iSample*3+0]) << 8) | ((ma_uint32)(pSamplesIn8[iSample*3+1]) << 16) | ((ma_uint32)(pSamplesIn8[iSample*3+2])) << 24);
34396  sampleS32 = (ma_int32)(sampleS32 * factor);
34397 
34398  pSamplesOut8[iSample*3+0] = (ma_uint8)(((ma_uint32)sampleS32 & 0x0000FF00) >> 8);
34399  pSamplesOut8[iSample*3+1] = (ma_uint8)(((ma_uint32)sampleS32 & 0x00FF0000) >> 16);
34400  pSamplesOut8[iSample*3+2] = (ma_uint8)(((ma_uint32)sampleS32 & 0xFF000000) >> 24);
34401  }
34402 }
34403 
34404 MA_API void ma_copy_and_apply_volume_factor_s32(ma_int32* pSamplesOut, const ma_int32* pSamplesIn, ma_uint64 sampleCount, float factor)
34405 {
34406  ma_uint64 iSample;
34407 
34408  if (pSamplesOut == NULL || pSamplesIn == NULL) {
34409  return;
34410  }
34411 
34412  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34413  pSamplesOut[iSample] = (ma_int32)(pSamplesIn[iSample] * factor);
34414  }
34415 }
34416 
34417 MA_API void ma_copy_and_apply_volume_factor_f32(float* pSamplesOut, const float* pSamplesIn, ma_uint64 sampleCount, float factor)
34418 {
34419  ma_uint64 iSample;
34420 
34421  if (pSamplesOut == NULL || pSamplesIn == NULL) {
34422  return;
34423  }
34424 
34425  for (iSample = 0; iSample < sampleCount; iSample += 1) {
34426  pSamplesOut[iSample] = pSamplesIn[iSample] * factor;
34427  }
34428 }
34429 
34430 MA_API void ma_apply_volume_factor_u8(ma_uint8* pSamples, ma_uint64 sampleCount, float factor)
34431 {
34432  ma_copy_and_apply_volume_factor_u8(pSamples, pSamples, sampleCount, factor);
34433 }
34434 
34435 MA_API void ma_apply_volume_factor_s16(ma_int16* pSamples, ma_uint64 sampleCount, float factor)
34436 {
34437  ma_copy_and_apply_volume_factor_s16(pSamples, pSamples, sampleCount, factor);
34438 }
34439 
34440 MA_API void ma_apply_volume_factor_s24(void* pSamples, ma_uint64 sampleCount, float factor)
34441 {
34442  ma_copy_and_apply_volume_factor_s24(pSamples, pSamples, sampleCount, factor);
34443 }
34444 
34445 MA_API void ma_apply_volume_factor_s32(ma_int32* pSamples, ma_uint64 sampleCount, float factor)
34446 {
34447  ma_copy_and_apply_volume_factor_s32(pSamples, pSamples, sampleCount, factor);
34448 }
34449 
34450 MA_API void ma_apply_volume_factor_f32(float* pSamples, ma_uint64 sampleCount, float factor)
34451 {
34452  ma_copy_and_apply_volume_factor_f32(pSamples, pSamples, sampleCount, factor);
34453 }
34454 
34455 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)
34456 {
34457  ma_copy_and_apply_volume_factor_u8(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
34458 }
34459 
34460 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)
34461 {
34462  ma_copy_and_apply_volume_factor_s16(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
34463 }
34464 
34465 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)
34466 {
34467  ma_copy_and_apply_volume_factor_s24(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
34468 }
34469 
34470 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)
34471 {
34472  ma_copy_and_apply_volume_factor_s32(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
34473 }
34474 
34475 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)
34476 {
34477  ma_copy_and_apply_volume_factor_f32(pPCMFramesOut, pPCMFramesIn, frameCount*channels, factor);
34478 }
34479 
34480 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)
34481 {
34482  switch (format)
34483  {
34484  case ma_format_u8: ma_copy_and_apply_volume_factor_pcm_frames_u8 ((ma_uint8*)pPCMFramesOut, (const ma_uint8*)pPCMFramesIn, frameCount, channels, factor); return;
34485  case ma_format_s16: ma_copy_and_apply_volume_factor_pcm_frames_s16((ma_int16*)pPCMFramesOut, (const ma_int16*)pPCMFramesIn, frameCount, channels, factor); return;
34486  case ma_format_s24: ma_copy_and_apply_volume_factor_pcm_frames_s24( pPCMFramesOut, pPCMFramesIn, frameCount, channels, factor); return;
34487  case ma_format_s32: ma_copy_and_apply_volume_factor_pcm_frames_s32((ma_int32*)pPCMFramesOut, (const ma_int32*)pPCMFramesIn, frameCount, channels, factor); return;
34488  case ma_format_f32: ma_copy_and_apply_volume_factor_pcm_frames_f32( (float*)pPCMFramesOut, (const float*)pPCMFramesIn, frameCount, channels, factor); return;
34489  default: return; /* Do nothing. */
34490  }
34491 }
34492 
34493 MA_API void ma_apply_volume_factor_pcm_frames_u8(ma_uint8* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
34494 {
34495  ma_copy_and_apply_volume_factor_pcm_frames_u8(pPCMFrames, pPCMFrames, frameCount, channels, factor);
34496 }
34497 
34498 MA_API void ma_apply_volume_factor_pcm_frames_s16(ma_int16* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
34499 {
34500  ma_copy_and_apply_volume_factor_pcm_frames_s16(pPCMFrames, pPCMFrames, frameCount, channels, factor);
34501 }
34502 
34503 MA_API void ma_apply_volume_factor_pcm_frames_s24(void* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
34504 {
34505  ma_copy_and_apply_volume_factor_pcm_frames_s24(pPCMFrames, pPCMFrames, frameCount, channels, factor);
34506 }
34507 
34508 MA_API void ma_apply_volume_factor_pcm_frames_s32(ma_int32* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
34509 {
34510  ma_copy_and_apply_volume_factor_pcm_frames_s32(pPCMFrames, pPCMFrames, frameCount, channels, factor);
34511 }
34512 
34513 MA_API void ma_apply_volume_factor_pcm_frames_f32(float* pPCMFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
34514 {
34515  ma_copy_and_apply_volume_factor_pcm_frames_f32(pPCMFrames, pPCMFrames, frameCount, channels, factor);
34516 }
34517 
34518 MA_API void ma_apply_volume_factor_pcm_frames(void* pPCMFrames, ma_uint64 frameCount, ma_format format, ma_uint32 channels, float factor)
34519 {
34520  ma_copy_and_apply_volume_factor_pcm_frames(pPCMFrames, pPCMFrames, frameCount, format, channels, factor);
34521 }
34522 
34523 
34524 MA_API float ma_factor_to_gain_db(float factor)
34525 {
34526  return (float)(20*ma_log10f(factor));
34527 }
34528 
34529 MA_API float ma_gain_db_to_factor(float gain)
34530 {
34531  return (float)ma_powf(10, gain/20.0f);
34532 }
34533 
34534 
34535 /**************************************************************************************************************************************************************
34536 
34537 Format Conversion
34538 
34539 **************************************************************************************************************************************************************/
34540 
34542 {
34543  return (ma_int16)(x * 32767.0f);
34544 }
34545 
34547 {
34548  return (ma_int16)((ma_int16)x - 128);
34549 }
34550 
34552 {
34553  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. */
34554 }
34555 
34557 {
34558  s24[0] = (ma_uint8)((x & 0x000000FF) >> 0);
34559  s24[1] = (ma_uint8)((x & 0x0000FF00) >> 8);
34560  s24[2] = (ma_uint8)((x & 0x00FF0000) >> 16);
34561 }
34562 
34563 
34565 {
34566  return (ma_uint8)(ma_clamp(x, -128, 127) + 128);
34567 }
34568 
34570 {
34571  return (ma_int16)ma_clamp(x, -32768, 32767);
34572 }
34573 
34575 {
34576  return (ma_int64)ma_clamp(x, -8388608, 8388607);
34577 }
34578 
34580 {
34581  /* This dance is to silence warnings with -std=c89. A good compiler should be able to optimize this away. */
34582  ma_int64 clipMin;
34583  ma_int64 clipMax;
34584  clipMin = -((ma_int64)2147483647 + 1);
34585  clipMax = (ma_int64)2147483647;
34586 
34587  return (ma_int32)ma_clamp(x, clipMin, clipMax);
34588 }
34589 
34590 
34591 /* u8 */
34592 MA_API void ma_pcm_u8_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34593 {
34594  (void)ditherMode;
34595  ma_copy_memory_64(dst, src, count * sizeof(ma_uint8));
34596 }
34597 
34598 
34599 static MA_INLINE void ma_pcm_u8_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34600 {
34601  ma_int16* dst_s16 = (ma_int16*)dst;
34602  const ma_uint8* src_u8 = (const ma_uint8*)src;
34603 
34604  ma_uint64 i;
34605  for (i = 0; i < count; i += 1) {
34606  ma_int16 x = src_u8[i];
34607  x = (ma_int16)(x - 128);
34608  x = (ma_int16)(x << 8);
34609  dst_s16[i] = x;
34610  }
34611 
34612  (void)ditherMode;
34613 }
34614 
34615 static MA_INLINE void ma_pcm_u8_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34616 {
34617  ma_pcm_u8_to_s16__reference(dst, src, count, ditherMode);
34618 }
34619 
34620 #if defined(MA_SUPPORT_SSE2)
34621 static MA_INLINE void ma_pcm_u8_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34622 {
34623  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
34624 }
34625 #endif
34626 #if defined(MA_SUPPORT_AVX2)
34627 static MA_INLINE void ma_pcm_u8_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34628 {
34629  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
34630 }
34631 #endif
34632 #if defined(MA_SUPPORT_NEON)
34633 static MA_INLINE void ma_pcm_u8_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34634 {
34635  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
34636 }
34637 #endif
34638 
34639 MA_API void ma_pcm_u8_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34640 {
34641 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34642  ma_pcm_u8_to_s16__reference(dst, src, count, ditherMode);
34643 #else
34644  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
34645  if (ma_has_avx2()) {
34646  ma_pcm_u8_to_s16__avx2(dst, src, count, ditherMode);
34647  } else
34648  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
34649  if (ma_has_sse2()) {
34650  ma_pcm_u8_to_s16__sse2(dst, src, count, ditherMode);
34651  } else
34652  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
34653  if (ma_has_neon()) {
34654  ma_pcm_u8_to_s16__neon(dst, src, count, ditherMode);
34655  } else
34656  #endif
34657  {
34658  ma_pcm_u8_to_s16__optimized(dst, src, count, ditherMode);
34659  }
34660 #endif
34661 }
34662 
34663 
34664 static MA_INLINE void ma_pcm_u8_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34665 {
34666  ma_uint8* dst_s24 = (ma_uint8*)dst;
34667  const ma_uint8* src_u8 = (const ma_uint8*)src;
34668 
34669  ma_uint64 i;
34670  for (i = 0; i < count; i += 1) {
34671  ma_int16 x = src_u8[i];
34672  x = (ma_int16)(x - 128);
34673 
34674  dst_s24[i*3+0] = 0;
34675  dst_s24[i*3+1] = 0;
34676  dst_s24[i*3+2] = (ma_uint8)((ma_int8)x);
34677  }
34678 
34679  (void)ditherMode;
34680 }
34681 
34682 static MA_INLINE void ma_pcm_u8_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34683 {
34684  ma_pcm_u8_to_s24__reference(dst, src, count, ditherMode);
34685 }
34686 
34687 #if defined(MA_SUPPORT_SSE2)
34688 static MA_INLINE void ma_pcm_u8_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34689 {
34690  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
34691 }
34692 #endif
34693 #if defined(MA_SUPPORT_AVX2)
34694 static MA_INLINE void ma_pcm_u8_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34695 {
34696  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
34697 }
34698 #endif
34699 #if defined(MA_SUPPORT_NEON)
34700 static MA_INLINE void ma_pcm_u8_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34701 {
34702  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
34703 }
34704 #endif
34705 
34706 MA_API void ma_pcm_u8_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34707 {
34708 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34709  ma_pcm_u8_to_s24__reference(dst, src, count, ditherMode);
34710 #else
34711  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
34712  if (ma_has_avx2()) {
34713  ma_pcm_u8_to_s24__avx2(dst, src, count, ditherMode);
34714  } else
34715  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
34716  if (ma_has_sse2()) {
34717  ma_pcm_u8_to_s24__sse2(dst, src, count, ditherMode);
34718  } else
34719  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
34720  if (ma_has_neon()) {
34721  ma_pcm_u8_to_s24__neon(dst, src, count, ditherMode);
34722  } else
34723  #endif
34724  {
34725  ma_pcm_u8_to_s24__optimized(dst, src, count, ditherMode);
34726  }
34727 #endif
34728 }
34729 
34730 
34731 static MA_INLINE void ma_pcm_u8_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34732 {
34733  ma_int32* dst_s32 = (ma_int32*)dst;
34734  const ma_uint8* src_u8 = (const ma_uint8*)src;
34735 
34736  ma_uint64 i;
34737  for (i = 0; i < count; i += 1) {
34738  ma_int32 x = src_u8[i];
34739  x = x - 128;
34740  x = x << 24;
34741  dst_s32[i] = x;
34742  }
34743 
34744  (void)ditherMode;
34745 }
34746 
34747 static MA_INLINE void ma_pcm_u8_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34748 {
34749  ma_pcm_u8_to_s32__reference(dst, src, count, ditherMode);
34750 }
34751 
34752 #if defined(MA_SUPPORT_SSE2)
34753 static MA_INLINE void ma_pcm_u8_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34754 {
34755  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
34756 }
34757 #endif
34758 #if defined(MA_SUPPORT_AVX2)
34759 static MA_INLINE void ma_pcm_u8_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34760 {
34761  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
34762 }
34763 #endif
34764 #if defined(MA_SUPPORT_NEON)
34765 static MA_INLINE void ma_pcm_u8_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34766 {
34767  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
34768 }
34769 #endif
34770 
34771 MA_API void ma_pcm_u8_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34772 {
34773 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34774  ma_pcm_u8_to_s32__reference(dst, src, count, ditherMode);
34775 #else
34776  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
34777  if (ma_has_avx2()) {
34778  ma_pcm_u8_to_s32__avx2(dst, src, count, ditherMode);
34779  } else
34780  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
34781  if (ma_has_sse2()) {
34782  ma_pcm_u8_to_s32__sse2(dst, src, count, ditherMode);
34783  } else
34784  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
34785  if (ma_has_neon()) {
34786  ma_pcm_u8_to_s32__neon(dst, src, count, ditherMode);
34787  } else
34788  #endif
34789  {
34790  ma_pcm_u8_to_s32__optimized(dst, src, count, ditherMode);
34791  }
34792 #endif
34793 }
34794 
34795 
34796 static MA_INLINE void ma_pcm_u8_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34797 {
34798  float* dst_f32 = (float*)dst;
34799  const ma_uint8* src_u8 = (const ma_uint8*)src;
34800 
34801  ma_uint64 i;
34802  for (i = 0; i < count; i += 1) {
34803  float x = (float)src_u8[i];
34804  x = x * 0.00784313725490196078f; /* 0..255 to 0..2 */
34805  x = x - 1; /* 0..2 to -1..1 */
34806 
34807  dst_f32[i] = x;
34808  }
34809 
34810  (void)ditherMode;
34811 }
34812 
34813 static MA_INLINE void ma_pcm_u8_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34814 {
34815  ma_pcm_u8_to_f32__reference(dst, src, count, ditherMode);
34816 }
34817 
34818 #if defined(MA_SUPPORT_SSE2)
34819 static MA_INLINE void ma_pcm_u8_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34820 {
34821  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
34822 }
34823 #endif
34824 #if defined(MA_SUPPORT_AVX2)
34825 static MA_INLINE void ma_pcm_u8_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34826 {
34827  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
34828 }
34829 #endif
34830 #if defined(MA_SUPPORT_NEON)
34831 static MA_INLINE void ma_pcm_u8_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34832 {
34833  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
34834 }
34835 #endif
34836 
34837 MA_API void ma_pcm_u8_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34838 {
34839 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34840  ma_pcm_u8_to_f32__reference(dst, src, count, ditherMode);
34841 #else
34842  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
34843  if (ma_has_avx2()) {
34844  ma_pcm_u8_to_f32__avx2(dst, src, count, ditherMode);
34845  } else
34846  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
34847  if (ma_has_sse2()) {
34848  ma_pcm_u8_to_f32__sse2(dst, src, count, ditherMode);
34849  } else
34850  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
34851  if (ma_has_neon()) {
34852  ma_pcm_u8_to_f32__neon(dst, src, count, ditherMode);
34853  } else
34854  #endif
34855  {
34856  ma_pcm_u8_to_f32__optimized(dst, src, count, ditherMode);
34857  }
34858 #endif
34859 }
34860 
34861 
34862 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34863 static MA_INLINE void ma_pcm_interleave_u8__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
34864 {
34865  ma_uint8* dst_u8 = (ma_uint8*)dst;
34866  const ma_uint8** src_u8 = (const ma_uint8**)src;
34867 
34868  ma_uint64 iFrame;
34869  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34870  ma_uint32 iChannel;
34871  for (iChannel = 0; iChannel < channels; iChannel += 1) {
34872  dst_u8[iFrame*channels + iChannel] = src_u8[iChannel][iFrame];
34873  }
34874  }
34875 }
34876 #else
34877 static MA_INLINE void ma_pcm_interleave_u8__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
34878 {
34879  ma_uint8* dst_u8 = (ma_uint8*)dst;
34880  const ma_uint8** src_u8 = (const ma_uint8**)src;
34881 
34882  if (channels == 1) {
34883  ma_copy_memory_64(dst, src[0], frameCount * sizeof(ma_uint8));
34884  } else if (channels == 2) {
34885  ma_uint64 iFrame;
34886  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34887  dst_u8[iFrame*2 + 0] = src_u8[0][iFrame];
34888  dst_u8[iFrame*2 + 1] = src_u8[1][iFrame];
34889  }
34890  } else {
34891  ma_uint64 iFrame;
34892  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34893  ma_uint32 iChannel;
34894  for (iChannel = 0; iChannel < channels; iChannel += 1) {
34895  dst_u8[iFrame*channels + iChannel] = src_u8[iChannel][iFrame];
34896  }
34897  }
34898  }
34899 }
34900 #endif
34901 
34902 MA_API void ma_pcm_interleave_u8(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
34903 {
34904 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34905  ma_pcm_interleave_u8__reference(dst, src, frameCount, channels);
34906 #else
34907  ma_pcm_interleave_u8__optimized(dst, src, frameCount, channels);
34908 #endif
34909 }
34910 
34911 
34912 static MA_INLINE void ma_pcm_deinterleave_u8__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
34913 {
34914  ma_uint8** dst_u8 = (ma_uint8**)dst;
34915  const ma_uint8* src_u8 = (const ma_uint8*)src;
34916 
34917  ma_uint64 iFrame;
34918  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
34919  ma_uint32 iChannel;
34920  for (iChannel = 0; iChannel < channels; iChannel += 1) {
34921  dst_u8[iChannel][iFrame] = src_u8[iFrame*channels + iChannel];
34922  }
34923  }
34924 }
34925 
34926 static MA_INLINE void ma_pcm_deinterleave_u8__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
34927 {
34928  ma_pcm_deinterleave_u8__reference(dst, src, frameCount, channels);
34929 }
34930 
34931 MA_API void ma_pcm_deinterleave_u8(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
34932 {
34933 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
34934  ma_pcm_deinterleave_u8__reference(dst, src, frameCount, channels);
34935 #else
34936  ma_pcm_deinterleave_u8__optimized(dst, src, frameCount, channels);
34937 #endif
34938 }
34939 
34940 
34941 /* s16 */
34942 static MA_INLINE void ma_pcm_s16_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34943 {
34944  ma_uint8* dst_u8 = (ma_uint8*)dst;
34945  const ma_int16* src_s16 = (const ma_int16*)src;
34946 
34947  if (ditherMode == ma_dither_mode_none) {
34948  ma_uint64 i;
34949  for (i = 0; i < count; i += 1) {
34950  ma_int16 x = src_s16[i];
34951  x = (ma_int16)(x >> 8);
34952  x = (ma_int16)(x + 128);
34953  dst_u8[i] = (ma_uint8)x;
34954  }
34955  } else {
34956  ma_uint64 i;
34957  for (i = 0; i < count; i += 1) {
34958  ma_int16 x = src_s16[i];
34959 
34960  /* Dither. Don't overflow. */
34961  ma_int32 dither = ma_dither_s32(ditherMode, -0x80, 0x7F);
34962  if ((x + dither) <= 0x7FFF) {
34963  x = (ma_int16)(x + dither);
34964  } else {
34965  x = 0x7FFF;
34966  }
34967 
34968  x = (ma_int16)(x >> 8);
34969  x = (ma_int16)(x + 128);
34970  dst_u8[i] = (ma_uint8)x;
34971  }
34972  }
34973 }
34974 
34975 static MA_INLINE void ma_pcm_s16_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34976 {
34977  ma_pcm_s16_to_u8__reference(dst, src, count, ditherMode);
34978 }
34979 
34980 #if defined(MA_SUPPORT_SSE2)
34981 static MA_INLINE void ma_pcm_s16_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34982 {
34983  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
34984 }
34985 #endif
34986 #if defined(MA_SUPPORT_AVX2)
34987 static MA_INLINE void ma_pcm_s16_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34988 {
34989  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
34990 }
34991 #endif
34992 #if defined(MA_SUPPORT_NEON)
34993 static MA_INLINE void ma_pcm_s16_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
34994 {
34995  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
34996 }
34997 #endif
34998 
34999 MA_API void ma_pcm_s16_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35000 {
35001 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35002  ma_pcm_s16_to_u8__reference(dst, src, count, ditherMode);
35003 #else
35004  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35005  if (ma_has_avx2()) {
35006  ma_pcm_s16_to_u8__avx2(dst, src, count, ditherMode);
35007  } else
35008  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35009  if (ma_has_sse2()) {
35010  ma_pcm_s16_to_u8__sse2(dst, src, count, ditherMode);
35011  } else
35012  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35013  if (ma_has_neon()) {
35014  ma_pcm_s16_to_u8__neon(dst, src, count, ditherMode);
35015  } else
35016  #endif
35017  {
35018  ma_pcm_s16_to_u8__optimized(dst, src, count, ditherMode);
35019  }
35020 #endif
35021 }
35022 
35023 
35024 MA_API void ma_pcm_s16_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35025 {
35026  (void)ditherMode;
35027  ma_copy_memory_64(dst, src, count * sizeof(ma_int16));
35028 }
35029 
35030 
35031 static MA_INLINE void ma_pcm_s16_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35032 {
35033  ma_uint8* dst_s24 = (ma_uint8*)dst;
35034  const ma_int16* src_s16 = (const ma_int16*)src;
35035 
35036  ma_uint64 i;
35037  for (i = 0; i < count; i += 1) {
35038  dst_s24[i*3+0] = 0;
35039  dst_s24[i*3+1] = (ma_uint8)(src_s16[i] & 0xFF);
35040  dst_s24[i*3+2] = (ma_uint8)(src_s16[i] >> 8);
35041  }
35042 
35043  (void)ditherMode;
35044 }
35045 
35046 static MA_INLINE void ma_pcm_s16_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35047 {
35048  ma_pcm_s16_to_s24__reference(dst, src, count, ditherMode);
35049 }
35050 
35051 #if defined(MA_SUPPORT_SSE2)
35052 static MA_INLINE void ma_pcm_s16_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35053 {
35054  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
35055 }
35056 #endif
35057 #if defined(MA_SUPPORT_AVX2)
35058 static MA_INLINE void ma_pcm_s16_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35059 {
35060  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
35061 }
35062 #endif
35063 #if defined(MA_SUPPORT_NEON)
35064 static MA_INLINE void ma_pcm_s16_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35065 {
35066  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
35067 }
35068 #endif
35069 
35070 MA_API void ma_pcm_s16_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35071 {
35072 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35073  ma_pcm_s16_to_s24__reference(dst, src, count, ditherMode);
35074 #else
35075  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35076  if (ma_has_avx2()) {
35077  ma_pcm_s16_to_s24__avx2(dst, src, count, ditherMode);
35078  } else
35079  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35080  if (ma_has_sse2()) {
35081  ma_pcm_s16_to_s24__sse2(dst, src, count, ditherMode);
35082  } else
35083  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35084  if (ma_has_neon()) {
35085  ma_pcm_s16_to_s24__neon(dst, src, count, ditherMode);
35086  } else
35087  #endif
35088  {
35089  ma_pcm_s16_to_s24__optimized(dst, src, count, ditherMode);
35090  }
35091 #endif
35092 }
35093 
35094 
35095 static MA_INLINE void ma_pcm_s16_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35096 {
35097  ma_int32* dst_s32 = (ma_int32*)dst;
35098  const ma_int16* src_s16 = (const ma_int16*)src;
35099 
35100  ma_uint64 i;
35101  for (i = 0; i < count; i += 1) {
35102  dst_s32[i] = src_s16[i] << 16;
35103  }
35104 
35105  (void)ditherMode;
35106 }
35107 
35108 static MA_INLINE void ma_pcm_s16_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35109 {
35110  ma_pcm_s16_to_s32__reference(dst, src, count, ditherMode);
35111 }
35112 
35113 #if defined(MA_SUPPORT_SSE2)
35114 static MA_INLINE void ma_pcm_s16_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35115 {
35116  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
35117 }
35118 #endif
35119 #if defined(MA_SUPPORT_AVX2)
35120 static MA_INLINE void ma_pcm_s16_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35121 {
35122  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
35123 }
35124 #endif
35125 #if defined(MA_SUPPORT_NEON)
35126 static MA_INLINE void ma_pcm_s16_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35127 {
35128  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
35129 }
35130 #endif
35131 
35132 MA_API void ma_pcm_s16_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35133 {
35134 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35135  ma_pcm_s16_to_s32__reference(dst, src, count, ditherMode);
35136 #else
35137  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35138  if (ma_has_avx2()) {
35139  ma_pcm_s16_to_s32__avx2(dst, src, count, ditherMode);
35140  } else
35141  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35142  if (ma_has_sse2()) {
35143  ma_pcm_s16_to_s32__sse2(dst, src, count, ditherMode);
35144  } else
35145  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35146  if (ma_has_neon()) {
35147  ma_pcm_s16_to_s32__neon(dst, src, count, ditherMode);
35148  } else
35149  #endif
35150  {
35151  ma_pcm_s16_to_s32__optimized(dst, src, count, ditherMode);
35152  }
35153 #endif
35154 }
35155 
35156 
35157 static MA_INLINE void ma_pcm_s16_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35158 {
35159  float* dst_f32 = (float*)dst;
35160  const ma_int16* src_s16 = (const ma_int16*)src;
35161 
35162  ma_uint64 i;
35163  for (i = 0; i < count; i += 1) {
35164  float x = (float)src_s16[i];
35165 
35166 #if 0
35167  /* The accurate way. */
35168  x = x + 32768.0f; /* -32768..32767 to 0..65535 */
35169  x = x * 0.00003051804379339284f; /* 0..65535 to 0..2 */
35170  x = x - 1; /* 0..2 to -1..1 */
35171 #else
35172  /* The fast way. */
35173  x = x * 0.000030517578125f; /* -32768..32767 to -1..0.999969482421875 */
35174 #endif
35175 
35176  dst_f32[i] = x;
35177  }
35178 
35179  (void)ditherMode;
35180 }
35181 
35182 static MA_INLINE void ma_pcm_s16_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35183 {
35184  ma_pcm_s16_to_f32__reference(dst, src, count, ditherMode);
35185 }
35186 
35187 #if defined(MA_SUPPORT_SSE2)
35188 static MA_INLINE void ma_pcm_s16_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35189 {
35190  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
35191 }
35192 #endif
35193 #if defined(MA_SUPPORT_AVX2)
35194 static MA_INLINE void ma_pcm_s16_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35195 {
35196  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
35197 }
35198 #endif
35199 #if defined(MA_SUPPORT_NEON)
35200 static MA_INLINE void ma_pcm_s16_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35201 {
35202  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
35203 }
35204 #endif
35205 
35206 MA_API void ma_pcm_s16_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35207 {
35208 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35209  ma_pcm_s16_to_f32__reference(dst, src, count, ditherMode);
35210 #else
35211  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35212  if (ma_has_avx2()) {
35213  ma_pcm_s16_to_f32__avx2(dst, src, count, ditherMode);
35214  } else
35215  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35216  if (ma_has_sse2()) {
35217  ma_pcm_s16_to_f32__sse2(dst, src, count, ditherMode);
35218  } else
35219  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35220  if (ma_has_neon()) {
35221  ma_pcm_s16_to_f32__neon(dst, src, count, ditherMode);
35222  } else
35223  #endif
35224  {
35225  ma_pcm_s16_to_f32__optimized(dst, src, count, ditherMode);
35226  }
35227 #endif
35228 }
35229 
35230 
35231 static MA_INLINE void ma_pcm_interleave_s16__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35232 {
35233  ma_int16* dst_s16 = (ma_int16*)dst;
35234  const ma_int16** src_s16 = (const ma_int16**)src;
35235 
35236  ma_uint64 iFrame;
35237  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
35238  ma_uint32 iChannel;
35239  for (iChannel = 0; iChannel < channels; iChannel += 1) {
35240  dst_s16[iFrame*channels + iChannel] = src_s16[iChannel][iFrame];
35241  }
35242  }
35243 }
35244 
35245 static MA_INLINE void ma_pcm_interleave_s16__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35246 {
35247  ma_pcm_interleave_s16__reference(dst, src, frameCount, channels);
35248 }
35249 
35250 MA_API void ma_pcm_interleave_s16(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35251 {
35252 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35253  ma_pcm_interleave_s16__reference(dst, src, frameCount, channels);
35254 #else
35255  ma_pcm_interleave_s16__optimized(dst, src, frameCount, channels);
35256 #endif
35257 }
35258 
35259 
35260 static MA_INLINE void ma_pcm_deinterleave_s16__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35261 {
35262  ma_int16** dst_s16 = (ma_int16**)dst;
35263  const ma_int16* src_s16 = (const ma_int16*)src;
35264 
35265  ma_uint64 iFrame;
35266  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
35267  ma_uint32 iChannel;
35268  for (iChannel = 0; iChannel < channels; iChannel += 1) {
35269  dst_s16[iChannel][iFrame] = src_s16[iFrame*channels + iChannel];
35270  }
35271  }
35272 }
35273 
35274 static MA_INLINE void ma_pcm_deinterleave_s16__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35275 {
35276  ma_pcm_deinterleave_s16__reference(dst, src, frameCount, channels);
35277 }
35278 
35279 MA_API void ma_pcm_deinterleave_s16(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35280 {
35281 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35282  ma_pcm_deinterleave_s16__reference(dst, src, frameCount, channels);
35283 #else
35284  ma_pcm_deinterleave_s16__optimized(dst, src, frameCount, channels);
35285 #endif
35286 }
35287 
35288 
35289 /* s24 */
35290 static MA_INLINE void ma_pcm_s24_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35291 {
35292  ma_uint8* dst_u8 = (ma_uint8*)dst;
35293  const ma_uint8* src_s24 = (const ma_uint8*)src;
35294 
35295  if (ditherMode == ma_dither_mode_none) {
35296  ma_uint64 i;
35297  for (i = 0; i < count; i += 1) {
35298  dst_u8[i] = (ma_uint8)((ma_int8)src_s24[i*3 + 2] + 128);
35299  }
35300  } else {
35301  ma_uint64 i;
35302  for (i = 0; i < count; i += 1) {
35303  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);
35304 
35305  /* Dither. Don't overflow. */
35306  ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
35307  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
35308  x = x + dither;
35309  } else {
35310  x = 0x7FFFFFFF;
35311  }
35312 
35313  x = x >> 24;
35314  x = x + 128;
35315  dst_u8[i] = (ma_uint8)x;
35316  }
35317  }
35318 }
35319 
35320 static MA_INLINE void ma_pcm_s24_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35321 {
35322  ma_pcm_s24_to_u8__reference(dst, src, count, ditherMode);
35323 }
35324 
35325 #if defined(MA_SUPPORT_SSE2)
35326 static MA_INLINE void ma_pcm_s24_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35327 {
35328  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
35329 }
35330 #endif
35331 #if defined(MA_SUPPORT_AVX2)
35332 static MA_INLINE void ma_pcm_s24_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35333 {
35334  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
35335 }
35336 #endif
35337 #if defined(MA_SUPPORT_NEON)
35338 static MA_INLINE void ma_pcm_s24_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35339 {
35340  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
35341 }
35342 #endif
35343 
35344 MA_API void ma_pcm_s24_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35345 {
35346 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35347  ma_pcm_s24_to_u8__reference(dst, src, count, ditherMode);
35348 #else
35349  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35350  if (ma_has_avx2()) {
35351  ma_pcm_s24_to_u8__avx2(dst, src, count, ditherMode);
35352  } else
35353  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35354  if (ma_has_sse2()) {
35355  ma_pcm_s24_to_u8__sse2(dst, src, count, ditherMode);
35356  } else
35357  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35358  if (ma_has_neon()) {
35359  ma_pcm_s24_to_u8__neon(dst, src, count, ditherMode);
35360  } else
35361  #endif
35362  {
35363  ma_pcm_s24_to_u8__optimized(dst, src, count, ditherMode);
35364  }
35365 #endif
35366 }
35367 
35368 
35369 static MA_INLINE void ma_pcm_s24_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35370 {
35371  ma_int16* dst_s16 = (ma_int16*)dst;
35372  const ma_uint8* src_s24 = (const ma_uint8*)src;
35373 
35374  if (ditherMode == ma_dither_mode_none) {
35375  ma_uint64 i;
35376  for (i = 0; i < count; i += 1) {
35377  ma_uint16 dst_lo = ((ma_uint16)src_s24[i*3 + 1]);
35378  ma_uint16 dst_hi = (ma_uint16)((ma_uint16)src_s24[i*3 + 2] << 8);
35379  dst_s16[i] = (ma_int16)(dst_lo | dst_hi);
35380  }
35381  } else {
35382  ma_uint64 i;
35383  for (i = 0; i < count; i += 1) {
35384  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);
35385 
35386  /* Dither. Don't overflow. */
35387  ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
35388  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
35389  x = x + dither;
35390  } else {
35391  x = 0x7FFFFFFF;
35392  }
35393 
35394  x = x >> 16;
35395  dst_s16[i] = (ma_int16)x;
35396  }
35397  }
35398 }
35399 
35400 static MA_INLINE void ma_pcm_s24_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35401 {
35402  ma_pcm_s24_to_s16__reference(dst, src, count, ditherMode);
35403 }
35404 
35405 #if defined(MA_SUPPORT_SSE2)
35406 static MA_INLINE void ma_pcm_s24_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35407 {
35408  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
35409 }
35410 #endif
35411 #if defined(MA_SUPPORT_AVX2)
35412 static MA_INLINE void ma_pcm_s24_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35413 {
35414  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
35415 }
35416 #endif
35417 #if defined(MA_SUPPORT_NEON)
35418 static MA_INLINE void ma_pcm_s24_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35419 {
35420  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
35421 }
35422 #endif
35423 
35424 MA_API void ma_pcm_s24_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35425 {
35426 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35427  ma_pcm_s24_to_s16__reference(dst, src, count, ditherMode);
35428 #else
35429  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35430  if (ma_has_avx2()) {
35431  ma_pcm_s24_to_s16__avx2(dst, src, count, ditherMode);
35432  } else
35433  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35434  if (ma_has_sse2()) {
35435  ma_pcm_s24_to_s16__sse2(dst, src, count, ditherMode);
35436  } else
35437  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35438  if (ma_has_neon()) {
35439  ma_pcm_s24_to_s16__neon(dst, src, count, ditherMode);
35440  } else
35441  #endif
35442  {
35443  ma_pcm_s24_to_s16__optimized(dst, src, count, ditherMode);
35444  }
35445 #endif
35446 }
35447 
35448 
35449 MA_API void ma_pcm_s24_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35450 {
35451  (void)ditherMode;
35452 
35453  ma_copy_memory_64(dst, src, count * 3);
35454 }
35455 
35456 
35457 static MA_INLINE void ma_pcm_s24_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35458 {
35459  ma_int32* dst_s32 = (ma_int32*)dst;
35460  const ma_uint8* src_s24 = (const ma_uint8*)src;
35461 
35462  ma_uint64 i;
35463  for (i = 0; i < count; i += 1) {
35464  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);
35465  }
35466 
35467  (void)ditherMode;
35468 }
35469 
35470 static MA_INLINE void ma_pcm_s24_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35471 {
35472  ma_pcm_s24_to_s32__reference(dst, src, count, ditherMode);
35473 }
35474 
35475 #if defined(MA_SUPPORT_SSE2)
35476 static MA_INLINE void ma_pcm_s24_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35477 {
35478  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
35479 }
35480 #endif
35481 #if defined(MA_SUPPORT_AVX2)
35482 static MA_INLINE void ma_pcm_s24_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35483 {
35484  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
35485 }
35486 #endif
35487 #if defined(MA_SUPPORT_NEON)
35488 static MA_INLINE void ma_pcm_s24_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35489 {
35490  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
35491 }
35492 #endif
35493 
35494 MA_API void ma_pcm_s24_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35495 {
35496 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35497  ma_pcm_s24_to_s32__reference(dst, src, count, ditherMode);
35498 #else
35499  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35500  if (ma_has_avx2()) {
35501  ma_pcm_s24_to_s32__avx2(dst, src, count, ditherMode);
35502  } else
35503  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35504  if (ma_has_sse2()) {
35505  ma_pcm_s24_to_s32__sse2(dst, src, count, ditherMode);
35506  } else
35507  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35508  if (ma_has_neon()) {
35509  ma_pcm_s24_to_s32__neon(dst, src, count, ditherMode);
35510  } else
35511  #endif
35512  {
35513  ma_pcm_s24_to_s32__optimized(dst, src, count, ditherMode);
35514  }
35515 #endif
35516 }
35517 
35518 
35519 static MA_INLINE void ma_pcm_s24_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35520 {
35521  float* dst_f32 = (float*)dst;
35522  const ma_uint8* src_s24 = (const ma_uint8*)src;
35523 
35524  ma_uint64 i;
35525  for (i = 0; i < count; i += 1) {
35526  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);
35527 
35528 #if 0
35529  /* The accurate way. */
35530  x = x + 8388608.0f; /* -8388608..8388607 to 0..16777215 */
35531  x = x * 0.00000011920929665621f; /* 0..16777215 to 0..2 */
35532  x = x - 1; /* 0..2 to -1..1 */
35533 #else
35534  /* The fast way. */
35535  x = x * 0.00000011920928955078125f; /* -8388608..8388607 to -1..0.999969482421875 */
35536 #endif
35537 
35538  dst_f32[i] = x;
35539  }
35540 
35541  (void)ditherMode;
35542 }
35543 
35544 static MA_INLINE void ma_pcm_s24_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35545 {
35546  ma_pcm_s24_to_f32__reference(dst, src, count, ditherMode);
35547 }
35548 
35549 #if defined(MA_SUPPORT_SSE2)
35550 static MA_INLINE void ma_pcm_s24_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35551 {
35552  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
35553 }
35554 #endif
35555 #if defined(MA_SUPPORT_AVX2)
35556 static MA_INLINE void ma_pcm_s24_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35557 {
35558  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
35559 }
35560 #endif
35561 #if defined(MA_SUPPORT_NEON)
35562 static MA_INLINE void ma_pcm_s24_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35563 {
35564  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
35565 }
35566 #endif
35567 
35568 MA_API void ma_pcm_s24_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35569 {
35570 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35571  ma_pcm_s24_to_f32__reference(dst, src, count, ditherMode);
35572 #else
35573  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35574  if (ma_has_avx2()) {
35575  ma_pcm_s24_to_f32__avx2(dst, src, count, ditherMode);
35576  } else
35577  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35578  if (ma_has_sse2()) {
35579  ma_pcm_s24_to_f32__sse2(dst, src, count, ditherMode);
35580  } else
35581  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35582  if (ma_has_neon()) {
35583  ma_pcm_s24_to_f32__neon(dst, src, count, ditherMode);
35584  } else
35585  #endif
35586  {
35587  ma_pcm_s24_to_f32__optimized(dst, src, count, ditherMode);
35588  }
35589 #endif
35590 }
35591 
35592 
35593 static MA_INLINE void ma_pcm_interleave_s24__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35594 {
35595  ma_uint8* dst8 = (ma_uint8*)dst;
35596  const ma_uint8** src8 = (const ma_uint8**)src;
35597 
35598  ma_uint64 iFrame;
35599  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
35600  ma_uint32 iChannel;
35601  for (iChannel = 0; iChannel < channels; iChannel += 1) {
35602  dst8[iFrame*3*channels + iChannel*3 + 0] = src8[iChannel][iFrame*3 + 0];
35603  dst8[iFrame*3*channels + iChannel*3 + 1] = src8[iChannel][iFrame*3 + 1];
35604  dst8[iFrame*3*channels + iChannel*3 + 2] = src8[iChannel][iFrame*3 + 2];
35605  }
35606  }
35607 }
35608 
35609 static MA_INLINE void ma_pcm_interleave_s24__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35610 {
35611  ma_pcm_interleave_s24__reference(dst, src, frameCount, channels);
35612 }
35613 
35614 MA_API void ma_pcm_interleave_s24(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35615 {
35616 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35617  ma_pcm_interleave_s24__reference(dst, src, frameCount, channels);
35618 #else
35619  ma_pcm_interleave_s24__optimized(dst, src, frameCount, channels);
35620 #endif
35621 }
35622 
35623 
35624 static MA_INLINE void ma_pcm_deinterleave_s24__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35625 {
35626  ma_uint8** dst8 = (ma_uint8**)dst;
35627  const ma_uint8* src8 = (const ma_uint8*)src;
35628 
35629  ma_uint32 iFrame;
35630  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
35631  ma_uint32 iChannel;
35632  for (iChannel = 0; iChannel < channels; iChannel += 1) {
35633  dst8[iChannel][iFrame*3 + 0] = src8[iFrame*3*channels + iChannel*3 + 0];
35634  dst8[iChannel][iFrame*3 + 1] = src8[iFrame*3*channels + iChannel*3 + 1];
35635  dst8[iChannel][iFrame*3 + 2] = src8[iFrame*3*channels + iChannel*3 + 2];
35636  }
35637  }
35638 }
35639 
35640 static MA_INLINE void ma_pcm_deinterleave_s24__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35641 {
35642  ma_pcm_deinterleave_s24__reference(dst, src, frameCount, channels);
35643 }
35644 
35645 MA_API void ma_pcm_deinterleave_s24(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35646 {
35647 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35648  ma_pcm_deinterleave_s24__reference(dst, src, frameCount, channels);
35649 #else
35650  ma_pcm_deinterleave_s24__optimized(dst, src, frameCount, channels);
35651 #endif
35652 }
35653 
35654 
35655 
35656 /* s32 */
35657 static MA_INLINE void ma_pcm_s32_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35658 {
35659  ma_uint8* dst_u8 = (ma_uint8*)dst;
35660  const ma_int32* src_s32 = (const ma_int32*)src;
35661 
35662  if (ditherMode == ma_dither_mode_none) {
35663  ma_uint64 i;
35664  for (i = 0; i < count; i += 1) {
35665  ma_int32 x = src_s32[i];
35666  x = x >> 24;
35667  x = x + 128;
35668  dst_u8[i] = (ma_uint8)x;
35669  }
35670  } else {
35671  ma_uint64 i;
35672  for (i = 0; i < count; i += 1) {
35673  ma_int32 x = src_s32[i];
35674 
35675  /* Dither. Don't overflow. */
35676  ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
35677  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
35678  x = x + dither;
35679  } else {
35680  x = 0x7FFFFFFF;
35681  }
35682 
35683  x = x >> 24;
35684  x = x + 128;
35685  dst_u8[i] = (ma_uint8)x;
35686  }
35687  }
35688 }
35689 
35690 static MA_INLINE void ma_pcm_s32_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35691 {
35692  ma_pcm_s32_to_u8__reference(dst, src, count, ditherMode);
35693 }
35694 
35695 #if defined(MA_SUPPORT_SSE2)
35696 static MA_INLINE void ma_pcm_s32_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35697 {
35698  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
35699 }
35700 #endif
35701 #if defined(MA_SUPPORT_AVX2)
35702 static MA_INLINE void ma_pcm_s32_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35703 {
35704  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
35705 }
35706 #endif
35707 #if defined(MA_SUPPORT_NEON)
35708 static MA_INLINE void ma_pcm_s32_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35709 {
35710  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
35711 }
35712 #endif
35713 
35714 MA_API void ma_pcm_s32_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35715 {
35716 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35717  ma_pcm_s32_to_u8__reference(dst, src, count, ditherMode);
35718 #else
35719  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35720  if (ma_has_avx2()) {
35721  ma_pcm_s32_to_u8__avx2(dst, src, count, ditherMode);
35722  } else
35723  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35724  if (ma_has_sse2()) {
35725  ma_pcm_s32_to_u8__sse2(dst, src, count, ditherMode);
35726  } else
35727  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35728  if (ma_has_neon()) {
35729  ma_pcm_s32_to_u8__neon(dst, src, count, ditherMode);
35730  } else
35731  #endif
35732  {
35733  ma_pcm_s32_to_u8__optimized(dst, src, count, ditherMode);
35734  }
35735 #endif
35736 }
35737 
35738 
35739 static MA_INLINE void ma_pcm_s32_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35740 {
35741  ma_int16* dst_s16 = (ma_int16*)dst;
35742  const ma_int32* src_s32 = (const ma_int32*)src;
35743 
35744  if (ditherMode == ma_dither_mode_none) {
35745  ma_uint64 i;
35746  for (i = 0; i < count; i += 1) {
35747  ma_int32 x = src_s32[i];
35748  x = x >> 16;
35749  dst_s16[i] = (ma_int16)x;
35750  }
35751  } else {
35752  ma_uint64 i;
35753  for (i = 0; i < count; i += 1) {
35754  ma_int32 x = src_s32[i];
35755 
35756  /* Dither. Don't overflow. */
35757  ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
35758  if ((ma_int64)x + dither <= 0x7FFFFFFF) {
35759  x = x + dither;
35760  } else {
35761  x = 0x7FFFFFFF;
35762  }
35763 
35764  x = x >> 16;
35765  dst_s16[i] = (ma_int16)x;
35766  }
35767  }
35768 }
35769 
35770 static MA_INLINE void ma_pcm_s32_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35771 {
35772  ma_pcm_s32_to_s16__reference(dst, src, count, ditherMode);
35773 }
35774 
35775 #if defined(MA_SUPPORT_SSE2)
35776 static MA_INLINE void ma_pcm_s32_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35777 {
35778  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
35779 }
35780 #endif
35781 #if defined(MA_SUPPORT_AVX2)
35782 static MA_INLINE void ma_pcm_s32_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35783 {
35784  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
35785 }
35786 #endif
35787 #if defined(MA_SUPPORT_NEON)
35788 static MA_INLINE void ma_pcm_s32_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35789 {
35790  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
35791 }
35792 #endif
35793 
35794 MA_API void ma_pcm_s32_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35795 {
35796 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35797  ma_pcm_s32_to_s16__reference(dst, src, count, ditherMode);
35798 #else
35799  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35800  if (ma_has_avx2()) {
35801  ma_pcm_s32_to_s16__avx2(dst, src, count, ditherMode);
35802  } else
35803  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35804  if (ma_has_sse2()) {
35805  ma_pcm_s32_to_s16__sse2(dst, src, count, ditherMode);
35806  } else
35807  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35808  if (ma_has_neon()) {
35809  ma_pcm_s32_to_s16__neon(dst, src, count, ditherMode);
35810  } else
35811  #endif
35812  {
35813  ma_pcm_s32_to_s16__optimized(dst, src, count, ditherMode);
35814  }
35815 #endif
35816 }
35817 
35818 
35819 static MA_INLINE void ma_pcm_s32_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35820 {
35821  ma_uint8* dst_s24 = (ma_uint8*)dst;
35822  const ma_int32* src_s32 = (const ma_int32*)src;
35823 
35824  ma_uint64 i;
35825  for (i = 0; i < count; i += 1) {
35826  ma_uint32 x = (ma_uint32)src_s32[i];
35827  dst_s24[i*3+0] = (ma_uint8)((x & 0x0000FF00) >> 8);
35828  dst_s24[i*3+1] = (ma_uint8)((x & 0x00FF0000) >> 16);
35829  dst_s24[i*3+2] = (ma_uint8)((x & 0xFF000000) >> 24);
35830  }
35831 
35832  (void)ditherMode; /* No dithering for s32 -> s24. */
35833 }
35834 
35835 static MA_INLINE void ma_pcm_s32_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35836 {
35837  ma_pcm_s32_to_s24__reference(dst, src, count, ditherMode);
35838 }
35839 
35840 #if defined(MA_SUPPORT_SSE2)
35841 static MA_INLINE void ma_pcm_s32_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35842 {
35843  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
35844 }
35845 #endif
35846 #if defined(MA_SUPPORT_AVX2)
35847 static MA_INLINE void ma_pcm_s32_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35848 {
35849  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
35850 }
35851 #endif
35852 #if defined(MA_SUPPORT_NEON)
35853 static MA_INLINE void ma_pcm_s32_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35854 {
35855  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
35856 }
35857 #endif
35858 
35859 MA_API void ma_pcm_s32_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35860 {
35861 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35862  ma_pcm_s32_to_s24__reference(dst, src, count, ditherMode);
35863 #else
35864  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35865  if (ma_has_avx2()) {
35866  ma_pcm_s32_to_s24__avx2(dst, src, count, ditherMode);
35867  } else
35868  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35869  if (ma_has_sse2()) {
35870  ma_pcm_s32_to_s24__sse2(dst, src, count, ditherMode);
35871  } else
35872  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35873  if (ma_has_neon()) {
35874  ma_pcm_s32_to_s24__neon(dst, src, count, ditherMode);
35875  } else
35876  #endif
35877  {
35878  ma_pcm_s32_to_s24__optimized(dst, src, count, ditherMode);
35879  }
35880 #endif
35881 }
35882 
35883 
35884 MA_API void ma_pcm_s32_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35885 {
35886  (void)ditherMode;
35887 
35888  ma_copy_memory_64(dst, src, count * sizeof(ma_int32));
35889 }
35890 
35891 
35892 static MA_INLINE void ma_pcm_s32_to_f32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35893 {
35894  float* dst_f32 = (float*)dst;
35895  const ma_int32* src_s32 = (const ma_int32*)src;
35896 
35897  ma_uint64 i;
35898  for (i = 0; i < count; i += 1) {
35899  double x = src_s32[i];
35900 
35901 #if 0
35902  x = x + 2147483648.0;
35903  x = x * 0.0000000004656612873077392578125;
35904  x = x - 1;
35905 #else
35906  x = x / 2147483648.0;
35907 #endif
35908 
35909  dst_f32[i] = (float)x;
35910  }
35911 
35912  (void)ditherMode; /* No dithering for s32 -> f32. */
35913 }
35914 
35915 static MA_INLINE void ma_pcm_s32_to_f32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35916 {
35917  ma_pcm_s32_to_f32__reference(dst, src, count, ditherMode);
35918 }
35919 
35920 #if defined(MA_SUPPORT_SSE2)
35921 static MA_INLINE void ma_pcm_s32_to_f32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35922 {
35923  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
35924 }
35925 #endif
35926 #if defined(MA_SUPPORT_AVX2)
35927 static MA_INLINE void ma_pcm_s32_to_f32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35928 {
35929  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
35930 }
35931 #endif
35932 #if defined(MA_SUPPORT_NEON)
35933 static MA_INLINE void ma_pcm_s32_to_f32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35934 {
35935  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
35936 }
35937 #endif
35938 
35939 MA_API void ma_pcm_s32_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
35940 {
35941 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35942  ma_pcm_s32_to_f32__reference(dst, src, count, ditherMode);
35943 #else
35944  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
35945  if (ma_has_avx2()) {
35946  ma_pcm_s32_to_f32__avx2(dst, src, count, ditherMode);
35947  } else
35948  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
35949  if (ma_has_sse2()) {
35950  ma_pcm_s32_to_f32__sse2(dst, src, count, ditherMode);
35951  } else
35952  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
35953  if (ma_has_neon()) {
35954  ma_pcm_s32_to_f32__neon(dst, src, count, ditherMode);
35955  } else
35956  #endif
35957  {
35958  ma_pcm_s32_to_f32__optimized(dst, src, count, ditherMode);
35959  }
35960 #endif
35961 }
35962 
35963 
35964 static MA_INLINE void ma_pcm_interleave_s32__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35965 {
35966  ma_int32* dst_s32 = (ma_int32*)dst;
35967  const ma_int32** src_s32 = (const ma_int32**)src;
35968 
35969  ma_uint64 iFrame;
35970  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
35971  ma_uint32 iChannel;
35972  for (iChannel = 0; iChannel < channels; iChannel += 1) {
35973  dst_s32[iFrame*channels + iChannel] = src_s32[iChannel][iFrame];
35974  }
35975  }
35976 }
35977 
35978 static MA_INLINE void ma_pcm_interleave_s32__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35979 {
35980  ma_pcm_interleave_s32__reference(dst, src, frameCount, channels);
35981 }
35982 
35983 MA_API void ma_pcm_interleave_s32(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
35984 {
35985 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
35986  ma_pcm_interleave_s32__reference(dst, src, frameCount, channels);
35987 #else
35988  ma_pcm_interleave_s32__optimized(dst, src, frameCount, channels);
35989 #endif
35990 }
35991 
35992 
35993 static MA_INLINE void ma_pcm_deinterleave_s32__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
35994 {
35995  ma_int32** dst_s32 = (ma_int32**)dst;
35996  const ma_int32* src_s32 = (const ma_int32*)src;
35997 
35998  ma_uint64 iFrame;
35999  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
36000  ma_uint32 iChannel;
36001  for (iChannel = 0; iChannel < channels; iChannel += 1) {
36002  dst_s32[iChannel][iFrame] = src_s32[iFrame*channels + iChannel];
36003  }
36004  }
36005 }
36006 
36007 static MA_INLINE void ma_pcm_deinterleave_s32__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
36008 {
36009  ma_pcm_deinterleave_s32__reference(dst, src, frameCount, channels);
36010 }
36011 
36012 MA_API void ma_pcm_deinterleave_s32(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
36013 {
36014 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36015  ma_pcm_deinterleave_s32__reference(dst, src, frameCount, channels);
36016 #else
36017  ma_pcm_deinterleave_s32__optimized(dst, src, frameCount, channels);
36018 #endif
36019 }
36020 
36021 
36022 /* f32 */
36023 static MA_INLINE void ma_pcm_f32_to_u8__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36024 {
36025  ma_uint64 i;
36026 
36027  ma_uint8* dst_u8 = (ma_uint8*)dst;
36028  const float* src_f32 = (const float*)src;
36029 
36030  float ditherMin = 0;
36031  float ditherMax = 0;
36032  if (ditherMode != ma_dither_mode_none) {
36033  ditherMin = 1.0f / -128;
36034  ditherMax = 1.0f / 127;
36035  }
36036 
36037  for (i = 0; i < count; i += 1) {
36038  float x = src_f32[i];
36039  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
36040  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36041  x = x + 1; /* -1..1 to 0..2 */
36042  x = x * 127.5f; /* 0..2 to 0..255 */
36043 
36044  dst_u8[i] = (ma_uint8)x;
36045  }
36046 }
36047 
36048 static MA_INLINE void ma_pcm_f32_to_u8__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36049 {
36050  ma_pcm_f32_to_u8__reference(dst, src, count, ditherMode);
36051 }
36052 
36053 #if defined(MA_SUPPORT_SSE2)
36054 static MA_INLINE void ma_pcm_f32_to_u8__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36055 {
36056  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
36057 }
36058 #endif
36059 #if defined(MA_SUPPORT_AVX2)
36060 static MA_INLINE void ma_pcm_f32_to_u8__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36061 {
36062  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
36063 }
36064 #endif
36065 #if defined(MA_SUPPORT_NEON)
36066 static MA_INLINE void ma_pcm_f32_to_u8__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36067 {
36068  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
36069 }
36070 #endif
36071 
36072 MA_API void ma_pcm_f32_to_u8(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36073 {
36074 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36075  ma_pcm_f32_to_u8__reference(dst, src, count, ditherMode);
36076 #else
36077  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
36078  if (ma_has_avx2()) {
36079  ma_pcm_f32_to_u8__avx2(dst, src, count, ditherMode);
36080  } else
36081  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
36082  if (ma_has_sse2()) {
36083  ma_pcm_f32_to_u8__sse2(dst, src, count, ditherMode);
36084  } else
36085  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
36086  if (ma_has_neon()) {
36087  ma_pcm_f32_to_u8__neon(dst, src, count, ditherMode);
36088  } else
36089  #endif
36090  {
36091  ma_pcm_f32_to_u8__optimized(dst, src, count, ditherMode);
36092  }
36093 #endif
36094 }
36095 
36096 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36097 static MA_INLINE void ma_pcm_f32_to_s16__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36098 {
36099  ma_uint64 i;
36100 
36101  ma_int16* dst_s16 = (ma_int16*)dst;
36102  const float* src_f32 = (const float*)src;
36103 
36104  float ditherMin = 0;
36105  float ditherMax = 0;
36106  if (ditherMode != ma_dither_mode_none) {
36107  ditherMin = 1.0f / -32768;
36108  ditherMax = 1.0f / 32767;
36109  }
36110 
36111  for (i = 0; i < count; i += 1) {
36112  float x = src_f32[i];
36113  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
36114  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36115 
36116 #if 0
36117  /* The accurate way. */
36118  x = x + 1; /* -1..1 to 0..2 */
36119  x = x * 32767.5f; /* 0..2 to 0..65535 */
36120  x = x - 32768.0f; /* 0...65535 to -32768..32767 */
36121 #else
36122  /* The fast way. */
36123  x = x * 32767.0f; /* -1..1 to -32767..32767 */
36124 #endif
36125 
36126  dst_s16[i] = (ma_int16)x;
36127  }
36128 }
36129 #else
36130 static MA_INLINE void ma_pcm_f32_to_s16__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36131 {
36132  ma_uint64 i;
36133  ma_uint64 i4;
36134  ma_uint64 count4;
36135 
36136  ma_int16* dst_s16 = (ma_int16*)dst;
36137  const float* src_f32 = (const float*)src;
36138 
36139  float ditherMin = 0;
36140  float ditherMax = 0;
36141  if (ditherMode != ma_dither_mode_none) {
36142  ditherMin = 1.0f / -32768;
36143  ditherMax = 1.0f / 32767;
36144  }
36145 
36146  /* Unrolled. */
36147  i = 0;
36148  count4 = count >> 2;
36149  for (i4 = 0; i4 < count4; i4 += 1) {
36150  float d0 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
36151  float d1 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
36152  float d2 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
36153  float d3 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
36154 
36155  float x0 = src_f32[i+0];
36156  float x1 = src_f32[i+1];
36157  float x2 = src_f32[i+2];
36158  float x3 = src_f32[i+3];
36159 
36160  x0 = x0 + d0;
36161  x1 = x1 + d1;
36162  x2 = x2 + d2;
36163  x3 = x3 + d3;
36164 
36165  x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
36166  x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
36167  x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
36168  x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
36169 
36170  x0 = x0 * 32767.0f;
36171  x1 = x1 * 32767.0f;
36172  x2 = x2 * 32767.0f;
36173  x3 = x3 * 32767.0f;
36174 
36175  dst_s16[i+0] = (ma_int16)x0;
36176  dst_s16[i+1] = (ma_int16)x1;
36177  dst_s16[i+2] = (ma_int16)x2;
36178  dst_s16[i+3] = (ma_int16)x3;
36179 
36180  i += 4;
36181  }
36182 
36183  /* Leftover. */
36184  for (; i < count; i += 1) {
36185  float x = src_f32[i];
36186  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
36187  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36188  x = x * 32767.0f; /* -1..1 to -32767..32767 */
36189 
36190  dst_s16[i] = (ma_int16)x;
36191  }
36192 }
36193 
36194 #if defined(MA_SUPPORT_SSE2)
36195 static MA_INLINE void ma_pcm_f32_to_s16__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36196 {
36197  ma_uint64 i;
36198  ma_uint64 i8;
36199  ma_uint64 count8;
36200  ma_int16* dst_s16;
36201  const float* src_f32;
36202  float ditherMin;
36203  float ditherMax;
36204 
36205  /* Both the input and output buffers need to be aligned to 16 bytes. */
36206  if ((((ma_uintptr)dst & 15) != 0) || (((ma_uintptr)src & 15) != 0)) {
36207  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
36208  return;
36209  }
36210 
36211  dst_s16 = (ma_int16*)dst;
36212  src_f32 = (const float*)src;
36213 
36214  ditherMin = 0;
36215  ditherMax = 0;
36216  if (ditherMode != ma_dither_mode_none) {
36217  ditherMin = 1.0f / -32768;
36218  ditherMax = 1.0f / 32767;
36219  }
36220 
36221  i = 0;
36222 
36223  /* SSE2. SSE allows us to output 8 s16's at a time which means our loop is unrolled 8 times. */
36224  count8 = count >> 3;
36225  for (i8 = 0; i8 < count8; i8 += 1) {
36226  __m128 d0;
36227  __m128 d1;
36228  __m128 x0;
36229  __m128 x1;
36230 
36231  if (ditherMode == ma_dither_mode_none) {
36232  d0 = _mm_set1_ps(0);
36233  d1 = _mm_set1_ps(0);
36234  } else if (ditherMode == ma_dither_mode_rectangle) {
36235  d0 = _mm_set_ps(
36236  ma_dither_f32_rectangle(ditherMin, ditherMax),
36237  ma_dither_f32_rectangle(ditherMin, ditherMax),
36238  ma_dither_f32_rectangle(ditherMin, ditherMax),
36239  ma_dither_f32_rectangle(ditherMin, ditherMax)
36240  );
36241  d1 = _mm_set_ps(
36242  ma_dither_f32_rectangle(ditherMin, ditherMax),
36243  ma_dither_f32_rectangle(ditherMin, ditherMax),
36244  ma_dither_f32_rectangle(ditherMin, ditherMax),
36245  ma_dither_f32_rectangle(ditherMin, ditherMax)
36246  );
36247  } else {
36248  d0 = _mm_set_ps(
36249  ma_dither_f32_triangle(ditherMin, ditherMax),
36250  ma_dither_f32_triangle(ditherMin, ditherMax),
36251  ma_dither_f32_triangle(ditherMin, ditherMax),
36252  ma_dither_f32_triangle(ditherMin, ditherMax)
36253  );
36254  d1 = _mm_set_ps(
36255  ma_dither_f32_triangle(ditherMin, ditherMax),
36256  ma_dither_f32_triangle(ditherMin, ditherMax),
36257  ma_dither_f32_triangle(ditherMin, ditherMax),
36258  ma_dither_f32_triangle(ditherMin, ditherMax)
36259  );
36260  }
36261 
36262  x0 = *((__m128*)(src_f32 + i) + 0);
36263  x1 = *((__m128*)(src_f32 + i) + 1);
36264 
36265  x0 = _mm_add_ps(x0, d0);
36266  x1 = _mm_add_ps(x1, d1);
36267 
36268  x0 = _mm_mul_ps(x0, _mm_set1_ps(32767.0f));
36269  x1 = _mm_mul_ps(x1, _mm_set1_ps(32767.0f));
36270 
36271  _mm_stream_si128(((__m128i*)(dst_s16 + i)), _mm_packs_epi32(_mm_cvttps_epi32(x0), _mm_cvttps_epi32(x1)));
36272 
36273  i += 8;
36274  }
36275 
36276 
36277  /* Leftover. */
36278  for (; i < count; i += 1) {
36279  float x = src_f32[i];
36280  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
36281  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36282  x = x * 32767.0f; /* -1..1 to -32767..32767 */
36283 
36284  dst_s16[i] = (ma_int16)x;
36285  }
36286 }
36287 #endif /* SSE2 */
36288 
36289 #if defined(MA_SUPPORT_AVX2)
36290 static MA_INLINE void ma_pcm_f32_to_s16__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36291 {
36292  ma_uint64 i;
36293  ma_uint64 i16;
36294  ma_uint64 count16;
36295  ma_int16* dst_s16;
36296  const float* src_f32;
36297  float ditherMin;
36298  float ditherMax;
36299 
36300  /* Both the input and output buffers need to be aligned to 32 bytes. */
36301  if ((((ma_uintptr)dst & 31) != 0) || (((ma_uintptr)src & 31) != 0)) {
36302  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
36303  return;
36304  }
36305 
36306  dst_s16 = (ma_int16*)dst;
36307  src_f32 = (const float*)src;
36308 
36309  ditherMin = 0;
36310  ditherMax = 0;
36311  if (ditherMode != ma_dither_mode_none) {
36312  ditherMin = 1.0f / -32768;
36313  ditherMax = 1.0f / 32767;
36314  }
36315 
36316  i = 0;
36317 
36318  /* AVX2. AVX2 allows us to output 16 s16's at a time which means our loop is unrolled 16 times. */
36319  count16 = count >> 4;
36320  for (i16 = 0; i16 < count16; i16 += 1) {
36321  __m256 d0;
36322  __m256 d1;
36323  __m256 x0;
36324  __m256 x1;
36325  __m256i i0;
36326  __m256i i1;
36327  __m256i p0;
36328  __m256i p1;
36329  __m256i r;
36330 
36331  if (ditherMode == ma_dither_mode_none) {
36332  d0 = _mm256_set1_ps(0);
36333  d1 = _mm256_set1_ps(0);
36334  } else if (ditherMode == ma_dither_mode_rectangle) {
36335  d0 = _mm256_set_ps(
36336  ma_dither_f32_rectangle(ditherMin, ditherMax),
36337  ma_dither_f32_rectangle(ditherMin, ditherMax),
36338  ma_dither_f32_rectangle(ditherMin, ditherMax),
36339  ma_dither_f32_rectangle(ditherMin, ditherMax),
36340  ma_dither_f32_rectangle(ditherMin, ditherMax),
36341  ma_dither_f32_rectangle(ditherMin, ditherMax),
36342  ma_dither_f32_rectangle(ditherMin, ditherMax),
36343  ma_dither_f32_rectangle(ditherMin, ditherMax)
36344  );
36345  d1 = _mm256_set_ps(
36346  ma_dither_f32_rectangle(ditherMin, ditherMax),
36347  ma_dither_f32_rectangle(ditherMin, ditherMax),
36348  ma_dither_f32_rectangle(ditherMin, ditherMax),
36349  ma_dither_f32_rectangle(ditherMin, ditherMax),
36350  ma_dither_f32_rectangle(ditherMin, ditherMax),
36351  ma_dither_f32_rectangle(ditherMin, ditherMax),
36352  ma_dither_f32_rectangle(ditherMin, ditherMax),
36353  ma_dither_f32_rectangle(ditherMin, ditherMax)
36354  );
36355  } else {
36356  d0 = _mm256_set_ps(
36357  ma_dither_f32_triangle(ditherMin, ditherMax),
36358  ma_dither_f32_triangle(ditherMin, ditherMax),
36359  ma_dither_f32_triangle(ditherMin, ditherMax),
36360  ma_dither_f32_triangle(ditherMin, ditherMax),
36361  ma_dither_f32_triangle(ditherMin, ditherMax),
36362  ma_dither_f32_triangle(ditherMin, ditherMax),
36363  ma_dither_f32_triangle(ditherMin, ditherMax),
36364  ma_dither_f32_triangle(ditherMin, ditherMax)
36365  );
36366  d1 = _mm256_set_ps(
36367  ma_dither_f32_triangle(ditherMin, ditherMax),
36368  ma_dither_f32_triangle(ditherMin, ditherMax),
36369  ma_dither_f32_triangle(ditherMin, ditherMax),
36370  ma_dither_f32_triangle(ditherMin, ditherMax),
36371  ma_dither_f32_triangle(ditherMin, ditherMax),
36372  ma_dither_f32_triangle(ditherMin, ditherMax),
36373  ma_dither_f32_triangle(ditherMin, ditherMax),
36374  ma_dither_f32_triangle(ditherMin, ditherMax)
36375  );
36376  }
36377 
36378  x0 = *((__m256*)(src_f32 + i) + 0);
36379  x1 = *((__m256*)(src_f32 + i) + 1);
36380 
36381  x0 = _mm256_add_ps(x0, d0);
36382  x1 = _mm256_add_ps(x1, d1);
36383 
36384  x0 = _mm256_mul_ps(x0, _mm256_set1_ps(32767.0f));
36385  x1 = _mm256_mul_ps(x1, _mm256_set1_ps(32767.0f));
36386 
36387  /* Computing the final result is a little more complicated for AVX2 than SSE2. */
36388  i0 = _mm256_cvttps_epi32(x0);
36389  i1 = _mm256_cvttps_epi32(x1);
36390  p0 = _mm256_permute2x128_si256(i0, i1, 0 | 32);
36391  p1 = _mm256_permute2x128_si256(i0, i1, 1 | 48);
36392  r = _mm256_packs_epi32(p0, p1);
36393 
36394  _mm256_stream_si256(((__m256i*)(dst_s16 + i)), r);
36395 
36396  i += 16;
36397  }
36398 
36399 
36400  /* Leftover. */
36401  for (; i < count; i += 1) {
36402  float x = src_f32[i];
36403  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
36404  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36405  x = x * 32767.0f; /* -1..1 to -32767..32767 */
36406 
36407  dst_s16[i] = (ma_int16)x;
36408  }
36409 }
36410 #endif /* AVX2 */
36411 
36412 #if defined(MA_SUPPORT_NEON)
36413 static MA_INLINE void ma_pcm_f32_to_s16__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36414 {
36415  ma_uint64 i;
36416  ma_uint64 i8;
36417  ma_uint64 count8;
36418  ma_int16* dst_s16;
36419  const float* src_f32;
36420  float ditherMin;
36421  float ditherMax;
36422 
36423  if (!ma_has_neon()) {
36424  return ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
36425  }
36426 
36427  /* Both the input and output buffers need to be aligned to 16 bytes. */
36428  if ((((ma_uintptr)dst & 15) != 0) || (((ma_uintptr)src & 15) != 0)) {
36429  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
36430  return;
36431  }
36432 
36433  dst_s16 = (ma_int16*)dst;
36434  src_f32 = (const float*)src;
36435 
36436  ditherMin = 0;
36437  ditherMax = 0;
36438  if (ditherMode != ma_dither_mode_none) {
36439  ditherMin = 1.0f / -32768;
36440  ditherMax = 1.0f / 32767;
36441  }
36442 
36443  i = 0;
36444 
36445  /* NEON. NEON allows us to output 8 s16's at a time which means our loop is unrolled 8 times. */
36446  count8 = count >> 3;
36447  for (i8 = 0; i8 < count8; i8 += 1) {
36448  float32x4_t d0;
36449  float32x4_t d1;
36450  float32x4_t x0;
36451  float32x4_t x1;
36452  int32x4_t i0;
36453  int32x4_t i1;
36454 
36455  if (ditherMode == ma_dither_mode_none) {
36456  d0 = vmovq_n_f32(0);
36457  d1 = vmovq_n_f32(0);
36458  } else if (ditherMode == ma_dither_mode_rectangle) {
36459  float d0v[4];
36460  d0v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36461  d0v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36462  d0v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36463  d0v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36464  d0 = vld1q_f32(d0v);
36465 
36466  float d1v[4];
36467  d1v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36468  d1v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36469  d1v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36470  d1v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
36471  d1 = vld1q_f32(d1v);
36472  } else {
36473  float d0v[4];
36474  d0v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
36475  d0v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
36476  d0v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
36477  d0v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
36478  d0 = vld1q_f32(d0v);
36479 
36480  float d1v[4];
36481  d1v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
36482  d1v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
36483  d1v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
36484  d1v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
36485  d1 = vld1q_f32(d1v);
36486  }
36487 
36488  x0 = *((float32x4_t*)(src_f32 + i) + 0);
36489  x1 = *((float32x4_t*)(src_f32 + i) + 1);
36490 
36491  x0 = vaddq_f32(x0, d0);
36492  x1 = vaddq_f32(x1, d1);
36493 
36494  x0 = vmulq_n_f32(x0, 32767.0f);
36495  x1 = vmulq_n_f32(x1, 32767.0f);
36496 
36497  i0 = vcvtq_s32_f32(x0);
36498  i1 = vcvtq_s32_f32(x1);
36499  *((int16x8_t*)(dst_s16 + i)) = vcombine_s16(vqmovn_s32(i0), vqmovn_s32(i1));
36500 
36501  i += 8;
36502  }
36503 
36504 
36505  /* Leftover. */
36506  for (; i < count; i += 1) {
36507  float x = src_f32[i];
36508  x = x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
36509  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36510  x = x * 32767.0f; /* -1..1 to -32767..32767 */
36511 
36512  dst_s16[i] = (ma_int16)x;
36513  }
36514 }
36515 #endif /* Neon */
36516 #endif /* MA_USE_REFERENCE_CONVERSION_APIS */
36517 
36518 MA_API void ma_pcm_f32_to_s16(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36519 {
36520 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36521  ma_pcm_f32_to_s16__reference(dst, src, count, ditherMode);
36522 #else
36523  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
36524  if (ma_has_avx2()) {
36525  ma_pcm_f32_to_s16__avx2(dst, src, count, ditherMode);
36526  } else
36527  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
36528  if (ma_has_sse2()) {
36529  ma_pcm_f32_to_s16__sse2(dst, src, count, ditherMode);
36530  } else
36531  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
36532  if (ma_has_neon()) {
36533  ma_pcm_f32_to_s16__neon(dst, src, count, ditherMode);
36534  } else
36535  #endif
36536  {
36537  ma_pcm_f32_to_s16__optimized(dst, src, count, ditherMode);
36538  }
36539 #endif
36540 }
36541 
36542 
36543 static MA_INLINE void ma_pcm_f32_to_s24__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36544 {
36545  ma_uint8* dst_s24 = (ma_uint8*)dst;
36546  const float* src_f32 = (const float*)src;
36547 
36548  ma_uint64 i;
36549  for (i = 0; i < count; i += 1) {
36550  ma_int32 r;
36551  float x = src_f32[i];
36552  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36553 
36554 #if 0
36555  /* The accurate way. */
36556  x = x + 1; /* -1..1 to 0..2 */
36557  x = x * 8388607.5f; /* 0..2 to 0..16777215 */
36558  x = x - 8388608.0f; /* 0..16777215 to -8388608..8388607 */
36559 #else
36560  /* The fast way. */
36561  x = x * 8388607.0f; /* -1..1 to -8388607..8388607 */
36562 #endif
36563 
36564  r = (ma_int32)x;
36565  dst_s24[(i*3)+0] = (ma_uint8)((r & 0x0000FF) >> 0);
36566  dst_s24[(i*3)+1] = (ma_uint8)((r & 0x00FF00) >> 8);
36567  dst_s24[(i*3)+2] = (ma_uint8)((r & 0xFF0000) >> 16);
36568  }
36569 
36570  (void)ditherMode; /* No dithering for f32 -> s24. */
36571 }
36572 
36573 static MA_INLINE void ma_pcm_f32_to_s24__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36574 {
36575  ma_pcm_f32_to_s24__reference(dst, src, count, ditherMode);
36576 }
36577 
36578 #if defined(MA_SUPPORT_SSE2)
36579 static MA_INLINE void ma_pcm_f32_to_s24__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36580 {
36581  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
36582 }
36583 #endif
36584 #if defined(MA_SUPPORT_AVX2)
36585 static MA_INLINE void ma_pcm_f32_to_s24__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36586 {
36587  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
36588 }
36589 #endif
36590 #if defined(MA_SUPPORT_NEON)
36591 static MA_INLINE void ma_pcm_f32_to_s24__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36592 {
36593  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
36594 }
36595 #endif
36596 
36597 MA_API void ma_pcm_f32_to_s24(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36598 {
36599 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36600  ma_pcm_f32_to_s24__reference(dst, src, count, ditherMode);
36601 #else
36602  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
36603  if (ma_has_avx2()) {
36604  ma_pcm_f32_to_s24__avx2(dst, src, count, ditherMode);
36605  } else
36606  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
36607  if (ma_has_sse2()) {
36608  ma_pcm_f32_to_s24__sse2(dst, src, count, ditherMode);
36609  } else
36610  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
36611  if (ma_has_neon()) {
36612  ma_pcm_f32_to_s24__neon(dst, src, count, ditherMode);
36613  } else
36614  #endif
36615  {
36616  ma_pcm_f32_to_s24__optimized(dst, src, count, ditherMode);
36617  }
36618 #endif
36619 }
36620 
36621 
36622 static MA_INLINE void ma_pcm_f32_to_s32__reference(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36623 {
36624  ma_int32* dst_s32 = (ma_int32*)dst;
36625  const float* src_f32 = (const float*)src;
36626 
36627  ma_uint32 i;
36628  for (i = 0; i < count; i += 1) {
36629  double x = src_f32[i];
36630  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
36631 
36632 #if 0
36633  /* The accurate way. */
36634  x = x + 1; /* -1..1 to 0..2 */
36635  x = x * 2147483647.5; /* 0..2 to 0..4294967295 */
36636  x = x - 2147483648.0; /* 0...4294967295 to -2147483648..2147483647 */
36637 #else
36638  /* The fast way. */
36639  x = x * 2147483647.0; /* -1..1 to -2147483647..2147483647 */
36640 #endif
36641 
36642  dst_s32[i] = (ma_int32)x;
36643  }
36644 
36645  (void)ditherMode; /* No dithering for f32 -> s32. */
36646 }
36647 
36648 static MA_INLINE void ma_pcm_f32_to_s32__optimized(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36649 {
36650  ma_pcm_f32_to_s32__reference(dst, src, count, ditherMode);
36651 }
36652 
36653 #if defined(MA_SUPPORT_SSE2)
36654 static MA_INLINE void ma_pcm_f32_to_s32__sse2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36655 {
36656  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
36657 }
36658 #endif
36659 #if defined(MA_SUPPORT_AVX2)
36660 static MA_INLINE void ma_pcm_f32_to_s32__avx2(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36661 {
36662  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
36663 }
36664 #endif
36665 #if defined(MA_SUPPORT_NEON)
36666 static MA_INLINE void ma_pcm_f32_to_s32__neon(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36667 {
36668  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
36669 }
36670 #endif
36671 
36672 MA_API void ma_pcm_f32_to_s32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36673 {
36674 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36675  ma_pcm_f32_to_s32__reference(dst, src, count, ditherMode);
36676 #else
36677  # if MA_PREFERRED_SIMD == MA_SIMD_AVX2
36678  if (ma_has_avx2()) {
36679  ma_pcm_f32_to_s32__avx2(dst, src, count, ditherMode);
36680  } else
36681  #elif MA_PREFERRED_SIMD == MA_SIMD_SSE2
36682  if (ma_has_sse2()) {
36683  ma_pcm_f32_to_s32__sse2(dst, src, count, ditherMode);
36684  } else
36685  #elif MA_PREFERRED_SIMD == MA_SIMD_NEON
36686  if (ma_has_neon()) {
36687  ma_pcm_f32_to_s32__neon(dst, src, count, ditherMode);
36688  } else
36689  #endif
36690  {
36691  ma_pcm_f32_to_s32__optimized(dst, src, count, ditherMode);
36692  }
36693 #endif
36694 }
36695 
36696 
36697 MA_API void ma_pcm_f32_to_f32(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode)
36698 {
36699  (void)ditherMode;
36700 
36701  ma_copy_memory_64(dst, src, count * sizeof(float));
36702 }
36703 
36704 
36705 static void ma_pcm_interleave_f32__reference(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
36706 {
36707  float* dst_f32 = (float*)dst;
36708  const float** src_f32 = (const float**)src;
36709 
36710  ma_uint64 iFrame;
36711  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
36712  ma_uint32 iChannel;
36713  for (iChannel = 0; iChannel < channels; iChannel += 1) {
36714  dst_f32[iFrame*channels + iChannel] = src_f32[iChannel][iFrame];
36715  }
36716  }
36717 }
36718 
36719 static void ma_pcm_interleave_f32__optimized(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
36720 {
36721  ma_pcm_interleave_f32__reference(dst, src, frameCount, channels);
36722 }
36723 
36724 MA_API void ma_pcm_interleave_f32(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels)
36725 {
36726 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36727  ma_pcm_interleave_f32__reference(dst, src, frameCount, channels);
36728 #else
36729  ma_pcm_interleave_f32__optimized(dst, src, frameCount, channels);
36730 #endif
36731 }
36732 
36733 
36734 static void ma_pcm_deinterleave_f32__reference(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
36735 {
36736  float** dst_f32 = (float**)dst;
36737  const float* src_f32 = (const float*)src;
36738 
36739  ma_uint64 iFrame;
36740  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
36741  ma_uint32 iChannel;
36742  for (iChannel = 0; iChannel < channels; iChannel += 1) {
36743  dst_f32[iChannel][iFrame] = src_f32[iFrame*channels + iChannel];
36744  }
36745  }
36746 }
36747 
36748 static void ma_pcm_deinterleave_f32__optimized(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
36749 {
36750  ma_pcm_deinterleave_f32__reference(dst, src, frameCount, channels);
36751 }
36752 
36753 MA_API void ma_pcm_deinterleave_f32(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels)
36754 {
36755 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
36756  ma_pcm_deinterleave_f32__reference(dst, src, frameCount, channels);
36757 #else
36758  ma_pcm_deinterleave_f32__optimized(dst, src, frameCount, channels);
36759 #endif
36760 }
36761 
36762 
36763 MA_API void ma_pcm_convert(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode)
36764 {
36765  if (formatOut == formatIn) {
36766  ma_copy_memory_64(pOut, pIn, sampleCount * ma_get_bytes_per_sample(formatOut));
36767  return;
36768  }
36769 
36770  switch (formatIn)
36771  {
36772  case ma_format_u8:
36773  {
36774  switch (formatOut)
36775  {
36776  case ma_format_s16: ma_pcm_u8_to_s16(pOut, pIn, sampleCount, ditherMode); return;
36777  case ma_format_s24: ma_pcm_u8_to_s24(pOut, pIn, sampleCount, ditherMode); return;
36778  case ma_format_s32: ma_pcm_u8_to_s32(pOut, pIn, sampleCount, ditherMode); return;
36779  case ma_format_f32: ma_pcm_u8_to_f32(pOut, pIn, sampleCount, ditherMode); return;
36780  default: break;
36781  }
36782  } break;
36783 
36784  case ma_format_s16:
36785  {
36786  switch (formatOut)
36787  {
36788  case ma_format_u8: ma_pcm_s16_to_u8( pOut, pIn, sampleCount, ditherMode); return;
36789  case ma_format_s24: ma_pcm_s16_to_s24(pOut, pIn, sampleCount, ditherMode); return;
36790  case ma_format_s32: ma_pcm_s16_to_s32(pOut, pIn, sampleCount, ditherMode); return;
36791  case ma_format_f32: ma_pcm_s16_to_f32(pOut, pIn, sampleCount, ditherMode); return;
36792  default: break;
36793  }
36794  } break;
36795 
36796  case ma_format_s24:
36797  {
36798  switch (formatOut)
36799  {
36800  case ma_format_u8: ma_pcm_s24_to_u8( pOut, pIn, sampleCount, ditherMode); return;
36801  case ma_format_s16: ma_pcm_s24_to_s16(pOut, pIn, sampleCount, ditherMode); return;
36802  case ma_format_s32: ma_pcm_s24_to_s32(pOut, pIn, sampleCount, ditherMode); return;
36803  case ma_format_f32: ma_pcm_s24_to_f32(pOut, pIn, sampleCount, ditherMode); return;
36804  default: break;
36805  }
36806  } break;
36807 
36808  case ma_format_s32:
36809  {
36810  switch (formatOut)
36811  {
36812  case ma_format_u8: ma_pcm_s32_to_u8( pOut, pIn, sampleCount, ditherMode); return;
36813  case ma_format_s16: ma_pcm_s32_to_s16(pOut, pIn, sampleCount, ditherMode); return;
36814  case ma_format_s24: ma_pcm_s32_to_s24(pOut, pIn, sampleCount, ditherMode); return;
36815  case ma_format_f32: ma_pcm_s32_to_f32(pOut, pIn, sampleCount, ditherMode); return;
36816  default: break;
36817  }
36818  } break;
36819 
36820  case ma_format_f32:
36821  {
36822  switch (formatOut)
36823  {
36824  case ma_format_u8: ma_pcm_f32_to_u8( pOut, pIn, sampleCount, ditherMode); return;
36825  case ma_format_s16: ma_pcm_f32_to_s16(pOut, pIn, sampleCount, ditherMode); return;
36826  case ma_format_s24: ma_pcm_f32_to_s24(pOut, pIn, sampleCount, ditherMode); return;
36827  case ma_format_s32: ma_pcm_f32_to_s32(pOut, pIn, sampleCount, ditherMode); return;
36828  default: break;
36829  }
36830  } break;
36831 
36832  default: break;
36833  }
36834 }
36835 
36836 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)
36837 {
36838  ma_pcm_convert(pOut, formatOut, pIn, formatIn, frameCount * channels, ditherMode);
36839 }
36840 
36841 MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void* pInterleavedPCMFrames, void** ppDeinterleavedPCMFrames)
36842 {
36843  if (pInterleavedPCMFrames == NULL || ppDeinterleavedPCMFrames == NULL) {
36844  return; /* Invalid args. */
36845  }
36846 
36847  /* For efficiency we do this per format. */
36848  switch (format) {
36849  case ma_format_s16:
36850  {
36851  const ma_int16* pSrcS16 = (const ma_int16*)pInterleavedPCMFrames;
36852  ma_uint64 iPCMFrame;
36853  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
36854  ma_uint32 iChannel;
36855  for (iChannel = 0; iChannel < channels; ++iChannel) {
36856  ma_int16* pDstS16 = (ma_int16*)ppDeinterleavedPCMFrames[iChannel];
36857  pDstS16[iPCMFrame] = pSrcS16[iPCMFrame*channels+iChannel];
36858  }
36859  }
36860  } break;
36861 
36862  case ma_format_f32:
36863  {
36864  const float* pSrcF32 = (const float*)pInterleavedPCMFrames;
36865  ma_uint64 iPCMFrame;
36866  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
36867  ma_uint32 iChannel;
36868  for (iChannel = 0; iChannel < channels; ++iChannel) {
36869  float* pDstF32 = (float*)ppDeinterleavedPCMFrames[iChannel];
36870  pDstF32[iPCMFrame] = pSrcF32[iPCMFrame*channels+iChannel];
36871  }
36872  }
36873  } break;
36874 
36875  default:
36876  {
36877  ma_uint32 sampleSizeInBytes = ma_get_bytes_per_sample(format);
36878  ma_uint64 iPCMFrame;
36879  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
36880  ma_uint32 iChannel;
36881  for (iChannel = 0; iChannel < channels; ++iChannel) {
36882  void* pDst = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
36883  const void* pSrc = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*channels+iChannel)*sampleSizeInBytes);
36884  memcpy(pDst, pSrc, sampleSizeInBytes);
36885  }
36886  }
36887  } break;
36888  }
36889 }
36890 
36891 MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void** ppDeinterleavedPCMFrames, void* pInterleavedPCMFrames)
36892 {
36893  switch (format)
36894  {
36895  case ma_format_s16:
36896  {
36897  ma_int16* pDstS16 = (ma_int16*)pInterleavedPCMFrames;
36898  ma_uint64 iPCMFrame;
36899  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
36900  ma_uint32 iChannel;
36901  for (iChannel = 0; iChannel < channels; ++iChannel) {
36902  const ma_int16* pSrcS16 = (const ma_int16*)ppDeinterleavedPCMFrames[iChannel];
36903  pDstS16[iPCMFrame*channels+iChannel] = pSrcS16[iPCMFrame];
36904  }
36905  }
36906  } break;
36907 
36908  case ma_format_f32:
36909  {
36910  float* pDstF32 = (float*)pInterleavedPCMFrames;
36911  ma_uint64 iPCMFrame;
36912  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
36913  ma_uint32 iChannel;
36914  for (iChannel = 0; iChannel < channels; ++iChannel) {
36915  const float* pSrcF32 = (const float*)ppDeinterleavedPCMFrames[iChannel];
36916  pDstF32[iPCMFrame*channels+iChannel] = pSrcF32[iPCMFrame];
36917  }
36918  }
36919  } break;
36920 
36921  default:
36922  {
36923  ma_uint32 sampleSizeInBytes = ma_get_bytes_per_sample(format);
36924  ma_uint64 iPCMFrame;
36925  for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
36926  ma_uint32 iChannel;
36927  for (iChannel = 0; iChannel < channels; ++iChannel) {
36928  void* pDst = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*channels+iChannel)*sampleSizeInBytes);
36929  const void* pSrc = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
36930  memcpy(pDst, pSrc, sampleSizeInBytes);
36931  }
36932  }
36933  } break;
36934  }
36935 }
36936 
36937 
36938 /**************************************************************************************************************************************************************
36939 
36940 Biquad Filter
36941 
36942 **************************************************************************************************************************************************************/
36943 #ifndef MA_BIQUAD_FIXED_POINT_SHIFT
36944 #define MA_BIQUAD_FIXED_POINT_SHIFT 14
36945 #endif
36946 
36947 static ma_int32 ma_biquad_float_to_fp(double x)
36948 {
36949  return (ma_int32)(x * (1 << MA_BIQUAD_FIXED_POINT_SHIFT));
36950 }
36951 
36952 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)
36953 {
36955 
36957  config.format = format;
36958  config.channels = channels;
36959  config.b0 = b0;
36960  config.b1 = b1;
36961  config.b2 = b2;
36962  config.a0 = a0;
36963  config.a1 = a1;
36964  config.a2 = a2;
36965 
36966  return config;
36967 }
36968 
36970 {
36971  if (pBQ == NULL) {
36972  return MA_INVALID_ARGS;
36973  }
36974 
36975  MA_ZERO_OBJECT(pBQ);
36976 
36977  if (pConfig == NULL) {
36978  return MA_INVALID_ARGS;
36979  }
36980 
36981  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
36982  return MA_INVALID_ARGS;
36983  }
36984 
36985  return ma_biquad_reinit(pConfig, pBQ);
36986 }
36987 
36989 {
36990  if (pBQ == NULL || pConfig == NULL) {
36991  return MA_INVALID_ARGS;
36992  }
36993 
36994  if (pConfig->a0 == 0) {
36995  return MA_INVALID_ARGS; /* Division by zero. */
36996  }
36997 
36998  /* Only supporting f32 and s16. */
36999  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
37000  return MA_INVALID_ARGS;
37001  }
37002 
37003  /* The format cannot be changed after initialization. */
37004  if (pBQ->format != ma_format_unknown && pBQ->format != pConfig->format) {
37005  return MA_INVALID_OPERATION;
37006  }
37007 
37008  /* The channel count cannot be changed after initialization. */
37009  if (pBQ->channels != 0 && pBQ->channels != pConfig->channels) {
37010  return MA_INVALID_OPERATION;
37011  }
37012 
37013 
37014  pBQ->format = pConfig->format;
37015  pBQ->channels = pConfig->channels;
37016 
37017  /* Normalize. */
37018  if (pConfig->format == ma_format_f32) {
37019  pBQ->b0.f32 = (float)(pConfig->b0 / pConfig->a0);
37020  pBQ->b1.f32 = (float)(pConfig->b1 / pConfig->a0);
37021  pBQ->b2.f32 = (float)(pConfig->b2 / pConfig->a0);
37022  pBQ->a1.f32 = (float)(pConfig->a1 / pConfig->a0);
37023  pBQ->a2.f32 = (float)(pConfig->a2 / pConfig->a0);
37024  } else {
37025  pBQ->b0.s32 = ma_biquad_float_to_fp(pConfig->b0 / pConfig->a0);
37026  pBQ->b1.s32 = ma_biquad_float_to_fp(pConfig->b1 / pConfig->a0);
37027  pBQ->b2.s32 = ma_biquad_float_to_fp(pConfig->b2 / pConfig->a0);
37028  pBQ->a1.s32 = ma_biquad_float_to_fp(pConfig->a1 / pConfig->a0);
37029  pBQ->a2.s32 = ma_biquad_float_to_fp(pConfig->a2 / pConfig->a0);
37030  }
37031 
37032  return MA_SUCCESS;
37033 }
37034 
37035 static MA_INLINE void ma_biquad_process_pcm_frame_f32__direct_form_2_transposed(ma_biquad* pBQ, float* pY, const float* pX)
37036 {
37037  ma_uint32 c;
37038  const ma_uint32 channels = pBQ->channels;
37039  const float b0 = pBQ->b0.f32;
37040  const float b1 = pBQ->b1.f32;
37041  const float b2 = pBQ->b2.f32;
37042  const float a1 = pBQ->a1.f32;
37043  const float a2 = pBQ->a2.f32;
37044 
37045  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
37046  for (c = 0; c < channels; c += 1) {
37047  float r1 = pBQ->r1[c].f32;
37048  float r2 = pBQ->r2[c].f32;
37049  float x = pX[c];
37050  float y;
37051 
37052  y = b0*x + r1;
37053  r1 = b1*x - a1*y + r2;
37054  r2 = b2*x - a2*y;
37055 
37056  pY[c] = y;
37057  pBQ->r1[c].f32 = r1;
37058  pBQ->r2[c].f32 = r2;
37059  }
37060 }
37061 
37062 static MA_INLINE void ma_biquad_process_pcm_frame_f32(ma_biquad* pBQ, float* pY, const float* pX)
37063 {
37065 }
37066 
37068 {
37069  ma_uint32 c;
37070  const ma_uint32 channels = pBQ->channels;
37071  const ma_int32 b0 = pBQ->b0.s32;
37072  const ma_int32 b1 = pBQ->b1.s32;
37073  const ma_int32 b2 = pBQ->b2.s32;
37074  const ma_int32 a1 = pBQ->a1.s32;
37075  const ma_int32 a2 = pBQ->a2.s32;
37076 
37077  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
37078  for (c = 0; c < channels; c += 1) {
37079  ma_int32 r1 = pBQ->r1[c].s32;
37080  ma_int32 r2 = pBQ->r2[c].s32;
37081  ma_int32 x = pX[c];
37082  ma_int32 y;
37083 
37084  y = (b0*x + r1) >> MA_BIQUAD_FIXED_POINT_SHIFT;
37085  r1 = (b1*x - a1*y + r2);
37086  r2 = (b2*x - a2*y);
37087 
37088  pY[c] = (ma_int16)ma_clamp(y, -32768, 32767);
37089  pBQ->r1[c].s32 = r1;
37090  pBQ->r2[c].s32 = r2;
37091  }
37092 }
37093 
37094 static MA_INLINE void ma_biquad_process_pcm_frame_s16(ma_biquad* pBQ, ma_int16* pY, const ma_int16* pX)
37095 {
37097 }
37098 
37099 MA_API ma_result ma_biquad_process_pcm_frames(ma_biquad* pBQ, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
37100 {
37101  ma_uint32 n;
37102 
37103  if (pBQ == NULL || pFramesOut == NULL || pFramesIn == NULL) {
37104  return MA_INVALID_ARGS;
37105  }
37106 
37107  /* 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. */
37108 
37109  if (pBQ->format == ma_format_f32) {
37110  /* */ float* pY = ( float*)pFramesOut;
37111  const float* pX = (const float*)pFramesIn;
37112 
37113  for (n = 0; n < frameCount; n += 1) {
37115  pY += pBQ->channels;
37116  pX += pBQ->channels;
37117  }
37118  } else if (pBQ->format == ma_format_s16) {
37119  /* */ ma_int16* pY = ( ma_int16*)pFramesOut;
37120  const ma_int16* pX = (const ma_int16*)pFramesIn;
37121 
37122  for (n = 0; n < frameCount; n += 1) {
37124  pY += pBQ->channels;
37125  pX += pBQ->channels;
37126  }
37127  } else {
37129  return MA_INVALID_ARGS; /* Format not supported. Should never hit this because it's checked in ma_biquad_init() and ma_biquad_reinit(). */
37130  }
37131 
37132  return MA_SUCCESS;
37133 }
37134 
37136 {
37137  if (pBQ == NULL) {
37138  return 0;
37139  }
37140 
37141  return 2;
37142 }
37143 
37144 
37145 /**************************************************************************************************************************************************************
37146 
37147 Low-Pass Filter
37148 
37149 **************************************************************************************************************************************************************/
37150 MA_API ma_lpf1_config ma_lpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency)
37151 {
37153 
37155  config.format = format;
37156  config.channels = channels;
37157  config.sampleRate = sampleRate;
37158  config.cutoffFrequency = cutoffFrequency;
37159  config.q = 0.5;
37160 
37161  return config;
37162 }
37163 
37164 MA_API ma_lpf2_config ma_lpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
37165 {
37167 
37169  config.format = format;
37170  config.channels = channels;
37171  config.sampleRate = sampleRate;
37172  config.cutoffFrequency = cutoffFrequency;
37173  config.q = q;
37174 
37175  /* Q cannot be 0 or else it'll result in a division by 0. In this case just default to 0.707107. */
37176  if (config.q == 0) {
37177  config.q = 0.707107;
37178  }
37179 
37180  return config;
37181 }
37182 
37183 
37184 MA_API ma_result ma_lpf1_init(const ma_lpf1_config* pConfig, ma_lpf1* pLPF)
37185 {
37186  if (pLPF == NULL) {
37187  return MA_INVALID_ARGS;
37188  }
37189 
37190  MA_ZERO_OBJECT(pLPF);
37191 
37192  if (pConfig == NULL) {
37193  return MA_INVALID_ARGS;
37194  }
37195 
37196  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
37197  return MA_INVALID_ARGS;
37198  }
37199 
37200  return ma_lpf1_reinit(pConfig, pLPF);
37201 }
37202 
37203 MA_API ma_result ma_lpf1_reinit(const ma_lpf1_config* pConfig, ma_lpf1* pLPF)
37204 {
37205  double a;
37206 
37207  if (pLPF == NULL || pConfig == NULL) {
37208  return MA_INVALID_ARGS;
37209  }
37210 
37211  /* Only supporting f32 and s16. */
37212  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
37213  return MA_INVALID_ARGS;
37214  }
37215 
37216  /* The format cannot be changed after initialization. */
37217  if (pLPF->format != ma_format_unknown && pLPF->format != pConfig->format) {
37218  return MA_INVALID_OPERATION;
37219  }
37220 
37221  /* The channel count cannot be changed after initialization. */
37222  if (pLPF->channels != 0 && pLPF->channels != pConfig->channels) {
37223  return MA_INVALID_OPERATION;
37224  }
37225 
37226  pLPF->format = pConfig->format;
37227  pLPF->channels = pConfig->channels;
37228 
37229  a = ma_expd(-2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate);
37230  if (pConfig->format == ma_format_f32) {
37231  pLPF->a.f32 = (float)a;
37232  } else {
37233  pLPF->a.s32 = ma_biquad_float_to_fp(a);
37234  }
37235 
37236  return MA_SUCCESS;
37237 }
37238 
37239 static MA_INLINE void ma_lpf1_process_pcm_frame_f32(ma_lpf1* pLPF, float* pY, const float* pX)
37240 {
37241  ma_uint32 c;
37242  const ma_uint32 channels = pLPF->channels;
37243  const float a = pLPF->a.f32;
37244  const float b = 1 - a;
37245 
37246  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
37247  for (c = 0; c < channels; c += 1) {
37248  float r1 = pLPF->r1[c].f32;
37249  float x = pX[c];
37250  float y;
37251 
37252  y = b*x + a*r1;
37253 
37254  pY[c] = y;
37255  pLPF->r1[c].f32 = y;
37256  }
37257 }
37258 
37259 static MA_INLINE void ma_lpf1_process_pcm_frame_s16(ma_lpf1* pLPF, ma_int16* pY, const ma_int16* pX)
37260 {
37261  ma_uint32 c;
37262  const ma_uint32 channels = pLPF->channels;
37263  const ma_int32 a = pLPF->a.s32;
37264  const ma_int32 b = ((1 << MA_BIQUAD_FIXED_POINT_SHIFT) - a);
37265 
37266  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
37267  for (c = 0; c < channels; c += 1) {
37268  ma_int32 r1 = pLPF->r1[c].s32;
37269  ma_int32 x = pX[c];
37270  ma_int32 y;
37271 
37272  y = (b*x + a*r1) >> MA_BIQUAD_FIXED_POINT_SHIFT;
37273 
37274  pY[c] = (ma_int16)y;
37275  pLPF->r1[c].s32 = (ma_int32)y;
37276  }
37277 }
37278 
37279 MA_API ma_result ma_lpf1_process_pcm_frames(ma_lpf1* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
37280 {
37281  ma_uint32 n;
37282 
37283  if (pLPF == NULL || pFramesOut == NULL || pFramesIn == NULL) {
37284  return MA_INVALID_ARGS;
37285  }
37286 
37287  /* 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. */
37288 
37289  if (pLPF->format == ma_format_f32) {
37290  /* */ float* pY = ( float*)pFramesOut;
37291  const float* pX = (const float*)pFramesIn;
37292 
37293  for (n = 0; n < frameCount; n += 1) {
37294  ma_lpf1_process_pcm_frame_f32(pLPF, pY, pX);
37295  pY += pLPF->channels;
37296  pX += pLPF->channels;
37297  }
37298  } else if (pLPF->format == ma_format_s16) {
37299  /* */ ma_int16* pY = ( ma_int16*)pFramesOut;
37300  const ma_int16* pX = (const ma_int16*)pFramesIn;
37301 
37302  for (n = 0; n < frameCount; n += 1) {
37303  ma_lpf1_process_pcm_frame_s16(pLPF, pY, pX);
37304  pY += pLPF->channels;
37305  pX += pLPF->channels;
37306  }
37307  } else {
37309  return MA_INVALID_ARGS; /* Format not supported. Should never hit this because it's checked in ma_biquad_init() and ma_biquad_reinit(). */
37310  }
37311 
37312  return MA_SUCCESS;
37313 }
37314 
37316 {
37317  if (pLPF == NULL) {
37318  return 0;
37319  }
37320 
37321  return 1;
37322 }
37323 
37324 
37326 {
37327  ma_biquad_config bqConfig;
37328  double q;
37329  double w;
37330  double s;
37331  double c;
37332  double a;
37333 
37334  MA_ASSERT(pConfig != NULL);
37335 
37336  q = pConfig->q;
37337  w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
37338  s = ma_sind(w);
37339  c = ma_cosd(w);
37340  a = s / (2*q);
37341 
37342  bqConfig.b0 = (1 - c) / 2;
37343  bqConfig.b1 = 1 - c;
37344  bqConfig.b2 = (1 - c) / 2;
37345  bqConfig.a0 = 1 + a;
37346  bqConfig.a1 = -2 * c;
37347  bqConfig.a2 = 1 - a;
37348 
37349  bqConfig.format = pConfig->format;
37350  bqConfig.channels = pConfig->channels;
37351 
37352  return bqConfig;
37353 }
37354 
37355 MA_API ma_result ma_lpf2_init(const ma_lpf2_config* pConfig, ma_lpf2* pLPF)
37356 {
37357  ma_result result;
37358  ma_biquad_config bqConfig;
37359 
37360  if (pLPF == NULL) {
37361  return MA_INVALID_ARGS;
37362  }
37363 
37364  MA_ZERO_OBJECT(pLPF);
37365 
37366  if (pConfig == NULL) {
37367  return MA_INVALID_ARGS;
37368  }
37369 
37370  bqConfig = ma_lpf2__get_biquad_config(pConfig);
37371  result = ma_biquad_init(&bqConfig, &pLPF->bq);
37372  if (result != MA_SUCCESS) {
37373  return result;
37374  }
37375 
37376  return MA_SUCCESS;
37377 }
37378 
37379 MA_API ma_result ma_lpf2_reinit(const ma_lpf2_config* pConfig, ma_lpf2* pLPF)
37380 {
37381  ma_result result;
37382  ma_biquad_config bqConfig;
37383 
37384  if (pLPF == NULL || pConfig == NULL) {
37385  return MA_INVALID_ARGS;
37386  }
37387 
37388  bqConfig = ma_lpf2__get_biquad_config(pConfig);
37389  result = ma_biquad_reinit(&bqConfig, &pLPF->bq);
37390  if (result != MA_SUCCESS) {
37391  return result;
37392  }
37393 
37394  return MA_SUCCESS;
37395 }
37396 
37397 static MA_INLINE void ma_lpf2_process_pcm_frame_s16(ma_lpf2* pLPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
37398 {
37399  ma_biquad_process_pcm_frame_s16(&pLPF->bq, pFrameOut, pFrameIn);
37400 }
37401 
37402 static MA_INLINE void ma_lpf2_process_pcm_frame_f32(ma_lpf2* pLPF, float* pFrameOut, const float* pFrameIn)
37403 {
37404  ma_biquad_process_pcm_frame_f32(&pLPF->bq, pFrameOut, pFrameIn);
37405 }
37406 
37407 MA_API ma_result ma_lpf2_process_pcm_frames(ma_lpf2* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
37408 {
37409  if (pLPF == NULL) {
37410  return MA_INVALID_ARGS;
37411  }
37412 
37413  return ma_biquad_process_pcm_frames(&pLPF->bq, pFramesOut, pFramesIn, frameCount);
37414 }
37415 
37417 {
37418  if (pLPF == NULL) {
37419  return 0;
37420  }
37421 
37422  return ma_biquad_get_latency(&pLPF->bq);
37423 }
37424 
37425 
37426 MA_API ma_lpf_config ma_lpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
37427 {
37429 
37431  config.format = format;
37432  config.channels = channels;
37433  config.sampleRate = sampleRate;
37434  config.cutoffFrequency = cutoffFrequency;
37435  config.order = ma_min(order, MA_MAX_FILTER_ORDER);
37436 
37437  return config;
37438 }
37439 
37440 static ma_result ma_lpf_reinit__internal(const ma_lpf_config* pConfig, ma_lpf* pLPF, ma_bool32 isNew)
37441 {
37442  ma_result result;
37443  ma_uint32 lpf1Count;
37444  ma_uint32 lpf2Count;
37445  ma_uint32 ilpf1;
37446  ma_uint32 ilpf2;
37447 
37448  if (pLPF == NULL || pConfig == NULL) {
37449  return MA_INVALID_ARGS;
37450  }
37451 
37452  /* Only supporting f32 and s16. */
37453  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
37454  return MA_INVALID_ARGS;
37455  }
37456 
37457  /* The format cannot be changed after initialization. */
37458  if (pLPF->format != ma_format_unknown && pLPF->format != pConfig->format) {
37459  return MA_INVALID_OPERATION;
37460  }
37461 
37462  /* The channel count cannot be changed after initialization. */
37463  if (pLPF->channels != 0 && pLPF->channels != pConfig->channels) {
37464  return MA_INVALID_OPERATION;
37465  }
37466 
37467  if (pConfig->order > MA_MAX_FILTER_ORDER) {
37468  return MA_INVALID_ARGS;
37469  }
37470 
37471  lpf1Count = pConfig->order % 2;
37472  lpf2Count = pConfig->order / 2;
37473 
37474  MA_ASSERT(lpf1Count <= ma_countof(pLPF->lpf1));
37475  MA_ASSERT(lpf2Count <= ma_countof(pLPF->lpf2));
37476 
37477  /* The filter order can't change between reinits. */
37478  if (!isNew) {
37479  if (pLPF->lpf1Count != lpf1Count || pLPF->lpf2Count != lpf2Count) {
37480  return MA_INVALID_OPERATION;
37481  }
37482  }
37483 
37484  for (ilpf1 = 0; ilpf1 < lpf1Count; ilpf1 += 1) {
37485  ma_lpf1_config lpf1Config = ma_lpf1_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency);
37486 
37487  if (isNew) {
37488  result = ma_lpf1_init(&lpf1Config, &pLPF->lpf1[ilpf1]);
37489  } else {
37490  result = ma_lpf1_reinit(&lpf1Config, &pLPF->lpf1[ilpf1]);
37491  }
37492 
37493  if (result != MA_SUCCESS) {
37494  return result;
37495  }
37496  }
37497 
37498  for (ilpf2 = 0; ilpf2 < lpf2Count; ilpf2 += 1) {
37499  ma_lpf2_config lpf2Config;
37500  double q;
37501  double a;
37502 
37503  /* Tempting to use 0.707107, but won't result in a Butterworth filter if the order is > 2. */
37504  if (lpf1Count == 1) {
37505  a = (1 + ilpf2*1) * (MA_PI_D/(pConfig->order*1)); /* Odd order. */
37506  } else {
37507  a = (1 + ilpf2*2) * (MA_PI_D/(pConfig->order*2)); /* Even order. */
37508  }
37509  q = 1 / (2*ma_cosd(a));
37510 
37511  lpf2Config = ma_lpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
37512 
37513  if (isNew) {
37514  result = ma_lpf2_init(&lpf2Config, &pLPF->lpf2[ilpf2]);
37515  } else {
37516  result = ma_lpf2_reinit(&lpf2Config, &pLPF->lpf2[ilpf2]);
37517  }
37518 
37519  if (result != MA_SUCCESS) {
37520  return result;
37521  }
37522  }
37523 
37524  pLPF->lpf1Count = lpf1Count;
37525  pLPF->lpf2Count = lpf2Count;
37526  pLPF->format = pConfig->format;
37527  pLPF->channels = pConfig->channels;
37528  pLPF->sampleRate = pConfig->sampleRate;
37529 
37530  return MA_SUCCESS;
37531 }
37532 
37533 MA_API ma_result ma_lpf_init(const ma_lpf_config* pConfig, ma_lpf* pLPF)
37534 {
37535  if (pLPF == NULL) {
37536  return MA_INVALID_ARGS;
37537  }
37538 
37539  MA_ZERO_OBJECT(pLPF);
37540 
37541  if (pConfig == NULL) {
37542  return MA_INVALID_ARGS;
37543  }
37544 
37545  return ma_lpf_reinit__internal(pConfig, pLPF, /*isNew*/MA_TRUE);
37546 }
37547 
37548 MA_API ma_result ma_lpf_reinit(const ma_lpf_config* pConfig, ma_lpf* pLPF)
37549 {
37550  return ma_lpf_reinit__internal(pConfig, pLPF, /*isNew*/MA_FALSE);
37551 }
37552 
37553 static MA_INLINE void ma_lpf_process_pcm_frame_f32(ma_lpf* pLPF, float* pY, const void* pX)
37554 {
37555  ma_uint32 ilpf1;
37556  ma_uint32 ilpf2;
37557 
37558  MA_ASSERT(pLPF->format == ma_format_f32);
37559 
37560  MA_COPY_MEMORY(pY, pX, ma_get_bytes_per_frame(pLPF->format, pLPF->channels));
37561 
37562  for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
37563  ma_lpf1_process_pcm_frame_f32(&pLPF->lpf1[ilpf1], pY, pY);
37564  }
37565 
37566  for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
37567  ma_lpf2_process_pcm_frame_f32(&pLPF->lpf2[ilpf2], pY, pY);
37568  }
37569 }
37570 
37571 static MA_INLINE void ma_lpf_process_pcm_frame_s16(ma_lpf* pLPF, ma_int16* pY, const ma_int16* pX)
37572 {
37573  ma_uint32 ilpf1;
37574  ma_uint32 ilpf2;
37575 
37576  MA_ASSERT(pLPF->format == ma_format_s16);
37577 
37578  MA_COPY_MEMORY(pY, pX, ma_get_bytes_per_frame(pLPF->format, pLPF->channels));
37579 
37580  for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
37581  ma_lpf1_process_pcm_frame_s16(&pLPF->lpf1[ilpf1], pY, pY);
37582  }
37583 
37584  for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
37585  ma_lpf2_process_pcm_frame_s16(&pLPF->lpf2[ilpf2], pY, pY);
37586  }
37587 }
37588 
37589 MA_API ma_result ma_lpf_process_pcm_frames(ma_lpf* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
37590 {
37591  ma_result result;
37592  ma_uint32 ilpf1;
37593  ma_uint32 ilpf2;
37594 
37595  if (pLPF == NULL) {
37596  return MA_INVALID_ARGS;
37597  }
37598 
37599  /* Faster path for in-place. */
37600  if (pFramesOut == pFramesIn) {
37601  for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
37602  result = ma_lpf1_process_pcm_frames(&pLPF->lpf1[ilpf1], pFramesOut, pFramesOut, frameCount);
37603  if (result != MA_SUCCESS) {
37604  return result;
37605  }
37606  }
37607 
37608  for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
37609  result = ma_lpf2_process_pcm_frames(&pLPF->lpf2[ilpf2], pFramesOut, pFramesOut, frameCount);
37610  if (result != MA_SUCCESS) {
37611  return result;
37612  }
37613  }
37614  }
37615 
37616  /* Slightly slower path for copying. */
37617  if (pFramesOut != pFramesIn) {
37618  ma_uint32 iFrame;
37619 
37620  /* */ if (pLPF->format == ma_format_f32) {
37621  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
37622  const float* pFramesInF32 = (const float*)pFramesIn;
37623 
37624  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
37625  ma_lpf_process_pcm_frame_f32(pLPF, pFramesOutF32, pFramesInF32);
37626  pFramesOutF32 += pLPF->channels;
37627  pFramesInF32 += pLPF->channels;
37628  }
37629  } else if (pLPF->format == ma_format_s16) {
37630  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
37631  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
37632 
37633  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
37634  ma_lpf_process_pcm_frame_s16(pLPF, pFramesOutS16, pFramesInS16);
37635  pFramesOutS16 += pLPF->channels;
37636  pFramesInS16 += pLPF->channels;
37637  }
37638  } else {
37640  return MA_INVALID_OPERATION; /* Should never hit this. */
37641  }
37642  }
37643 
37644  return MA_SUCCESS;
37645 }
37646 
37648 {
37649  if (pLPF == NULL) {
37650  return 0;
37651  }
37652 
37653  return pLPF->lpf2Count*2 + pLPF->lpf1Count;
37654 }
37655 
37656 
37657 /**************************************************************************************************************************************************************
37658 
37659 High-Pass Filtering
37660 
37661 **************************************************************************************************************************************************************/
37662 MA_API ma_hpf1_config ma_hpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency)
37663 {
37665 
37667  config.format = format;
37668  config.channels = channels;
37669  config.sampleRate = sampleRate;
37670  config.cutoffFrequency = cutoffFrequency;
37671 
37672  return config;
37673 }
37674 
37675 MA_API ma_hpf2_config ma_hpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
37676 {
37678 
37680  config.format = format;
37681  config.channels = channels;
37682  config.sampleRate = sampleRate;
37683  config.cutoffFrequency = cutoffFrequency;
37684  config.q = q;
37685 
37686  /* Q cannot be 0 or else it'll result in a division by 0. In this case just default to 0.707107. */
37687  if (config.q == 0) {
37688  config.q = 0.707107;
37689  }
37690 
37691  return config;
37692 }
37693 
37694 
37695 MA_API ma_result ma_hpf1_init(const ma_hpf1_config* pConfig, ma_hpf1* pHPF)
37696 {
37697  if (pHPF == NULL) {
37698  return MA_INVALID_ARGS;
37699  }
37700 
37701  MA_ZERO_OBJECT(pHPF);
37702 
37703  if (pConfig == NULL) {
37704  return MA_INVALID_ARGS;
37705  }
37706 
37707  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
37708  return MA_INVALID_ARGS;
37709  }
37710 
37711  return ma_hpf1_reinit(pConfig, pHPF);
37712 }
37713 
37714 MA_API ma_result ma_hpf1_reinit(const ma_hpf1_config* pConfig, ma_hpf1* pHPF)
37715 {
37716  double a;
37717 
37718  if (pHPF == NULL || pConfig == NULL) {
37719  return MA_INVALID_ARGS;
37720  }
37721 
37722  /* Only supporting f32 and s16. */
37723  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
37724  return MA_INVALID_ARGS;
37725  }
37726 
37727  /* The format cannot be changed after initialization. */
37728  if (pHPF->format != ma_format_unknown && pHPF->format != pConfig->format) {
37729  return MA_INVALID_OPERATION;
37730  }
37731 
37732  /* The channel count cannot be changed after initialization. */
37733  if (pHPF->channels != 0 && pHPF->channels != pConfig->channels) {
37734  return MA_INVALID_OPERATION;
37735  }
37736 
37737  pHPF->format = pConfig->format;
37738  pHPF->channels = pConfig->channels;
37739 
37740  a = ma_expd(-2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate);
37741  if (pConfig->format == ma_format_f32) {
37742  pHPF->a.f32 = (float)a;
37743  } else {
37744  pHPF->a.s32 = ma_biquad_float_to_fp(a);
37745  }
37746 
37747  return MA_SUCCESS;
37748 }
37749 
37750 static MA_INLINE void ma_hpf1_process_pcm_frame_f32(ma_hpf1* pHPF, float* pY, const float* pX)
37751 {
37752  ma_uint32 c;
37753  const ma_uint32 channels = pHPF->channels;
37754  const float a = 1 - pHPF->a.f32;
37755  const float b = 1 - a;
37756 
37757  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
37758  for (c = 0; c < channels; c += 1) {
37759  float r1 = pHPF->r1[c].f32;
37760  float x = pX[c];
37761  float y;
37762 
37763  y = b*x - a*r1;
37764 
37765  pY[c] = y;
37766  pHPF->r1[c].f32 = y;
37767  }
37768 }
37769 
37770 static MA_INLINE void ma_hpf1_process_pcm_frame_s16(ma_hpf1* pHPF, ma_int16* pY, const ma_int16* pX)
37771 {
37772  ma_uint32 c;
37773  const ma_uint32 channels = pHPF->channels;
37774  const ma_int32 a = ((1 << MA_BIQUAD_FIXED_POINT_SHIFT) - pHPF->a.s32);
37775  const ma_int32 b = ((1 << MA_BIQUAD_FIXED_POINT_SHIFT) - a);
37776 
37777  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
37778  for (c = 0; c < channels; c += 1) {
37779  ma_int32 r1 = pHPF->r1[c].s32;
37780  ma_int32 x = pX[c];
37781  ma_int32 y;
37782 
37783  y = (b*x - a*r1) >> MA_BIQUAD_FIXED_POINT_SHIFT;
37784 
37785  pY[c] = (ma_int16)y;
37786  pHPF->r1[c].s32 = (ma_int32)y;
37787  }
37788 }
37789 
37790 MA_API ma_result ma_hpf1_process_pcm_frames(ma_hpf1* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
37791 {
37792  ma_uint32 n;
37793 
37794  if (pHPF == NULL || pFramesOut == NULL || pFramesIn == NULL) {
37795  return MA_INVALID_ARGS;
37796  }
37797 
37798  /* 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. */
37799 
37800  if (pHPF->format == ma_format_f32) {
37801  /* */ float* pY = ( float*)pFramesOut;
37802  const float* pX = (const float*)pFramesIn;
37803 
37804  for (n = 0; n < frameCount; n += 1) {
37805  ma_hpf1_process_pcm_frame_f32(pHPF, pY, pX);
37806  pY += pHPF->channels;
37807  pX += pHPF->channels;
37808  }
37809  } else if (pHPF->format == ma_format_s16) {
37810  /* */ ma_int16* pY = ( ma_int16*)pFramesOut;
37811  const ma_int16* pX = (const ma_int16*)pFramesIn;
37812 
37813  for (n = 0; n < frameCount; n += 1) {
37814  ma_hpf1_process_pcm_frame_s16(pHPF, pY, pX);
37815  pY += pHPF->channels;
37816  pX += pHPF->channels;
37817  }
37818  } else {
37820  return MA_INVALID_ARGS; /* Format not supported. Should never hit this because it's checked in ma_biquad_init() and ma_biquad_reinit(). */
37821  }
37822 
37823  return MA_SUCCESS;
37824 }
37825 
37827 {
37828  if (pHPF == NULL) {
37829  return 0;
37830  }
37831 
37832  return 1;
37833 }
37834 
37835 
37837 {
37838  ma_biquad_config bqConfig;
37839  double q;
37840  double w;
37841  double s;
37842  double c;
37843  double a;
37844 
37845  MA_ASSERT(pConfig != NULL);
37846 
37847  q = pConfig->q;
37848  w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
37849  s = ma_sind(w);
37850  c = ma_cosd(w);
37851  a = s / (2*q);
37852 
37853  bqConfig.b0 = (1 + c) / 2;
37854  bqConfig.b1 = -(1 + c);
37855  bqConfig.b2 = (1 + c) / 2;
37856  bqConfig.a0 = 1 + a;
37857  bqConfig.a1 = -2 * c;
37858  bqConfig.a2 = 1 - a;
37859 
37860  bqConfig.format = pConfig->format;
37861  bqConfig.channels = pConfig->channels;
37862 
37863  return bqConfig;
37864 }
37865 
37866 MA_API ma_result ma_hpf2_init(const ma_hpf2_config* pConfig, ma_hpf2* pHPF)
37867 {
37868  ma_result result;
37869  ma_biquad_config bqConfig;
37870 
37871  if (pHPF == NULL) {
37872  return MA_INVALID_ARGS;
37873  }
37874 
37875  MA_ZERO_OBJECT(pHPF);
37876 
37877  if (pConfig == NULL) {
37878  return MA_INVALID_ARGS;
37879  }
37880 
37881  bqConfig = ma_hpf2__get_biquad_config(pConfig);
37882  result = ma_biquad_init(&bqConfig, &pHPF->bq);
37883  if (result != MA_SUCCESS) {
37884  return result;
37885  }
37886 
37887  return MA_SUCCESS;
37888 }
37889 
37890 MA_API ma_result ma_hpf2_reinit(const ma_hpf2_config* pConfig, ma_hpf2* pHPF)
37891 {
37892  ma_result result;
37893  ma_biquad_config bqConfig;
37894 
37895  if (pHPF == NULL || pConfig == NULL) {
37896  return MA_INVALID_ARGS;
37897  }
37898 
37899  bqConfig = ma_hpf2__get_biquad_config(pConfig);
37900  result = ma_biquad_reinit(&bqConfig, &pHPF->bq);
37901  if (result != MA_SUCCESS) {
37902  return result;
37903  }
37904 
37905  return MA_SUCCESS;
37906 }
37907 
37908 static MA_INLINE void ma_hpf2_process_pcm_frame_s16(ma_hpf2* pHPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
37909 {
37910  ma_biquad_process_pcm_frame_s16(&pHPF->bq, pFrameOut, pFrameIn);
37911 }
37912 
37913 static MA_INLINE void ma_hpf2_process_pcm_frame_f32(ma_hpf2* pHPF, float* pFrameOut, const float* pFrameIn)
37914 {
37915  ma_biquad_process_pcm_frame_f32(&pHPF->bq, pFrameOut, pFrameIn);
37916 }
37917 
37918 MA_API ma_result ma_hpf2_process_pcm_frames(ma_hpf2* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
37919 {
37920  if (pHPF == NULL) {
37921  return MA_INVALID_ARGS;
37922  }
37923 
37924  return ma_biquad_process_pcm_frames(&pHPF->bq, pFramesOut, pFramesIn, frameCount);
37925 }
37926 
37928 {
37929  if (pHPF == NULL) {
37930  return 0;
37931  }
37932 
37933  return ma_biquad_get_latency(&pHPF->bq);
37934 }
37935 
37936 
37937 MA_API ma_hpf_config ma_hpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
37938 {
37940 
37942  config.format = format;
37943  config.channels = channels;
37944  config.sampleRate = sampleRate;
37945  config.cutoffFrequency = cutoffFrequency;
37946  config.order = ma_min(order, MA_MAX_FILTER_ORDER);
37947 
37948  return config;
37949 }
37950 
37951 static ma_result ma_hpf_reinit__internal(const ma_hpf_config* pConfig, ma_hpf* pHPF, ma_bool32 isNew)
37952 {
37953  ma_result result;
37954  ma_uint32 hpf1Count;
37955  ma_uint32 hpf2Count;
37956  ma_uint32 ihpf1;
37957  ma_uint32 ihpf2;
37958 
37959  if (pHPF == NULL || pConfig == NULL) {
37960  return MA_INVALID_ARGS;
37961  }
37962 
37963  /* Only supporting f32 and s16. */
37964  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
37965  return MA_INVALID_ARGS;
37966  }
37967 
37968  /* The format cannot be changed after initialization. */
37969  if (pHPF->format != ma_format_unknown && pHPF->format != pConfig->format) {
37970  return MA_INVALID_OPERATION;
37971  }
37972 
37973  /* The channel count cannot be changed after initialization. */
37974  if (pHPF->channels != 0 && pHPF->channels != pConfig->channels) {
37975  return MA_INVALID_OPERATION;
37976  }
37977 
37978  if (pConfig->order > MA_MAX_FILTER_ORDER) {
37979  return MA_INVALID_ARGS;
37980  }
37981 
37982  hpf1Count = pConfig->order % 2;
37983  hpf2Count = pConfig->order / 2;
37984 
37985  MA_ASSERT(hpf1Count <= ma_countof(pHPF->hpf1));
37986  MA_ASSERT(hpf2Count <= ma_countof(pHPF->hpf2));
37987 
37988  /* The filter order can't change between reinits. */
37989  if (!isNew) {
37990  if (pHPF->hpf1Count != hpf1Count || pHPF->hpf2Count != hpf2Count) {
37991  return MA_INVALID_OPERATION;
37992  }
37993  }
37994 
37995  for (ihpf1 = 0; ihpf1 < hpf1Count; ihpf1 += 1) {
37996  ma_hpf1_config hpf1Config = ma_hpf1_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency);
37997 
37998  if (isNew) {
37999  result = ma_hpf1_init(&hpf1Config, &pHPF->hpf1[ihpf1]);
38000  } else {
38001  result = ma_hpf1_reinit(&hpf1Config, &pHPF->hpf1[ihpf1]);
38002  }
38003 
38004  if (result != MA_SUCCESS) {
38005  return result;
38006  }
38007  }
38008 
38009  for (ihpf2 = 0; ihpf2 < hpf2Count; ihpf2 += 1) {
38010  ma_hpf2_config hpf2Config;
38011  double q;
38012  double a;
38013 
38014  /* Tempting to use 0.707107, but won't result in a Butterworth filter if the order is > 2. */
38015  if (hpf1Count == 1) {
38016  a = (1 + ihpf2*1) * (MA_PI_D/(pConfig->order*1)); /* Odd order. */
38017  } else {
38018  a = (1 + ihpf2*2) * (MA_PI_D/(pConfig->order*2)); /* Even order. */
38019  }
38020  q = 1 / (2*ma_cosd(a));
38021 
38022  hpf2Config = ma_hpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
38023 
38024  if (isNew) {
38025  result = ma_hpf2_init(&hpf2Config, &pHPF->hpf2[ihpf2]);
38026  } else {
38027  result = ma_hpf2_reinit(&hpf2Config, &pHPF->hpf2[ihpf2]);
38028  }
38029 
38030  if (result != MA_SUCCESS) {
38031  return result;
38032  }
38033  }
38034 
38035  pHPF->hpf1Count = hpf1Count;
38036  pHPF->hpf2Count = hpf2Count;
38037  pHPF->format = pConfig->format;
38038  pHPF->channels = pConfig->channels;
38039  pHPF->sampleRate = pConfig->sampleRate;
38040 
38041  return MA_SUCCESS;
38042 }
38043 
38044 MA_API ma_result ma_hpf_init(const ma_hpf_config* pConfig, ma_hpf* pHPF)
38045 {
38046  if (pHPF == NULL) {
38047  return MA_INVALID_ARGS;
38048  }
38049 
38050  MA_ZERO_OBJECT(pHPF);
38051 
38052  if (pConfig == NULL) {
38053  return MA_INVALID_ARGS;
38054  }
38055 
38056  return ma_hpf_reinit__internal(pConfig, pHPF, /*isNew*/MA_TRUE);
38057 }
38058 
38059 MA_API ma_result ma_hpf_reinit(const ma_hpf_config* pConfig, ma_hpf* pHPF)
38060 {
38061  return ma_hpf_reinit__internal(pConfig, pHPF, /*isNew*/MA_FALSE);
38062 }
38063 
38064 MA_API ma_result ma_hpf_process_pcm_frames(ma_hpf* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38065 {
38066  ma_result result;
38067  ma_uint32 ihpf1;
38068  ma_uint32 ihpf2;
38069 
38070  if (pHPF == NULL) {
38071  return MA_INVALID_ARGS;
38072  }
38073 
38074  /* Faster path for in-place. */
38075  if (pFramesOut == pFramesIn) {
38076  for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
38077  result = ma_hpf1_process_pcm_frames(&pHPF->hpf1[ihpf1], pFramesOut, pFramesOut, frameCount);
38078  if (result != MA_SUCCESS) {
38079  return result;
38080  }
38081  }
38082 
38083  for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
38084  result = ma_hpf2_process_pcm_frames(&pHPF->hpf2[ihpf2], pFramesOut, pFramesOut, frameCount);
38085  if (result != MA_SUCCESS) {
38086  return result;
38087  }
38088  }
38089  }
38090 
38091  /* Slightly slower path for copying. */
38092  if (pFramesOut != pFramesIn) {
38093  ma_uint32 iFrame;
38094 
38095  /* */ if (pHPF->format == ma_format_f32) {
38096  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
38097  const float* pFramesInF32 = (const float*)pFramesIn;
38098 
38099  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
38100  MA_COPY_MEMORY(pFramesOutF32, pFramesInF32, ma_get_bytes_per_frame(pHPF->format, pHPF->channels));
38101 
38102  for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
38103  ma_hpf1_process_pcm_frame_f32(&pHPF->hpf1[ihpf1], pFramesOutF32, pFramesOutF32);
38104  }
38105 
38106  for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
38107  ma_hpf2_process_pcm_frame_f32(&pHPF->hpf2[ihpf2], pFramesOutF32, pFramesOutF32);
38108  }
38109 
38110  pFramesOutF32 += pHPF->channels;
38111  pFramesInF32 += pHPF->channels;
38112  }
38113  } else if (pHPF->format == ma_format_s16) {
38114  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
38115  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
38116 
38117  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
38118  MA_COPY_MEMORY(pFramesOutS16, pFramesInS16, ma_get_bytes_per_frame(pHPF->format, pHPF->channels));
38119 
38120  for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
38121  ma_hpf1_process_pcm_frame_s16(&pHPF->hpf1[ihpf1], pFramesOutS16, pFramesOutS16);
38122  }
38123 
38124  for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
38125  ma_hpf2_process_pcm_frame_s16(&pHPF->hpf2[ihpf2], pFramesOutS16, pFramesOutS16);
38126  }
38127 
38128  pFramesOutS16 += pHPF->channels;
38129  pFramesInS16 += pHPF->channels;
38130  }
38131  } else {
38133  return MA_INVALID_OPERATION; /* Should never hit this. */
38134  }
38135  }
38136 
38137  return MA_SUCCESS;
38138 }
38139 
38141 {
38142  if (pHPF == NULL) {
38143  return 0;
38144  }
38145 
38146  return pHPF->hpf2Count*2 + pHPF->hpf1Count;
38147 }
38148 
38149 
38150 /**************************************************************************************************************************************************************
38151 
38152 Band-Pass Filtering
38153 
38154 **************************************************************************************************************************************************************/
38155 MA_API ma_bpf2_config ma_bpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q)
38156 {
38158 
38160  config.format = format;
38161  config.channels = channels;
38162  config.sampleRate = sampleRate;
38163  config.cutoffFrequency = cutoffFrequency;
38164  config.q = q;
38165 
38166  /* Q cannot be 0 or else it'll result in a division by 0. In this case just default to 0.707107. */
38167  if (config.q == 0) {
38168  config.q = 0.707107;
38169  }
38170 
38171  return config;
38172 }
38173 
38174 
38176 {
38177  ma_biquad_config bqConfig;
38178  double q;
38179  double w;
38180  double s;
38181  double c;
38182  double a;
38183 
38184  MA_ASSERT(pConfig != NULL);
38185 
38186  q = pConfig->q;
38187  w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
38188  s = ma_sind(w);
38189  c = ma_cosd(w);
38190  a = s / (2*q);
38191 
38192  bqConfig.b0 = q * a;
38193  bqConfig.b1 = 0;
38194  bqConfig.b2 = -q * a;
38195  bqConfig.a0 = 1 + a;
38196  bqConfig.a1 = -2 * c;
38197  bqConfig.a2 = 1 - a;
38198 
38199  bqConfig.format = pConfig->format;
38200  bqConfig.channels = pConfig->channels;
38201 
38202  return bqConfig;
38203 }
38204 
38205 MA_API ma_result ma_bpf2_init(const ma_bpf2_config* pConfig, ma_bpf2* pBPF)
38206 {
38207  ma_result result;
38208  ma_biquad_config bqConfig;
38209 
38210  if (pBPF == NULL) {
38211  return MA_INVALID_ARGS;
38212  }
38213 
38214  MA_ZERO_OBJECT(pBPF);
38215 
38216  if (pConfig == NULL) {
38217  return MA_INVALID_ARGS;
38218  }
38219 
38220  bqConfig = ma_bpf2__get_biquad_config(pConfig);
38221  result = ma_biquad_init(&bqConfig, &pBPF->bq);
38222  if (result != MA_SUCCESS) {
38223  return result;
38224  }
38225 
38226  return MA_SUCCESS;
38227 }
38228 
38229 MA_API ma_result ma_bpf2_reinit(const ma_bpf2_config* pConfig, ma_bpf2* pBPF)
38230 {
38231  ma_result result;
38232  ma_biquad_config bqConfig;
38233 
38234  if (pBPF == NULL || pConfig == NULL) {
38235  return MA_INVALID_ARGS;
38236  }
38237 
38238  bqConfig = ma_bpf2__get_biquad_config(pConfig);
38239  result = ma_biquad_reinit(&bqConfig, &pBPF->bq);
38240  if (result != MA_SUCCESS) {
38241  return result;
38242  }
38243 
38244  return MA_SUCCESS;
38245 }
38246 
38247 static MA_INLINE void ma_bpf2_process_pcm_frame_s16(ma_bpf2* pBPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
38248 {
38249  ma_biquad_process_pcm_frame_s16(&pBPF->bq, pFrameOut, pFrameIn);
38250 }
38251 
38252 static MA_INLINE void ma_bpf2_process_pcm_frame_f32(ma_bpf2* pBPF, float* pFrameOut, const float* pFrameIn)
38253 {
38254  ma_biquad_process_pcm_frame_f32(&pBPF->bq, pFrameOut, pFrameIn);
38255 }
38256 
38257 MA_API ma_result ma_bpf2_process_pcm_frames(ma_bpf2* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38258 {
38259  if (pBPF == NULL) {
38260  return MA_INVALID_ARGS;
38261  }
38262 
38263  return ma_biquad_process_pcm_frames(&pBPF->bq, pFramesOut, pFramesIn, frameCount);
38264 }
38265 
38267 {
38268  if (pBPF == NULL) {
38269  return 0;
38270  }
38271 
38272  return ma_biquad_get_latency(&pBPF->bq);
38273 }
38274 
38275 
38276 MA_API ma_bpf_config ma_bpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
38277 {
38279 
38281  config.format = format;
38282  config.channels = channels;
38283  config.sampleRate = sampleRate;
38284  config.cutoffFrequency = cutoffFrequency;
38285  config.order = ma_min(order, MA_MAX_FILTER_ORDER);
38286 
38287  return config;
38288 }
38289 
38290 static ma_result ma_bpf_reinit__internal(const ma_bpf_config* pConfig, ma_bpf* pBPF, ma_bool32 isNew)
38291 {
38292  ma_result result;
38293  ma_uint32 bpf2Count;
38294  ma_uint32 ibpf2;
38295 
38296  if (pBPF == NULL || pConfig == NULL) {
38297  return MA_INVALID_ARGS;
38298  }
38299 
38300  /* Only supporting f32 and s16. */
38301  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
38302  return MA_INVALID_ARGS;
38303  }
38304 
38305  /* The format cannot be changed after initialization. */
38306  if (pBPF->format != ma_format_unknown && pBPF->format != pConfig->format) {
38307  return MA_INVALID_OPERATION;
38308  }
38309 
38310  /* The channel count cannot be changed after initialization. */
38311  if (pBPF->channels != 0 && pBPF->channels != pConfig->channels) {
38312  return MA_INVALID_OPERATION;
38313  }
38314 
38315  if (pConfig->order > MA_MAX_FILTER_ORDER) {
38316  return MA_INVALID_ARGS;
38317  }
38318 
38319  /* We must have an even number of order. */
38320  if ((pConfig->order & 0x1) != 0) {
38321  return MA_INVALID_ARGS;
38322  }
38323 
38324  bpf2Count = pConfig->order / 2;
38325 
38326  MA_ASSERT(bpf2Count <= ma_countof(pBPF->bpf2));
38327 
38328  /* The filter order can't change between reinits. */
38329  if (!isNew) {
38330  if (pBPF->bpf2Count != bpf2Count) {
38331  return MA_INVALID_OPERATION;
38332  }
38333  }
38334 
38335  for (ibpf2 = 0; ibpf2 < bpf2Count; ibpf2 += 1) {
38336  ma_bpf2_config bpf2Config;
38337  double q;
38338 
38339  /* TODO: Calculate Q to make this a proper Butterworth filter. */
38340  q = 0.707107;
38341 
38342  bpf2Config = ma_bpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
38343 
38344  if (isNew) {
38345  result = ma_bpf2_init(&bpf2Config, &pBPF->bpf2[ibpf2]);
38346  } else {
38347  result = ma_bpf2_reinit(&bpf2Config, &pBPF->bpf2[ibpf2]);
38348  }
38349 
38350  if (result != MA_SUCCESS) {
38351  return result;
38352  }
38353  }
38354 
38355  pBPF->bpf2Count = bpf2Count;
38356  pBPF->format = pConfig->format;
38357  pBPF->channels = pConfig->channels;
38358 
38359  return MA_SUCCESS;
38360 }
38361 
38362 MA_API ma_result ma_bpf_init(const ma_bpf_config* pConfig, ma_bpf* pBPF)
38363 {
38364  if (pBPF == NULL) {
38365  return MA_INVALID_ARGS;
38366  }
38367 
38368  MA_ZERO_OBJECT(pBPF);
38369 
38370  if (pConfig == NULL) {
38371  return MA_INVALID_ARGS;
38372  }
38373 
38374  return ma_bpf_reinit__internal(pConfig, pBPF, /*isNew*/MA_TRUE);
38375 }
38376 
38377 MA_API ma_result ma_bpf_reinit(const ma_bpf_config* pConfig, ma_bpf* pBPF)
38378 {
38379  return ma_bpf_reinit__internal(pConfig, pBPF, /*isNew*/MA_FALSE);
38380 }
38381 
38382 MA_API ma_result ma_bpf_process_pcm_frames(ma_bpf* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38383 {
38384  ma_result result;
38385  ma_uint32 ibpf2;
38386 
38387  if (pBPF == NULL) {
38388  return MA_INVALID_ARGS;
38389  }
38390 
38391  /* Faster path for in-place. */
38392  if (pFramesOut == pFramesIn) {
38393  for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
38394  result = ma_bpf2_process_pcm_frames(&pBPF->bpf2[ibpf2], pFramesOut, pFramesOut, frameCount);
38395  if (result != MA_SUCCESS) {
38396  return result;
38397  }
38398  }
38399  }
38400 
38401  /* Slightly slower path for copying. */
38402  if (pFramesOut != pFramesIn) {
38403  ma_uint32 iFrame;
38404 
38405  /* */ if (pBPF->format == ma_format_f32) {
38406  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
38407  const float* pFramesInF32 = (const float*)pFramesIn;
38408 
38409  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
38410  MA_COPY_MEMORY(pFramesOutF32, pFramesInF32, ma_get_bytes_per_frame(pBPF->format, pBPF->channels));
38411 
38412  for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
38413  ma_bpf2_process_pcm_frame_f32(&pBPF->bpf2[ibpf2], pFramesOutF32, pFramesOutF32);
38414  }
38415 
38416  pFramesOutF32 += pBPF->channels;
38417  pFramesInF32 += pBPF->channels;
38418  }
38419  } else if (pBPF->format == ma_format_s16) {
38420  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
38421  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
38422 
38423  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
38424  MA_COPY_MEMORY(pFramesOutS16, pFramesInS16, ma_get_bytes_per_frame(pBPF->format, pBPF->channels));
38425 
38426  for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
38427  ma_bpf2_process_pcm_frame_s16(&pBPF->bpf2[ibpf2], pFramesOutS16, pFramesOutS16);
38428  }
38429 
38430  pFramesOutS16 += pBPF->channels;
38431  pFramesInS16 += pBPF->channels;
38432  }
38433  } else {
38435  return MA_INVALID_OPERATION; /* Should never hit this. */
38436  }
38437  }
38438 
38439  return MA_SUCCESS;
38440 }
38441 
38443 {
38444  if (pBPF == NULL) {
38445  return 0;
38446  }
38447 
38448  return pBPF->bpf2Count*2;
38449 }
38450 
38451 
38452 /**************************************************************************************************************************************************************
38453 
38454 Notching Filter
38455 
38456 **************************************************************************************************************************************************************/
38457 MA_API ma_notch2_config ma_notch2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency)
38458 {
38460 
38462  config.format = format;
38463  config.channels = channels;
38464  config.sampleRate = sampleRate;
38465  config.q = q;
38466  config.frequency = frequency;
38467 
38468  if (config.q == 0) {
38469  config.q = 0.707107;
38470  }
38471 
38472  return config;
38473 }
38474 
38475 
38477 {
38478  ma_biquad_config bqConfig;
38479  double q;
38480  double w;
38481  double s;
38482  double c;
38483  double a;
38484 
38485  MA_ASSERT(pConfig != NULL);
38486 
38487  q = pConfig->q;
38488  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
38489  s = ma_sind(w);
38490  c = ma_cosd(w);
38491  a = s / (2*q);
38492 
38493  bqConfig.b0 = 1;
38494  bqConfig.b1 = -2 * c;
38495  bqConfig.b2 = 1;
38496  bqConfig.a0 = 1 + a;
38497  bqConfig.a1 = -2 * c;
38498  bqConfig.a2 = 1 - a;
38499 
38500  bqConfig.format = pConfig->format;
38501  bqConfig.channels = pConfig->channels;
38502 
38503  return bqConfig;
38504 }
38505 
38506 MA_API ma_result ma_notch2_init(const ma_notch2_config* pConfig, ma_notch2* pFilter)
38507 {
38508  ma_result result;
38509  ma_biquad_config bqConfig;
38510 
38511  if (pFilter == NULL) {
38512  return MA_INVALID_ARGS;
38513  }
38514 
38515  MA_ZERO_OBJECT(pFilter);
38516 
38517  if (pConfig == NULL) {
38518  return MA_INVALID_ARGS;
38519  }
38520 
38521  bqConfig = ma_notch2__get_biquad_config(pConfig);
38522  result = ma_biquad_init(&bqConfig, &pFilter->bq);
38523  if (result != MA_SUCCESS) {
38524  return result;
38525  }
38526 
38527  return MA_SUCCESS;
38528 }
38529 
38531 {
38532  ma_result result;
38533  ma_biquad_config bqConfig;
38534 
38535  if (pFilter == NULL || pConfig == NULL) {
38536  return MA_INVALID_ARGS;
38537  }
38538 
38539  bqConfig = ma_notch2__get_biquad_config(pConfig);
38540  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
38541  if (result != MA_SUCCESS) {
38542  return result;
38543  }
38544 
38545  return MA_SUCCESS;
38546 }
38547 
38548 static MA_INLINE void ma_notch2_process_pcm_frame_s16(ma_notch2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
38549 {
38550  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
38551 }
38552 
38553 static MA_INLINE void ma_notch2_process_pcm_frame_f32(ma_notch2* pFilter, float* pFrameOut, const float* pFrameIn)
38554 {
38555  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
38556 }
38557 
38558 MA_API ma_result ma_notch2_process_pcm_frames(ma_notch2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38559 {
38560  if (pFilter == NULL) {
38561  return MA_INVALID_ARGS;
38562  }
38563 
38564  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
38565 }
38566 
38568 {
38569  if (pFilter == NULL) {
38570  return 0;
38571  }
38572 
38573  return ma_biquad_get_latency(&pFilter->bq);
38574 }
38575 
38576 
38577 
38578 /**************************************************************************************************************************************************************
38579 
38580 Peaking EQ Filter
38581 
38582 **************************************************************************************************************************************************************/
38583 MA_API ma_peak2_config ma_peak2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
38584 {
38586 
38588  config.format = format;
38589  config.channels = channels;
38590  config.sampleRate = sampleRate;
38591  config.gainDB = gainDB;
38592  config.q = q;
38593  config.frequency = frequency;
38594 
38595  if (config.q == 0) {
38596  config.q = 0.707107;
38597  }
38598 
38599  return config;
38600 }
38601 
38602 
38604 {
38605  ma_biquad_config bqConfig;
38606  double q;
38607  double w;
38608  double s;
38609  double c;
38610  double a;
38611  double A;
38612 
38613  MA_ASSERT(pConfig != NULL);
38614 
38615  q = pConfig->q;
38616  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
38617  s = ma_sind(w);
38618  c = ma_cosd(w);
38619  a = s / (2*q);
38620  A = ma_powd(10, (pConfig->gainDB / 40));
38621 
38622  bqConfig.b0 = 1 + (a * A);
38623  bqConfig.b1 = -2 * c;
38624  bqConfig.b2 = 1 - (a * A);
38625  bqConfig.a0 = 1 + (a / A);
38626  bqConfig.a1 = -2 * c;
38627  bqConfig.a2 = 1 - (a / A);
38628 
38629  bqConfig.format = pConfig->format;
38630  bqConfig.channels = pConfig->channels;
38631 
38632  return bqConfig;
38633 }
38634 
38635 MA_API ma_result ma_peak2_init(const ma_peak2_config* pConfig, ma_peak2* pFilter)
38636 {
38637  ma_result result;
38638  ma_biquad_config bqConfig;
38639 
38640  if (pFilter == NULL) {
38641  return MA_INVALID_ARGS;
38642  }
38643 
38644  MA_ZERO_OBJECT(pFilter);
38645 
38646  if (pConfig == NULL) {
38647  return MA_INVALID_ARGS;
38648  }
38649 
38650  bqConfig = ma_peak2__get_biquad_config(pConfig);
38651  result = ma_biquad_init(&bqConfig, &pFilter->bq);
38652  if (result != MA_SUCCESS) {
38653  return result;
38654  }
38655 
38656  return MA_SUCCESS;
38657 }
38658 
38659 MA_API ma_result ma_peak2_reinit(const ma_peak2_config* pConfig, ma_peak2* pFilter)
38660 {
38661  ma_result result;
38662  ma_biquad_config bqConfig;
38663 
38664  if (pFilter == NULL || pConfig == NULL) {
38665  return MA_INVALID_ARGS;
38666  }
38667 
38668  bqConfig = ma_peak2__get_biquad_config(pConfig);
38669  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
38670  if (result != MA_SUCCESS) {
38671  return result;
38672  }
38673 
38674  return MA_SUCCESS;
38675 }
38676 
38677 static MA_INLINE void ma_peak2_process_pcm_frame_s16(ma_peak2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
38678 {
38679  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
38680 }
38681 
38682 static MA_INLINE void ma_peak2_process_pcm_frame_f32(ma_peak2* pFilter, float* pFrameOut, const float* pFrameIn)
38683 {
38684  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
38685 }
38686 
38687 MA_API ma_result ma_peak2_process_pcm_frames(ma_peak2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38688 {
38689  if (pFilter == NULL) {
38690  return MA_INVALID_ARGS;
38691  }
38692 
38693  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
38694 }
38695 
38697 {
38698  if (pFilter == NULL) {
38699  return 0;
38700  }
38701 
38702  return ma_biquad_get_latency(&pFilter->bq);
38703 }
38704 
38705 
38706 /**************************************************************************************************************************************************************
38707 
38708 Low Shelf Filter
38709 
38710 **************************************************************************************************************************************************************/
38711 MA_API ma_loshelf2_config ma_loshelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency)
38712 {
38714 
38716  config.format = format;
38717  config.channels = channels;
38718  config.sampleRate = sampleRate;
38719  config.gainDB = gainDB;
38720  config.shelfSlope = shelfSlope;
38721  config.frequency = frequency;
38722 
38723  return config;
38724 }
38725 
38726 
38728 {
38729  ma_biquad_config bqConfig;
38730  double w;
38731  double s;
38732  double c;
38733  double A;
38734  double S;
38735  double a;
38736  double sqrtA;
38737 
38738  MA_ASSERT(pConfig != NULL);
38739 
38740  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
38741  s = ma_sind(w);
38742  c = ma_cosd(w);
38743  A = ma_powd(10, (pConfig->gainDB / 40));
38744  S = pConfig->shelfSlope;
38745  a = s/2 * ma_sqrtd((A + 1/A) * (1/S - 1) + 2);
38746  sqrtA = 2*ma_sqrtd(A)*a;
38747 
38748  bqConfig.b0 = A * ((A + 1) - (A - 1)*c + sqrtA);
38749  bqConfig.b1 = 2 * A * ((A - 1) - (A + 1)*c);
38750  bqConfig.b2 = A * ((A + 1) - (A - 1)*c - sqrtA);
38751  bqConfig.a0 = (A + 1) + (A - 1)*c + sqrtA;
38752  bqConfig.a1 = -2 * ((A - 1) + (A + 1)*c);
38753  bqConfig.a2 = (A + 1) + (A - 1)*c - sqrtA;
38754 
38755  bqConfig.format = pConfig->format;
38756  bqConfig.channels = pConfig->channels;
38757 
38758  return bqConfig;
38759 }
38760 
38762 {
38763  ma_result result;
38764  ma_biquad_config bqConfig;
38765 
38766  if (pFilter == NULL) {
38767  return MA_INVALID_ARGS;
38768  }
38769 
38770  MA_ZERO_OBJECT(pFilter);
38771 
38772  if (pConfig == NULL) {
38773  return MA_INVALID_ARGS;
38774  }
38775 
38776  bqConfig = ma_loshelf2__get_biquad_config(pConfig);
38777  result = ma_biquad_init(&bqConfig, &pFilter->bq);
38778  if (result != MA_SUCCESS) {
38779  return result;
38780  }
38781 
38782  return MA_SUCCESS;
38783 }
38784 
38786 {
38787  ma_result result;
38788  ma_biquad_config bqConfig;
38789 
38790  if (pFilter == NULL || pConfig == NULL) {
38791  return MA_INVALID_ARGS;
38792  }
38793 
38794  bqConfig = ma_loshelf2__get_biquad_config(pConfig);
38795  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
38796  if (result != MA_SUCCESS) {
38797  return result;
38798  }
38799 
38800  return MA_SUCCESS;
38801 }
38802 
38803 static MA_INLINE void ma_loshelf2_process_pcm_frame_s16(ma_loshelf2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
38804 {
38805  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
38806 }
38807 
38808 static MA_INLINE void ma_loshelf2_process_pcm_frame_f32(ma_loshelf2* pFilter, float* pFrameOut, const float* pFrameIn)
38809 {
38810  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
38811 }
38812 
38813 MA_API ma_result ma_loshelf2_process_pcm_frames(ma_loshelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38814 {
38815  if (pFilter == NULL) {
38816  return MA_INVALID_ARGS;
38817  }
38818 
38819  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
38820 }
38821 
38823 {
38824  if (pFilter == NULL) {
38825  return 0;
38826  }
38827 
38828  return ma_biquad_get_latency(&pFilter->bq);
38829 }
38830 
38831 
38832 /**************************************************************************************************************************************************************
38833 
38834 High Shelf Filter
38835 
38836 **************************************************************************************************************************************************************/
38837 MA_API ma_hishelf2_config ma_hishelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency)
38838 {
38840 
38842  config.format = format;
38843  config.channels = channels;
38844  config.sampleRate = sampleRate;
38845  config.gainDB = gainDB;
38846  config.shelfSlope = shelfSlope;
38847  config.frequency = frequency;
38848 
38849  return config;
38850 }
38851 
38852 
38854 {
38855  ma_biquad_config bqConfig;
38856  double w;
38857  double s;
38858  double c;
38859  double A;
38860  double S;
38861  double a;
38862  double sqrtA;
38863 
38864  MA_ASSERT(pConfig != NULL);
38865 
38866  w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
38867  s = ma_sind(w);
38868  c = ma_cosd(w);
38869  A = ma_powd(10, (pConfig->gainDB / 40));
38870  S = pConfig->shelfSlope;
38871  a = s/2 * ma_sqrtd((A + 1/A) * (1/S - 1) + 2);
38872  sqrtA = 2*ma_sqrtd(A)*a;
38873 
38874  bqConfig.b0 = A * ((A + 1) + (A - 1)*c + sqrtA);
38875  bqConfig.b1 = -2 * A * ((A - 1) + (A + 1)*c);
38876  bqConfig.b2 = A * ((A + 1) + (A - 1)*c - sqrtA);
38877  bqConfig.a0 = (A + 1) - (A - 1)*c + sqrtA;
38878  bqConfig.a1 = 2 * ((A - 1) - (A + 1)*c);
38879  bqConfig.a2 = (A + 1) - (A - 1)*c - sqrtA;
38880 
38881  bqConfig.format = pConfig->format;
38882  bqConfig.channels = pConfig->channels;
38883 
38884  return bqConfig;
38885 }
38886 
38888 {
38889  ma_result result;
38890  ma_biquad_config bqConfig;
38891 
38892  if (pFilter == NULL) {
38893  return MA_INVALID_ARGS;
38894  }
38895 
38896  MA_ZERO_OBJECT(pFilter);
38897 
38898  if (pConfig == NULL) {
38899  return MA_INVALID_ARGS;
38900  }
38901 
38902  bqConfig = ma_hishelf2__get_biquad_config(pConfig);
38903  result = ma_biquad_init(&bqConfig, &pFilter->bq);
38904  if (result != MA_SUCCESS) {
38905  return result;
38906  }
38907 
38908  return MA_SUCCESS;
38909 }
38910 
38912 {
38913  ma_result result;
38914  ma_biquad_config bqConfig;
38915 
38916  if (pFilter == NULL || pConfig == NULL) {
38917  return MA_INVALID_ARGS;
38918  }
38919 
38920  bqConfig = ma_hishelf2__get_biquad_config(pConfig);
38921  result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
38922  if (result != MA_SUCCESS) {
38923  return result;
38924  }
38925 
38926  return MA_SUCCESS;
38927 }
38928 
38929 static MA_INLINE void ma_hishelf2_process_pcm_frame_s16(ma_hishelf2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
38930 {
38931  ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
38932 }
38933 
38934 static MA_INLINE void ma_hishelf2_process_pcm_frame_f32(ma_hishelf2* pFilter, float* pFrameOut, const float* pFrameIn)
38935 {
38936  ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
38937 }
38938 
38939 MA_API ma_result ma_hishelf2_process_pcm_frames(ma_hishelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
38940 {
38941  if (pFilter == NULL) {
38942  return MA_INVALID_ARGS;
38943  }
38944 
38945  return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
38946 }
38947 
38949 {
38950  if (pFilter == NULL) {
38951  return 0;
38952  }
38953 
38954  return ma_biquad_get_latency(&pFilter->bq);
38955 }
38956 
38957 
38958 
38959 /**************************************************************************************************************************************************************
38960 
38961 Resampling
38962 
38963 **************************************************************************************************************************************************************/
38965 {
38968  config.format = format;
38969  config.channels = channels;
38970  config.sampleRateIn = sampleRateIn;
38971  config.sampleRateOut = sampleRateOut;
38973  config.lpfNyquistFactor = 1;
38974 
38975  return config;
38976 }
38977 
38978 static void ma_linear_resampler_adjust_timer_for_new_rate(ma_linear_resampler* pResampler, ma_uint32 oldSampleRateOut, ma_uint32 newSampleRateOut)
38979 {
38980  /*
38981  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
38982  be based on the old sample rate, but we are needing to adjust it to that it's based on the new sample rate.
38983  */
38984  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. */
38985  ma_uint32 oldRateTimeFract = pResampler->inTimeFrac % oldSampleRateOut;
38986 
38987  pResampler->inTimeFrac =
38988  (oldRateTimeWhole * newSampleRateOut) +
38989  ((oldRateTimeFract * newSampleRateOut) / oldSampleRateOut);
38990 
38991  /* Make sure the fractional part is less than the output sample rate. */
38992  pResampler->inTimeInt += pResampler->inTimeFrac / pResampler->config.sampleRateOut;
38993  pResampler->inTimeFrac = pResampler->inTimeFrac % pResampler->config.sampleRateOut;
38994 }
38995 
38996 static ma_result ma_linear_resampler_set_rate_internal(ma_linear_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_bool32 isResamplerAlreadyInitialized)
38997 {
38998  ma_result result;
38999  ma_uint32 gcf;
39000  ma_uint32 lpfSampleRate;
39001  double lpfCutoffFrequency;
39002  ma_lpf_config lpfConfig;
39003  ma_uint32 oldSampleRateOut; /* Required for adjusting time advance down the bottom. */
39004 
39005  if (pResampler == NULL) {
39006  return MA_INVALID_ARGS;
39007  }
39008 
39009  if (sampleRateIn == 0 || sampleRateOut == 0) {
39010  return MA_INVALID_ARGS;
39011  }
39012 
39013  oldSampleRateOut = pResampler->config.sampleRateOut;
39014 
39015  pResampler->config.sampleRateIn = sampleRateIn;
39016  pResampler->config.sampleRateOut = sampleRateOut;
39017 
39018  /* Simplify the sample rate. */
39019  gcf = ma_gcf_u32(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut);
39020  pResampler->config.sampleRateIn /= gcf;
39021  pResampler->config.sampleRateOut /= gcf;
39022 
39023  /* Always initialize the low-pass filter, even when the order is 0. */
39024  if (pResampler->config.lpfOrder > MA_MAX_FILTER_ORDER) {
39025  return MA_INVALID_ARGS;
39026  }
39027 
39028  lpfSampleRate = (ma_uint32)(ma_max(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut));
39029  lpfCutoffFrequency = ( double)(ma_min(pResampler->config.sampleRateIn, pResampler->config.sampleRateOut) * 0.5 * pResampler->config.lpfNyquistFactor);
39030 
39031  lpfConfig = ma_lpf_config_init(pResampler->config.format, pResampler->config.channels, lpfSampleRate, lpfCutoffFrequency, pResampler->config.lpfOrder);
39032 
39033  /*
39034  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
39035  getting cleared. Instead we re-initialize the filter which will maintain any cached frames.
39036  */
39037  if (isResamplerAlreadyInitialized) {
39038  result = ma_lpf_reinit(&lpfConfig, &pResampler->lpf);
39039  } else {
39040  result = ma_lpf_init(&lpfConfig, &pResampler->lpf);
39041  }
39042 
39043  if (result != MA_SUCCESS) {
39044  return result;
39045  }
39046 
39047 
39048  pResampler->inAdvanceInt = pResampler->config.sampleRateIn / pResampler->config.sampleRateOut;
39049  pResampler->inAdvanceFrac = pResampler->config.sampleRateIn % pResampler->config.sampleRateOut;
39050 
39051  /* Our timer was based on the old rate. We need to adjust it so that it's based on the new rate. */
39052  ma_linear_resampler_adjust_timer_for_new_rate(pResampler, oldSampleRateOut, pResampler->config.sampleRateOut);
39053 
39054  return MA_SUCCESS;
39055 }
39056 
39058 {
39059  ma_result result;
39060 
39061  if (pResampler == NULL) {
39062  return MA_INVALID_ARGS;
39063  }
39064 
39065  MA_ZERO_OBJECT(pResampler);
39066 
39067  if (pConfig == NULL) {
39068  return MA_INVALID_ARGS;
39069  }
39070 
39071  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
39072  return MA_INVALID_ARGS;
39073  }
39074 
39075  pResampler->config = *pConfig;
39076 
39077  /* Setting the rate will set up the filter and time advances for us. */
39078  result = ma_linear_resampler_set_rate_internal(pResampler, pConfig->sampleRateIn, pConfig->sampleRateOut, /* isResamplerAlreadyInitialized = */ MA_FALSE);
39079  if (result != MA_SUCCESS) {
39080  return result;
39081  }
39082 
39083  pResampler->inTimeInt = 1; /* Set this to one to force an input sample to always be loaded for the first output frame. */
39084  pResampler->inTimeFrac = 0;
39085 
39086  return MA_SUCCESS;
39087 }
39088 
39090 {
39091  if (pResampler == NULL) {
39092  return;
39093  }
39094 }
39095 
39097 {
39098  ma_int32 b;
39099  ma_int32 c;
39100  ma_int32 r;
39101 
39102  MA_ASSERT(a <= (1<<shift));
39103 
39104  b = x * ((1<<shift) - a);
39105  c = y * a;
39106  r = b + c;
39107 
39108  return (ma_int16)(r >> shift);
39109 }
39110 
39112 {
39113  ma_uint32 c;
39114  ma_uint32 a;
39115  const ma_uint32 channels = pResampler->config.channels;
39116  const ma_uint32 shift = 12;
39117 
39118  MA_ASSERT(pResampler != NULL);
39119  MA_ASSERT(pFrameOut != NULL);
39120 
39121  a = (pResampler->inTimeFrac << shift) / pResampler->config.sampleRateOut;
39122 
39123  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
39124  for (c = 0; c < channels; c += 1) {
39125  ma_int16 s = ma_linear_resampler_mix_s16(pResampler->x0.s16[c], pResampler->x1.s16[c], a, shift);
39126  pFrameOut[c] = s;
39127  }
39128 }
39129 
39130 
39131 static void ma_linear_resampler_interpolate_frame_f32(ma_linear_resampler* pResampler, float* MA_RESTRICT pFrameOut)
39132 {
39133  ma_uint32 c;
39134  float a;
39135  const ma_uint32 channels = pResampler->config.channels;
39136 
39137  MA_ASSERT(pResampler != NULL);
39138  MA_ASSERT(pFrameOut != NULL);
39139 
39140  a = (float)pResampler->inTimeFrac / pResampler->config.sampleRateOut;
39141 
39142  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
39143  for (c = 0; c < channels; c += 1) {
39144  float s = ma_mix_f32_fast(pResampler->x0.f32[c], pResampler->x1.f32[c], a);
39145  pFrameOut[c] = s;
39146  }
39147 }
39148 
39149 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)
39150 {
39151  const ma_int16* pFramesInS16;
39152  /* */ ma_int16* pFramesOutS16;
39153  ma_uint64 frameCountIn;
39154  ma_uint64 frameCountOut;
39155  ma_uint64 framesProcessedIn;
39156  ma_uint64 framesProcessedOut;
39157 
39158  MA_ASSERT(pResampler != NULL);
39159  MA_ASSERT(pFrameCountIn != NULL);
39160  MA_ASSERT(pFrameCountOut != NULL);
39161 
39162  pFramesInS16 = (const ma_int16*)pFramesIn;
39163  pFramesOutS16 = ( ma_int16*)pFramesOut;
39164  frameCountIn = *pFrameCountIn;
39165  frameCountOut = *pFrameCountOut;
39166  framesProcessedIn = 0;
39167  framesProcessedOut = 0;
39168 
39169  while (framesProcessedOut < frameCountOut) {
39170  /* Before interpolating we need to load the buffers. When doing this we need to ensure we run every input sample through the filter. */
39171  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
39172  ma_uint32 iChannel;
39173 
39174  if (pFramesInS16 != NULL) {
39175  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39176  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
39177  pResampler->x1.s16[iChannel] = pFramesInS16[iChannel];
39178  }
39179  pFramesInS16 += pResampler->config.channels;
39180  } else {
39181  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39182  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
39183  pResampler->x1.s16[iChannel] = 0;
39184  }
39185  }
39186 
39187  /* Filter. */
39188  ma_lpf_process_pcm_frame_s16(&pResampler->lpf, pResampler->x1.s16, pResampler->x1.s16);
39189 
39190  framesProcessedIn += 1;
39191  pResampler->inTimeInt -= 1;
39192  }
39193 
39194  if (pResampler->inTimeInt > 0) {
39195  break; /* Ran out of input data. */
39196  }
39197 
39198  /* Getting here means the frames have been loaded and filtered and we can generate the next output frame. */
39199  if (pFramesOutS16 != NULL) {
39200  MA_ASSERT(pResampler->inTimeInt == 0);
39201  ma_linear_resampler_interpolate_frame_s16(pResampler, pFramesOutS16);
39202 
39203  pFramesOutS16 += pResampler->config.channels;
39204  }
39205 
39206  framesProcessedOut += 1;
39207 
39208  /* Advance time forward. */
39209  pResampler->inTimeInt += pResampler->inAdvanceInt;
39210  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
39211  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
39212  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
39213  pResampler->inTimeInt += 1;
39214  }
39215  }
39216 
39217  *pFrameCountIn = framesProcessedIn;
39218  *pFrameCountOut = framesProcessedOut;
39219 
39220  return MA_SUCCESS;
39221 }
39222 
39223 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)
39224 {
39225  const ma_int16* pFramesInS16;
39226  /* */ ma_int16* pFramesOutS16;
39227  ma_uint64 frameCountIn;
39228  ma_uint64 frameCountOut;
39229  ma_uint64 framesProcessedIn;
39230  ma_uint64 framesProcessedOut;
39231 
39232  MA_ASSERT(pResampler != NULL);
39233  MA_ASSERT(pFrameCountIn != NULL);
39234  MA_ASSERT(pFrameCountOut != NULL);
39235 
39236  pFramesInS16 = (const ma_int16*)pFramesIn;
39237  pFramesOutS16 = ( ma_int16*)pFramesOut;
39238  frameCountIn = *pFrameCountIn;
39239  frameCountOut = *pFrameCountOut;
39240  framesProcessedIn = 0;
39241  framesProcessedOut = 0;
39242 
39243  while (framesProcessedOut < frameCountOut) {
39244  /* Before interpolating we need to load the buffers. */
39245  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
39246  ma_uint32 iChannel;
39247 
39248  if (pFramesInS16 != NULL) {
39249  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39250  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
39251  pResampler->x1.s16[iChannel] = pFramesInS16[iChannel];
39252  }
39253  pFramesInS16 += pResampler->config.channels;
39254  } else {
39255  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39256  pResampler->x0.s16[iChannel] = pResampler->x1.s16[iChannel];
39257  pResampler->x1.s16[iChannel] = 0;
39258  }
39259  }
39260 
39261  framesProcessedIn += 1;
39262  pResampler->inTimeInt -= 1;
39263  }
39264 
39265  if (pResampler->inTimeInt > 0) {
39266  break; /* Ran out of input data. */
39267  }
39268 
39269  /* Getting here means the frames have been loaded and we can generate the next output frame. */
39270  if (pFramesOutS16 != NULL) {
39271  MA_ASSERT(pResampler->inTimeInt == 0);
39272  ma_linear_resampler_interpolate_frame_s16(pResampler, pFramesOutS16);
39273 
39274  /* Filter. */
39275  ma_lpf_process_pcm_frame_s16(&pResampler->lpf, pFramesOutS16, pFramesOutS16);
39276 
39277  pFramesOutS16 += pResampler->config.channels;
39278  }
39279 
39280  framesProcessedOut += 1;
39281 
39282  /* Advance time forward. */
39283  pResampler->inTimeInt += pResampler->inAdvanceInt;
39284  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
39285  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
39286  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
39287  pResampler->inTimeInt += 1;
39288  }
39289  }
39290 
39291  *pFrameCountIn = framesProcessedIn;
39292  *pFrameCountOut = framesProcessedOut;
39293 
39294  return MA_SUCCESS;
39295 }
39296 
39297 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)
39298 {
39299  MA_ASSERT(pResampler != NULL);
39300 
39301  if (pResampler->config.sampleRateIn > pResampler->config.sampleRateOut) {
39302  return ma_linear_resampler_process_pcm_frames_s16_downsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39303  } else {
39304  return ma_linear_resampler_process_pcm_frames_s16_upsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39305  }
39306 }
39307 
39308 
39309 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)
39310 {
39311  const float* pFramesInF32;
39312  /* */ float* pFramesOutF32;
39313  ma_uint64 frameCountIn;
39314  ma_uint64 frameCountOut;
39315  ma_uint64 framesProcessedIn;
39316  ma_uint64 framesProcessedOut;
39317 
39318  MA_ASSERT(pResampler != NULL);
39319  MA_ASSERT(pFrameCountIn != NULL);
39320  MA_ASSERT(pFrameCountOut != NULL);
39321 
39322  pFramesInF32 = (const float*)pFramesIn;
39323  pFramesOutF32 = ( float*)pFramesOut;
39324  frameCountIn = *pFrameCountIn;
39325  frameCountOut = *pFrameCountOut;
39326  framesProcessedIn = 0;
39327  framesProcessedOut = 0;
39328 
39329  while (framesProcessedOut < frameCountOut) {
39330  /* Before interpolating we need to load the buffers. When doing this we need to ensure we run every input sample through the filter. */
39331  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
39332  ma_uint32 iChannel;
39333 
39334  if (pFramesInF32 != NULL) {
39335  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39336  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
39337  pResampler->x1.f32[iChannel] = pFramesInF32[iChannel];
39338  }
39339  pFramesInF32 += pResampler->config.channels;
39340  } else {
39341  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39342  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
39343  pResampler->x1.f32[iChannel] = 0;
39344  }
39345  }
39346 
39347  /* Filter. */
39348  ma_lpf_process_pcm_frame_f32(&pResampler->lpf, pResampler->x1.f32, pResampler->x1.f32);
39349 
39350  framesProcessedIn += 1;
39351  pResampler->inTimeInt -= 1;
39352  }
39353 
39354  if (pResampler->inTimeInt > 0) {
39355  break; /* Ran out of input data. */
39356  }
39357 
39358  /* Getting here means the frames have been loaded and filtered and we can generate the next output frame. */
39359  if (pFramesOutF32 != NULL) {
39360  MA_ASSERT(pResampler->inTimeInt == 0);
39361  ma_linear_resampler_interpolate_frame_f32(pResampler, pFramesOutF32);
39362 
39363  pFramesOutF32 += pResampler->config.channels;
39364  }
39365 
39366  framesProcessedOut += 1;
39367 
39368  /* Advance time forward. */
39369  pResampler->inTimeInt += pResampler->inAdvanceInt;
39370  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
39371  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
39372  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
39373  pResampler->inTimeInt += 1;
39374  }
39375  }
39376 
39377  *pFrameCountIn = framesProcessedIn;
39378  *pFrameCountOut = framesProcessedOut;
39379 
39380  return MA_SUCCESS;
39381 }
39382 
39383 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)
39384 {
39385  const float* pFramesInF32;
39386  /* */ float* pFramesOutF32;
39387  ma_uint64 frameCountIn;
39388  ma_uint64 frameCountOut;
39389  ma_uint64 framesProcessedIn;
39390  ma_uint64 framesProcessedOut;
39391 
39392  MA_ASSERT(pResampler != NULL);
39393  MA_ASSERT(pFrameCountIn != NULL);
39394  MA_ASSERT(pFrameCountOut != NULL);
39395 
39396  pFramesInF32 = (const float*)pFramesIn;
39397  pFramesOutF32 = ( float*)pFramesOut;
39398  frameCountIn = *pFrameCountIn;
39399  frameCountOut = *pFrameCountOut;
39400  framesProcessedIn = 0;
39401  framesProcessedOut = 0;
39402 
39403  while (framesProcessedOut < frameCountOut) {
39404  /* Before interpolating we need to load the buffers. */
39405  while (pResampler->inTimeInt > 0 && frameCountIn > framesProcessedIn) {
39406  ma_uint32 iChannel;
39407 
39408  if (pFramesInF32 != NULL) {
39409  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39410  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
39411  pResampler->x1.f32[iChannel] = pFramesInF32[iChannel];
39412  }
39413  pFramesInF32 += pResampler->config.channels;
39414  } else {
39415  for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
39416  pResampler->x0.f32[iChannel] = pResampler->x1.f32[iChannel];
39417  pResampler->x1.f32[iChannel] = 0;
39418  }
39419  }
39420 
39421  framesProcessedIn += 1;
39422  pResampler->inTimeInt -= 1;
39423  }
39424 
39425  if (pResampler->inTimeInt > 0) {
39426  break; /* Ran out of input data. */
39427  }
39428 
39429  /* Getting here means the frames have been loaded and we can generate the next output frame. */
39430  if (pFramesOutF32 != NULL) {
39431  MA_ASSERT(pResampler->inTimeInt == 0);
39432  ma_linear_resampler_interpolate_frame_f32(pResampler, pFramesOutF32);
39433 
39434  /* Filter. */
39435  ma_lpf_process_pcm_frame_f32(&pResampler->lpf, pFramesOutF32, pFramesOutF32);
39436 
39437  pFramesOutF32 += pResampler->config.channels;
39438  }
39439 
39440  framesProcessedOut += 1;
39441 
39442  /* Advance time forward. */
39443  pResampler->inTimeInt += pResampler->inAdvanceInt;
39444  pResampler->inTimeFrac += pResampler->inAdvanceFrac;
39445  if (pResampler->inTimeFrac >= pResampler->config.sampleRateOut) {
39446  pResampler->inTimeFrac -= pResampler->config.sampleRateOut;
39447  pResampler->inTimeInt += 1;
39448  }
39449  }
39450 
39451  *pFrameCountIn = framesProcessedIn;
39452  *pFrameCountOut = framesProcessedOut;
39453 
39454  return MA_SUCCESS;
39455 }
39456 
39457 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)
39458 {
39459  MA_ASSERT(pResampler != NULL);
39460 
39461  if (pResampler->config.sampleRateIn > pResampler->config.sampleRateOut) {
39462  return ma_linear_resampler_process_pcm_frames_f32_downsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39463  } else {
39464  return ma_linear_resampler_process_pcm_frames_f32_upsample(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39465  }
39466 }
39467 
39468 
39469 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)
39470 {
39471  if (pResampler == NULL) {
39472  return MA_INVALID_ARGS;
39473  }
39474 
39475  /* */ if (pResampler->config.format == ma_format_s16) {
39476  return ma_linear_resampler_process_pcm_frames_s16(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39477  } else if (pResampler->config.format == ma_format_f32) {
39478  return ma_linear_resampler_process_pcm_frames_f32(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39479  } else {
39480  /* 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(). */
39482  return MA_INVALID_ARGS;
39483  }
39484 }
39485 
39486 
39487 MA_API ma_result ma_linear_resampler_set_rate(ma_linear_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
39488 {
39489  return ma_linear_resampler_set_rate_internal(pResampler, sampleRateIn, sampleRateOut, /* isResamplerAlreadyInitialized = */ MA_TRUE);
39490 }
39491 
39493 {
39494  ma_uint32 n;
39495  ma_uint32 d;
39496 
39497  d = 1000;
39498  n = (ma_uint32)(ratioInOut * d);
39499 
39500  if (n == 0) {
39501  return MA_INVALID_ARGS; /* Ratio too small. */
39502  }
39503 
39504  MA_ASSERT(n != 0);
39505 
39506  return ma_linear_resampler_set_rate(pResampler, n, d);
39507 }
39508 
39509 
39511 {
39512  ma_uint64 inputFrameCount;
39513 
39514  if (pResampler == NULL) {
39515  return 0;
39516  }
39517 
39518  if (outputFrameCount == 0) {
39519  return 0;
39520  }
39521 
39522  /* Any whole input frames are consumed before the first output frame is generated. */
39523  inputFrameCount = pResampler->inTimeInt;
39524  outputFrameCount -= 1;
39525 
39526  /* The rest of the output frames can be calculated in constant time. */
39527  inputFrameCount += outputFrameCount * pResampler->inAdvanceInt;
39528  inputFrameCount += (pResampler->inTimeFrac + (outputFrameCount * pResampler->inAdvanceFrac)) / pResampler->config.sampleRateOut;
39529 
39530  return inputFrameCount;
39531 }
39532 
39534 {
39535  ma_uint64 outputFrameCount;
39536  ma_uint64 preliminaryInputFrameCountFromFrac;
39537  ma_uint64 preliminaryInputFrameCount;
39538 
39539  if (pResampler == NULL) {
39540  return 0;
39541  }
39542 
39543  /*
39544  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
39545  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
39546  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
39547  of an extra output frame. This add-by-one logic is necessary due to how the data loading logic works when processing frames.
39548  */
39549  outputFrameCount = (inputFrameCount * pResampler->config.sampleRateOut) / pResampler->config.sampleRateIn;
39550 
39551  /*
39552  We need to determine how many *whole* input frames will have been processed to generate our preliminary output frame count. This is
39553  used in the logic below to determine whether or not we need to add an extra output frame.
39554  */
39555  preliminaryInputFrameCountFromFrac = (pResampler->inTimeFrac + outputFrameCount*pResampler->inAdvanceFrac) / pResampler->config.sampleRateOut;
39556  preliminaryInputFrameCount = (pResampler->inTimeInt + outputFrameCount*pResampler->inAdvanceInt ) + preliminaryInputFrameCountFromFrac;
39557 
39558  /*
39559  If the total number of *whole* input frames that would be required to generate our preliminary output frame count is greather than
39560  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
39561  to actually process. Otherwise we need to add the extra output frame.
39562  */
39563  if (preliminaryInputFrameCount <= inputFrameCount) {
39564  outputFrameCount += 1;
39565  }
39566 
39567  return outputFrameCount;
39568 }
39569 
39571 {
39572  if (pResampler == NULL) {
39573  return 0;
39574  }
39575 
39576  return 1 + ma_lpf_get_latency(&pResampler->lpf);
39577 }
39578 
39580 {
39581  if (pResampler == NULL) {
39582  return 0;
39583  }
39584 
39585  return ma_linear_resampler_get_input_latency(pResampler) * pResampler->config.sampleRateOut / pResampler->config.sampleRateIn;
39586 }
39587 
39588 
39589 #if defined(ma_speex_resampler_h)
39590 #define MA_HAS_SPEEX_RESAMPLER
39591 
39592 static ma_result ma_result_from_speex_err(int err)
39593 {
39594  switch (err)
39595  {
39596  case RESAMPLER_ERR_SUCCESS: return MA_SUCCESS;
39598  case RESAMPLER_ERR_BAD_STATE: return MA_ERROR;
39601  case RESAMPLER_ERR_OVERFLOW: return MA_ERROR;
39602  default: return MA_ERROR;
39603  }
39604 }
39605 #endif /* ma_speex_resampler_h */
39606 
39607 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)
39608 {
39610 
39612  config.format = format;
39613  config.channels = channels;
39614  config.sampleRateIn = sampleRateIn;
39615  config.sampleRateOut = sampleRateOut;
39616  config.algorithm = algorithm;
39617 
39618  /* Linear. */
39620  config.linear.lpfNyquistFactor = 1;
39621 
39622  /* Speex. */
39623  config.speex.quality = 3; /* Cannot leave this as 0 as that is actually a valid value for Speex resampling quality. */
39624 
39625  return config;
39626 }
39627 
39629 {
39630  ma_result result;
39631 
39632  if (pResampler == NULL) {
39633  return MA_INVALID_ARGS;
39634  }
39635 
39636  MA_ZERO_OBJECT(pResampler);
39637 
39638  if (pConfig == NULL) {
39639  return MA_INVALID_ARGS;
39640  }
39641 
39642  if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
39643  return MA_INVALID_ARGS;
39644  }
39645 
39646  pResampler->config = *pConfig;
39647 
39648  switch (pConfig->algorithm)
39649  {
39651  {
39652  ma_linear_resampler_config linearConfig;
39653  linearConfig = ma_linear_resampler_config_init(pConfig->format, pConfig->channels, pConfig->sampleRateIn, pConfig->sampleRateOut);
39654  linearConfig.lpfOrder = pConfig->linear.lpfOrder;
39655  linearConfig.lpfNyquistFactor = pConfig->linear.lpfNyquistFactor;
39656 
39657  result = ma_linear_resampler_init(&linearConfig, &pResampler->state.linear);
39658  if (result != MA_SUCCESS) {
39659  return result;
39660  }
39661  } break;
39662 
39664  {
39665  #if defined(MA_HAS_SPEEX_RESAMPLER)
39666  int speexErr;
39667  pResampler->state.speex.pSpeexResamplerState = speex_resampler_init(pConfig->channels, pConfig->sampleRateIn, pConfig->sampleRateOut, pConfig->speex.quality, &speexErr);
39668  if (pResampler->state.speex.pSpeexResamplerState == NULL) {
39669  return ma_result_from_speex_err(speexErr);
39670  }
39671  #else
39672  /* Speex resampler not available. */
39673  return MA_NO_BACKEND;
39674  #endif
39675  } break;
39676 
39677  default: return MA_INVALID_ARGS;
39678  }
39679 
39680  return MA_SUCCESS;
39681 }
39682 
39683 MA_API void ma_resampler_uninit(ma_resampler* pResampler)
39684 {
39685  if (pResampler == NULL) {
39686  return;
39687  }
39688 
39689  if (pResampler->config.algorithm == ma_resample_algorithm_linear) {
39690  ma_linear_resampler_uninit(&pResampler->state.linear);
39691  }
39692 
39693 #if defined(MA_HAS_SPEEX_RESAMPLER)
39694  if (pResampler->config.algorithm == ma_resample_algorithm_speex) {
39695  speex_resampler_destroy((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState);
39696  }
39697 #endif
39698 }
39699 
39700 static ma_result ma_resampler_process_pcm_frames__read__linear(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
39701 {
39702  return ma_linear_resampler_process_pcm_frames(&pResampler->state.linear, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39703 }
39704 
39705 #if defined(MA_HAS_SPEEX_RESAMPLER)
39706 static ma_result ma_resampler_process_pcm_frames__read__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
39707 {
39708  int speexErr;
39709  ma_uint64 frameCountOut;
39710  ma_uint64 frameCountIn;
39711  ma_uint64 framesProcessedOut;
39712  ma_uint64 framesProcessedIn;
39713  unsigned int framesPerIteration = UINT_MAX;
39714 
39715  MA_ASSERT(pResampler != NULL);
39716  MA_ASSERT(pFramesOut != NULL);
39717  MA_ASSERT(pFrameCountOut != NULL);
39718  MA_ASSERT(pFrameCountIn != NULL);
39719 
39720  /*
39721  Reading from the Speex resampler requires a bit of dancing around for a few reasons. The first thing is that it's frame counts
39722  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
39723  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
39724  do this is for ma_resampler_get_required_input_frame_count() and ma_resampler_get_expected_output_frame_count().
39725  */
39726  frameCountOut = *pFrameCountOut;
39727  frameCountIn = *pFrameCountIn;
39728  framesProcessedOut = 0;
39729  framesProcessedIn = 0;
39730 
39731  while (framesProcessedOut < frameCountOut && framesProcessedIn < frameCountIn) {
39732  unsigned int frameCountInThisIteration;
39733  unsigned int frameCountOutThisIteration;
39734  const void* pFramesInThisIteration;
39735  void* pFramesOutThisIteration;
39736 
39737  frameCountInThisIteration = framesPerIteration;
39738  if ((ma_uint64)frameCountInThisIteration > (frameCountIn - framesProcessedIn)) {
39739  frameCountInThisIteration = (unsigned int)(frameCountIn - framesProcessedIn);
39740  }
39741 
39742  frameCountOutThisIteration = framesPerIteration;
39743  if ((ma_uint64)frameCountOutThisIteration > (frameCountOut - framesProcessedOut)) {
39744  frameCountOutThisIteration = (unsigned int)(frameCountOut - framesProcessedOut);
39745  }
39746 
39747  pFramesInThisIteration = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels));
39748  pFramesOutThisIteration = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels));
39749 
39750  if (pResampler->config.format == ma_format_f32) {
39751  speexErr = speex_resampler_process_interleaved_float((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, (const float*)pFramesInThisIteration, &frameCountInThisIteration, (float*)pFramesOutThisIteration, &frameCountOutThisIteration);
39752  } else if (pResampler->config.format == ma_format_s16) {
39753  speexErr = speex_resampler_process_interleaved_int((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, (const spx_int16_t*)pFramesInThisIteration, &frameCountInThisIteration, (spx_int16_t*)pFramesOutThisIteration, &frameCountOutThisIteration);
39754  } else {
39755  /* Format not supported. Should never get here. */
39757  return MA_INVALID_OPERATION;
39758  }
39759 
39760  if (speexErr != RESAMPLER_ERR_SUCCESS) {
39761  return ma_result_from_speex_err(speexErr);
39762  }
39763 
39764  framesProcessedIn += frameCountInThisIteration;
39765  framesProcessedOut += frameCountOutThisIteration;
39766  }
39767 
39768  *pFrameCountOut = framesProcessedOut;
39769  *pFrameCountIn = framesProcessedIn;
39770 
39771  return MA_SUCCESS;
39772 }
39773 #endif
39774 
39775 static ma_result ma_resampler_process_pcm_frames__read(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
39776 {
39777  MA_ASSERT(pResampler != NULL);
39778  MA_ASSERT(pFramesOut != NULL);
39779 
39780  /* pFramesOut is not NULL, which means we must have a capacity. */
39781  if (pFrameCountOut == NULL) {
39782  return MA_INVALID_ARGS;
39783  }
39784 
39785  /* It doesn't make sense to not have any input frames to process. */
39786  if (pFrameCountIn == NULL || pFramesIn == NULL) {
39787  return MA_INVALID_ARGS;
39788  }
39789 
39790  switch (pResampler->config.algorithm)
39791  {
39793  {
39794  return ma_resampler_process_pcm_frames__read__linear(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39795  }
39796 
39798  {
39799  #if defined(MA_HAS_SPEEX_RESAMPLER)
39800  return ma_resampler_process_pcm_frames__read__speex(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39801  #else
39802  break;
39803  #endif
39804  }
39805 
39806  default: break;
39807  }
39808 
39809  /* Should never get here. */
39811  return MA_INVALID_ARGS;
39812 }
39813 
39814 
39815 static ma_result ma_resampler_process_pcm_frames__seek__linear(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
39816 {
39817  MA_ASSERT(pResampler != NULL);
39818 
39819  /* Seeking is supported natively by the linear resampler. */
39820  return ma_linear_resampler_process_pcm_frames(&pResampler->state.linear, pFramesIn, pFrameCountIn, NULL, pFrameCountOut);
39821 }
39822 
39823 #if defined(MA_HAS_SPEEX_RESAMPLER)
39824 static ma_result ma_resampler_process_pcm_frames__seek__speex(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
39825 {
39826  /* The generic seek method is implemented in on top of ma_resampler_process_pcm_frames__read() by just processing into a dummy buffer. */
39827  float devnull[4096];
39828  ma_uint64 totalOutputFramesToProcess;
39829  ma_uint64 totalOutputFramesProcessed;
39830  ma_uint64 totalInputFramesProcessed;
39831  ma_uint32 bpf;
39832  ma_result result;
39833 
39834  MA_ASSERT(pResampler != NULL);
39835 
39836  totalOutputFramesProcessed = 0;
39837  totalInputFramesProcessed = 0;
39838  bpf = ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels);
39839 
39840  if (pFrameCountOut != NULL) {
39841  /* Seek by output frames. */
39842  totalOutputFramesToProcess = *pFrameCountOut;
39843  } else {
39844  /* Seek by input frames. */
39845  MA_ASSERT(pFrameCountIn != NULL);
39846  totalOutputFramesToProcess = ma_resampler_get_expected_output_frame_count(pResampler, *pFrameCountIn);
39847  }
39848 
39849  if (pFramesIn != NULL) {
39850  /* Process input data. */
39851  MA_ASSERT(pFrameCountIn != NULL);
39852  while (totalOutputFramesProcessed < totalOutputFramesToProcess && totalInputFramesProcessed < *pFrameCountIn) {
39853  ma_uint64 inputFramesToProcessThisIteration = (*pFrameCountIn - totalInputFramesProcessed);
39854  ma_uint64 outputFramesToProcessThisIteration = (totalOutputFramesToProcess - totalOutputFramesProcessed);
39855  if (outputFramesToProcessThisIteration > sizeof(devnull) / bpf) {
39856  outputFramesToProcessThisIteration = sizeof(devnull) / bpf;
39857  }
39858 
39859  result = ma_resampler_process_pcm_frames__read(pResampler, ma_offset_ptr(pFramesIn, totalInputFramesProcessed*bpf), &inputFramesToProcessThisIteration, ma_offset_ptr(devnull, totalOutputFramesProcessed*bpf), &outputFramesToProcessThisIteration);
39860  if (result != MA_SUCCESS) {
39861  return result;
39862  }
39863 
39864  totalOutputFramesProcessed += outputFramesToProcessThisIteration;
39865  totalInputFramesProcessed += inputFramesToProcessThisIteration;
39866  }
39867  } else {
39868  /* Don't process input data - just update timing and filter state as if zeroes were passed in. */
39869  while (totalOutputFramesProcessed < totalOutputFramesToProcess) {
39870  ma_uint64 inputFramesToProcessThisIteration = 16384;
39871  ma_uint64 outputFramesToProcessThisIteration = (totalOutputFramesToProcess - totalOutputFramesProcessed);
39872  if (outputFramesToProcessThisIteration > sizeof(devnull) / bpf) {
39873  outputFramesToProcessThisIteration = sizeof(devnull) / bpf;
39874  }
39875 
39876  result = ma_resampler_process_pcm_frames__read(pResampler, NULL, &inputFramesToProcessThisIteration, ma_offset_ptr(devnull, totalOutputFramesProcessed*bpf), &outputFramesToProcessThisIteration);
39877  if (result != MA_SUCCESS) {
39878  return result;
39879  }
39880 
39881  totalOutputFramesProcessed += outputFramesToProcessThisIteration;
39882  totalInputFramesProcessed += inputFramesToProcessThisIteration;
39883  }
39884  }
39885 
39886 
39887  if (pFrameCountIn != NULL) {
39888  *pFrameCountIn = totalInputFramesProcessed;
39889  }
39890  if (pFrameCountOut != NULL) {
39891  *pFrameCountOut = totalOutputFramesProcessed;
39892  }
39893 
39894  return MA_SUCCESS;
39895 }
39896 #endif
39897 
39898 static ma_result ma_resampler_process_pcm_frames__seek(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, ma_uint64* pFrameCountOut)
39899 {
39900  MA_ASSERT(pResampler != NULL);
39901 
39902  switch (pResampler->config.algorithm)
39903  {
39905  {
39906  return ma_resampler_process_pcm_frames__seek__linear(pResampler, pFramesIn, pFrameCountIn, pFrameCountOut);
39907  } break;
39908 
39910  {
39911  #if defined(MA_HAS_SPEEX_RESAMPLER)
39912  return ma_resampler_process_pcm_frames__seek__speex(pResampler, pFramesIn, pFrameCountIn, pFrameCountOut);
39913  #else
39914  break;
39915  #endif
39916  };
39917 
39918  default: break;
39919  }
39920 
39921  /* Should never hit this. */
39923  return MA_INVALID_ARGS;
39924 }
39925 
39926 
39927 MA_API ma_result ma_resampler_process_pcm_frames(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
39928 {
39929  if (pResampler == NULL) {
39930  return MA_INVALID_ARGS;
39931  }
39932 
39933  if (pFrameCountOut == NULL && pFrameCountIn == NULL) {
39934  return MA_INVALID_ARGS;
39935  }
39936 
39937  if (pFramesOut != NULL) {
39938  /* Reading. */
39939  return ma_resampler_process_pcm_frames__read(pResampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
39940  } else {
39941  /* Seeking. */
39942  return ma_resampler_process_pcm_frames__seek(pResampler, pFramesIn, pFrameCountIn, pFrameCountOut);
39943  }
39944 }
39945 
39946 MA_API ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
39947 {
39948  if (pResampler == NULL) {
39949  return MA_INVALID_ARGS;
39950  }
39951 
39952  if (sampleRateIn == 0 || sampleRateOut == 0) {
39953  return MA_INVALID_ARGS;
39954  }
39955 
39956  pResampler->config.sampleRateIn = sampleRateIn;
39957  pResampler->config.sampleRateOut = sampleRateOut;
39958 
39959  switch (pResampler->config.algorithm)
39960  {
39962  {
39963  return ma_linear_resampler_set_rate(&pResampler->state.linear, sampleRateIn, sampleRateOut);
39964  } break;
39965 
39967  {
39968  #if defined(MA_HAS_SPEEX_RESAMPLER)
39969  return ma_result_from_speex_err(speex_resampler_set_rate((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, sampleRateIn, sampleRateOut));
39970  #else
39971  break;
39972  #endif
39973  };
39974 
39975  default: break;
39976  }
39977 
39978  /* Should never get here. */
39980  return MA_INVALID_OPERATION;
39981 }
39982 
39983 MA_API ma_result ma_resampler_set_rate_ratio(ma_resampler* pResampler, float ratio)
39984 {
39985  if (pResampler == NULL) {
39986  return MA_INVALID_ARGS;
39987  }
39988 
39989  if (pResampler->config.algorithm == ma_resample_algorithm_linear) {
39990  return ma_linear_resampler_set_rate_ratio(&pResampler->state.linear, ratio);
39991  } else {
39992  /* Getting here means the backend does not have native support for setting the rate as a ratio so we just do it generically. */
39993  ma_uint32 n;
39994  ma_uint32 d;
39995 
39996  d = 1000;
39997  n = (ma_uint32)(ratio * d);
39998 
39999  if (n == 0) {
40000  return MA_INVALID_ARGS; /* Ratio too small. */
40001  }
40002 
40003  MA_ASSERT(n != 0);
40004 
40005  return ma_resampler_set_rate(pResampler, n, d);
40006  }
40007 }
40008 
40010 {
40011  if (pResampler == NULL) {
40012  return 0;
40013  }
40014 
40015  if (outputFrameCount == 0) {
40016  return 0;
40017  }
40018 
40019  switch (pResampler->config.algorithm)
40020  {
40022  {
40023  return ma_linear_resampler_get_required_input_frame_count(&pResampler->state.linear, outputFrameCount);
40024  }
40025 
40027  {
40028  #if defined(MA_HAS_SPEEX_RESAMPLER)
40030  int speexErr = ma_speex_resampler_get_required_input_frame_count((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, outputFrameCount, &count);
40031  if (speexErr != RESAMPLER_ERR_SUCCESS) {
40032  return 0;
40033  }
40034 
40035  return (ma_uint64)count;
40036  #else
40037  break;
40038  #endif
40039  }
40040 
40041  default: break;
40042  }
40043 
40044  /* Should never get here. */
40046  return 0;
40047 }
40048 
40050 {
40051  if (pResampler == NULL) {
40052  return 0; /* Invalid args. */
40053  }
40054 
40055  if (inputFrameCount == 0) {
40056  return 0;
40057  }
40058 
40059  switch (pResampler->config.algorithm)
40060  {
40062  {
40063  return ma_linear_resampler_get_expected_output_frame_count(&pResampler->state.linear, inputFrameCount);
40064  }
40065 
40067  {
40068  #if defined(MA_HAS_SPEEX_RESAMPLER)
40070  int speexErr = ma_speex_resampler_get_expected_output_frame_count((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState, inputFrameCount, &count);
40071  if (speexErr != RESAMPLER_ERR_SUCCESS) {
40072  return 0;
40073  }
40074 
40075  return (ma_uint64)count;
40076  #else
40077  break;
40078  #endif
40079  }
40080 
40081  default: break;
40082  }
40083 
40084  /* Should never get here. */
40086  return 0;
40087 }
40088 
40090 {
40091  if (pResampler == NULL) {
40092  return 0;
40093  }
40094 
40095  switch (pResampler->config.algorithm)
40096  {
40098  {
40099  return ma_linear_resampler_get_input_latency(&pResampler->state.linear);
40100  }
40101 
40103  {
40104  #if defined(MA_HAS_SPEEX_RESAMPLER)
40105  return (ma_uint64)ma_speex_resampler_get_input_latency((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState);
40106  #else
40107  break;
40108  #endif
40109  }
40110 
40111  default: break;
40112  }
40113 
40114  /* Should never get here. */
40116  return 0;
40117 }
40118 
40120 {
40121  if (pResampler == NULL) {
40122  return 0;
40123  }
40124 
40125  switch (pResampler->config.algorithm)
40126  {
40128  {
40130  }
40131 
40133  {
40134  #if defined(MA_HAS_SPEEX_RESAMPLER)
40135  return (ma_uint64)ma_speex_resampler_get_output_latency((SpeexResamplerState*)pResampler->state.speex.pSpeexResamplerState);
40136  #else
40137  break;
40138  #endif
40139  }
40140 
40141  default: break;
40142  }
40143 
40144  /* Should never get here. */
40146  return 0;
40147 }
40148 
40149 /**************************************************************************************************************************************************************
40150 
40151 Channel Conversion
40152 
40153 **************************************************************************************************************************************************************/
40154 #ifndef MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT
40155 #define MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT 12
40156 #endif
40157 
40158 #define MA_PLANE_LEFT 0
40159 #define MA_PLANE_RIGHT 1
40160 #define MA_PLANE_FRONT 2
40161 #define MA_PLANE_BACK 3
40162 #define MA_PLANE_BOTTOM 4
40163 #define MA_PLANE_TOP 5
40164 
40165 static float g_maChannelPlaneRatios[MA_CHANNEL_POSITION_COUNT][6] = {
40166  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_NONE */
40167  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_MONO */
40168  { 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_LEFT */
40169  { 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_RIGHT */
40170  { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_CENTER */
40171  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_LFE */
40172  { 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}, /* MA_CHANNEL_BACK_LEFT */
40173  { 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f}, /* MA_CHANNEL_BACK_RIGHT */
40174  { 0.25f, 0.0f, 0.75f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_LEFT_CENTER */
40175  { 0.0f, 0.25f, 0.75f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_FRONT_RIGHT_CENTER */
40176  { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, /* MA_CHANNEL_BACK_CENTER */
40177  { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_SIDE_LEFT */
40178  { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_SIDE_RIGHT */
40179  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, /* MA_CHANNEL_TOP_CENTER */
40180  { 0.33f, 0.0f, 0.33f, 0.0f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_FRONT_LEFT */
40181  { 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f}, /* MA_CHANNEL_TOP_FRONT_CENTER */
40182  { 0.0f, 0.33f, 0.33f, 0.0f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_FRONT_RIGHT */
40183  { 0.33f, 0.0f, 0.0f, 0.33f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_BACK_LEFT */
40184  { 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f}, /* MA_CHANNEL_TOP_BACK_CENTER */
40185  { 0.0f, 0.33f, 0.0f, 0.33f, 0.0f, 0.34f}, /* MA_CHANNEL_TOP_BACK_RIGHT */
40186  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_0 */
40187  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_1 */
40188  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_2 */
40189  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_3 */
40190  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_4 */
40191  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_5 */
40192  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_6 */
40193  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_7 */
40194  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_8 */
40195  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_9 */
40196  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_10 */
40197  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_11 */
40198  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_12 */
40199  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_13 */
40200  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_14 */
40201  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_15 */
40202  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_16 */
40203  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_17 */
40204  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_18 */
40205  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_19 */
40206  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_20 */
40207  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_21 */
40208  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_22 */
40209  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_23 */
40210  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_24 */
40211  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_25 */
40212  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_26 */
40213  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_27 */
40214  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_28 */
40215  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_29 */
40216  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_30 */
40217  { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* MA_CHANNEL_AUX_31 */
40218 };
40219 
40220 static float ma_calculate_channel_position_rectangular_weight(ma_channel channelPositionA, ma_channel channelPositionB)
40221 {
40222  /*
40223  Imagine the following simplified example: You have a single input speaker which is the front/left speaker which you want to convert to
40224  the following output configuration:
40225 
40226  - front/left
40227  - side/left
40228  - back/left
40229 
40230  The front/left output is easy - it the same speaker position so it receives the full contribution of the front/left input. The amount
40231  of contribution to apply to the side/left and back/left speakers, however, is a bit more complicated.
40232 
40233  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
40234  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
40235  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
40236  receive some amount of contribution from front/left speaker. The amount of contribution depends on how many planes are shared between
40237  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
40238  across 3 spatial dimensions.
40239 
40240  The first thing to do is figure out how each speaker's volume is spread over each of plane:
40241  - front/left: 2 planes (front and left) = 1/2 = half it's total volume on each plane
40242  - side/left: 1 plane (left only) = 1/1 = entire volume from left plane
40243  - back/left: 2 planes (back and left) = 1/2 = half it's total volume on each plane
40244  - top/front/left: 3 planes (top, front and left) = 1/3 = one third it's total volume on each plane
40245 
40246  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
40247  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
40248  taken by the other to produce the final contribution.
40249  */
40250 
40251  /* Contribution = Sum(Volume to Give * Volume to Take) */
40252  float contribution =
40253  g_maChannelPlaneRatios[channelPositionA][0] * g_maChannelPlaneRatios[channelPositionB][0] +
40254  g_maChannelPlaneRatios[channelPositionA][1] * g_maChannelPlaneRatios[channelPositionB][1] +
40255  g_maChannelPlaneRatios[channelPositionA][2] * g_maChannelPlaneRatios[channelPositionB][2] +
40256  g_maChannelPlaneRatios[channelPositionA][3] * g_maChannelPlaneRatios[channelPositionB][3] +
40257  g_maChannelPlaneRatios[channelPositionA][4] * g_maChannelPlaneRatios[channelPositionB][4] +
40258  g_maChannelPlaneRatios[channelPositionA][5] * g_maChannelPlaneRatios[channelPositionB][5];
40259 
40260  return contribution;
40261 }
40262 
40263 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)
40264 {
40266 
40267  /* Channel counts need to be clamped. */
40268  channelsIn = ma_min(channelsIn, ma_countof(config.channelMapIn));
40269  channelsOut = ma_min(channelsOut, ma_countof(config.channelMapOut));
40270 
40272  config.format = format;
40273  config.channelsIn = channelsIn;
40274  config.channelsOut = channelsOut;
40275  ma_channel_map_copy_or_default(config.channelMapIn, pChannelMapIn, channelsIn);
40276  ma_channel_map_copy_or_default(config.channelMapOut, pChannelMapOut, channelsOut);
40277  config.mixingMode = mixingMode;
40278 
40279  return config;
40280 }
40281 
40283 {
40285 }
40286 
40287 static ma_bool32 ma_is_spatial_channel_position(ma_channel channelPosition)
40288 {
40289  int i;
40290 
40291  if (channelPosition == MA_CHANNEL_NONE || channelPosition == MA_CHANNEL_MONO || channelPosition == MA_CHANNEL_LFE) {
40292  return MA_FALSE;
40293  }
40294 
40295  if (channelPosition >= MA_CHANNEL_AUX_0 && channelPosition <= MA_CHANNEL_AUX_31) {
40296  return MA_FALSE;
40297  }
40298 
40299  for (i = 0; i < 6; ++i) { /* Each side of a cube. */
40300  if (g_maChannelPlaneRatios[channelPosition][i] != 0) {
40301  return MA_TRUE;
40302  }
40303  }
40304 
40305  return MA_FALSE;
40306 }
40307 
40309 {
40310  ma_uint32 iChannelIn;
40311  ma_uint32 iChannelOut;
40312 
40313  if (pConverter == NULL) {
40314  return MA_INVALID_ARGS;
40315  }
40316 
40317  MA_ZERO_OBJECT(pConverter);
40318 
40319  if (pConfig == NULL) {
40320  return MA_INVALID_ARGS;
40321  }
40322 
40323  /* Basic validation for channel counts. */
40324  if (pConfig->channelsIn < MA_MIN_CHANNELS || pConfig->channelsIn > MA_MAX_CHANNELS ||
40325  pConfig->channelsOut < MA_MIN_CHANNELS || pConfig->channelsOut > MA_MAX_CHANNELS) {
40326  return MA_INVALID_ARGS;
40327  }
40328 
40329  if (!ma_channel_map_valid(pConfig->channelsIn, pConfig->channelMapIn)) {
40330  return MA_INVALID_ARGS; /* Invalid input channel map. */
40331  }
40332  if (!ma_channel_map_valid(pConfig->channelsOut, pConfig->channelMapOut)) {
40333  return MA_INVALID_ARGS; /* Invalid output channel map. */
40334  }
40335 
40336  pConverter->format = pConfig->format;
40337  pConverter->channelsIn = pConfig->channelsIn;
40338  pConverter->channelsOut = pConfig->channelsOut;
40339  ma_channel_map_copy_or_default(pConverter->channelMapIn, pConfig->channelMapIn, pConfig->channelsIn);
40340  ma_channel_map_copy_or_default(pConverter->channelMapOut, pConfig->channelMapOut, pConfig->channelsOut);
40341  pConverter->mixingMode = pConfig->mixingMode;
40342 
40343  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; iChannelIn += 1) {
40344  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40345  if (pConverter->format == ma_format_f32) {
40346  pConverter->weights.f32[iChannelIn][iChannelOut] = pConfig->weights[iChannelIn][iChannelOut];
40347  } else {
40348  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(pConfig->weights[iChannelIn][iChannelOut]);
40349  }
40350  }
40351  }
40352 
40353 
40354 
40355  /* If the input and output channels and channel maps are the same we should use a passthrough. */
40356  if (pConverter->channelsIn == pConverter->channelsOut) {
40357  if (ma_channel_map_equal(pConverter->channelsIn, pConverter->channelMapIn, pConverter->channelMapOut)) {
40358  pConverter->isPassthrough = MA_TRUE;
40359  }
40360  if (ma_channel_map_blank(pConverter->channelsIn, pConverter->channelMapIn) || ma_channel_map_blank(pConverter->channelsOut, pConverter->channelMapOut)) {
40361  pConverter->isPassthrough = MA_TRUE;
40362  }
40363  }
40364 
40365 
40366  /*
40367  We can use a simple case for expanding the mono channel. This will used when expanding a mono input into any output so long
40368  as no LFE is present in the output.
40369  */
40370  if (!pConverter->isPassthrough) {
40371  if (pConverter->channelsIn == 1 && pConverter->channelMapIn[0] == MA_CHANNEL_MONO) {
40372  /* Optimal case if no LFE is in the output channel map. */
40373  pConverter->isSimpleMonoExpansion = MA_TRUE;
40374  if (ma_channel_map_contains_channel_position(pConverter->channelsOut, pConverter->channelMapOut, MA_CHANNEL_LFE)) {
40375  pConverter->isSimpleMonoExpansion = MA_FALSE;
40376  }
40377  }
40378  }
40379 
40380  /* Another optimized case is stereo to mono. */
40381  if (!pConverter->isPassthrough) {
40382  if (pConverter->channelsOut == 1 && pConverter->channelMapOut[0] == MA_CHANNEL_MONO && pConverter->channelsIn == 2) {
40383  /* Optimal case if no LFE is in the input channel map. */
40384  pConverter->isStereoToMono = MA_TRUE;
40385  if (ma_channel_map_contains_channel_position(pConverter->channelsIn, pConverter->channelMapIn, MA_CHANNEL_LFE)) {
40386  pConverter->isStereoToMono = MA_FALSE;
40387  }
40388  }
40389  }
40390 
40391 
40392  /*
40393  Here is where we do a bit of pre-processing to know how each channel should be combined to make up the output. Rules:
40394 
40395  1) If it's a passthrough, do nothing - it's just a simple memcpy().
40396  2) If the channel counts are the same and every channel position in the input map is present in the output map, use a
40397  simple shuffle. An example might be different 5.1 channel layouts.
40398  3) Otherwise channels are blended based on spatial locality.
40399  */
40400  if (!pConverter->isPassthrough) {
40401  if (pConverter->channelsIn == pConverter->channelsOut) {
40402  ma_bool32 areAllChannelPositionsPresent = MA_TRUE;
40403  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40404  ma_bool32 isInputChannelPositionInOutput = MA_FALSE;
40405  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40406  if (pConverter->channelMapIn[iChannelIn] == pConverter->channelMapOut[iChannelOut]) {
40407  isInputChannelPositionInOutput = MA_TRUE;
40408  break;
40409  }
40410  }
40411 
40412  if (!isInputChannelPositionInOutput) {
40413  areAllChannelPositionsPresent = MA_FALSE;
40414  break;
40415  }
40416  }
40417 
40418  if (areAllChannelPositionsPresent) {
40419  pConverter->isSimpleShuffle = MA_TRUE;
40420 
40421  /*
40422  All the router will be doing is rearranging channels which means all we need to do is use a shuffling table which is just
40423  a mapping between the index of the input channel to the index of the output channel.
40424  */
40425  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40426  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40427  if (pConverter->channelMapIn[iChannelIn] == pConverter->channelMapOut[iChannelOut]) {
40428  pConverter->shuffleTable[iChannelIn] = (ma_uint8)iChannelOut;
40429  break;
40430  }
40431  }
40432  }
40433  }
40434  }
40435  }
40436 
40437 
40438  /*
40439  Here is where weights are calculated. Note that we calculate the weights at all times, even when using a passthrough and simple
40440  shuffling. We use different algorithms for calculating weights depending on our mixing mode.
40441 
40442  In simple mode we don't do any blending (except for converting between mono, which is done in a later step). Instead we just
40443  map 1:1 matching channels. In this mode, if no channels in the input channel map correspond to anything in the output channel
40444  map, nothing will be heard!
40445  */
40446 
40447  /* In all cases we need to make sure all channels that are present in both channel maps have a 1:1 mapping. */
40448  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40449  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
40450 
40451  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40452  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
40453 
40454  if (channelPosIn == channelPosOut) {
40455  if (pConverter->format == ma_format_f32) {
40456  pConverter->weights.f32[iChannelIn][iChannelOut] = 1;
40457  } else {
40458  pConverter->weights.s16[iChannelIn][iChannelOut] = (1 << MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT);
40459  }
40460  }
40461  }
40462  }
40463 
40464  /*
40465  The mono channel is accumulated on all other channels, except LFE. Make sure in this loop we exclude output mono channels since
40466  they were handled in the pass above.
40467  */
40468  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40469  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
40470 
40471  if (channelPosIn == MA_CHANNEL_MONO) {
40472  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40473  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
40474 
40475  if (channelPosOut != MA_CHANNEL_NONE && channelPosOut != MA_CHANNEL_MONO && channelPosOut != MA_CHANNEL_LFE) {
40476  if (pConverter->format == ma_format_f32) {
40477  pConverter->weights.f32[iChannelIn][iChannelOut] = 1;
40478  } else {
40479  pConverter->weights.s16[iChannelIn][iChannelOut] = (1 << MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT);
40480  }
40481  }
40482  }
40483  }
40484  }
40485 
40486  /* The output mono channel is the average of all non-none, non-mono and non-lfe input channels. */
40487  {
40488  ma_uint32 len = 0;
40489  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40490  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
40491 
40492  if (channelPosIn != MA_CHANNEL_NONE && channelPosIn != MA_CHANNEL_MONO && channelPosIn != MA_CHANNEL_LFE) {
40493  len += 1;
40494  }
40495  }
40496 
40497  if (len > 0) {
40498  float monoWeight = 1.0f / len;
40499 
40500  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40501  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
40502 
40503  if (channelPosOut == MA_CHANNEL_MONO) {
40504  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40505  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
40506 
40507  if (channelPosIn != MA_CHANNEL_NONE && channelPosIn != MA_CHANNEL_MONO && channelPosIn != MA_CHANNEL_LFE) {
40508  if (pConverter->format == ma_format_f32) {
40509  pConverter->weights.f32[iChannelIn][iChannelOut] = monoWeight;
40510  } else {
40511  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(monoWeight);
40512  }
40513  }
40514  }
40515  }
40516  }
40517  }
40518  }
40519 
40520 
40521  /* Input and output channels that are not present on the other side need to be blended in based on spatial locality. */
40522  switch (pConverter->mixingMode)
40523  {
40524  case ma_channel_mix_mode_rectangular:
40525  {
40526  /* Unmapped input channels. */
40527  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40528  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
40529 
40530  if (ma_is_spatial_channel_position(channelPosIn)) {
40531  if (!ma_channel_map_contains_channel_position(pConverter->channelsOut, pConverter->channelMapOut, channelPosIn)) {
40532  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40533  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
40534 
40535  if (ma_is_spatial_channel_position(channelPosOut)) {
40536  float weight = 0;
40537  if (pConverter->mixingMode == ma_channel_mix_mode_rectangular) {
40538  weight = ma_calculate_channel_position_rectangular_weight(channelPosIn, channelPosOut);
40539  }
40540 
40541  /* Only apply the weight if we haven't already got some contribution from the respective channels. */
40542  if (pConverter->format == ma_format_f32) {
40543  if (pConverter->weights.f32[iChannelIn][iChannelOut] == 0) {
40544  pConverter->weights.f32[iChannelIn][iChannelOut] = weight;
40545  }
40546  } else {
40547  if (pConverter->weights.s16[iChannelIn][iChannelOut] == 0) {
40548  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(weight);
40549  }
40550  }
40551  }
40552  }
40553  }
40554  }
40555  }
40556 
40557  /* Unmapped output channels. */
40558  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40559  ma_channel channelPosOut = pConverter->channelMapOut[iChannelOut];
40560 
40561  if (ma_is_spatial_channel_position(channelPosOut)) {
40562  if (!ma_channel_map_contains_channel_position(pConverter->channelsIn, pConverter->channelMapIn, channelPosOut)) {
40563  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40564  ma_channel channelPosIn = pConverter->channelMapIn[iChannelIn];
40565 
40566  if (ma_is_spatial_channel_position(channelPosIn)) {
40567  float weight = 0;
40568  if (pConverter->mixingMode == ma_channel_mix_mode_rectangular) {
40569  weight = ma_calculate_channel_position_rectangular_weight(channelPosIn, channelPosOut);
40570  }
40571 
40572  /* Only apply the weight if we haven't already got some contribution from the respective channels. */
40573  if (pConverter->format == ma_format_f32) {
40574  if (pConverter->weights.f32[iChannelIn][iChannelOut] == 0) {
40575  pConverter->weights.f32[iChannelIn][iChannelOut] = weight;
40576  }
40577  } else {
40578  if (pConverter->weights.s16[iChannelIn][iChannelOut] == 0) {
40579  pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(weight);
40580  }
40581  }
40582  }
40583  }
40584  }
40585  }
40586  }
40587  } break;
40588 
40590  {
40591  /* In simple mode, excess channels need to be silenced or dropped. */
40592  ma_uint32 iChannel;
40593  for (iChannel = 0; iChannel < ma_min(pConverter->channelsIn, pConverter->channelsOut); iChannel += 1) {
40594  if (pConverter->format == ma_format_f32) {
40595  if (pConverter->weights.f32[iChannel][iChannel] == 0) {
40596  pConverter->weights.f32[iChannel][iChannel] = 1;
40597  }
40598  } else {
40599  if (pConverter->weights.s16[iChannel][iChannel] == 0) {
40600  pConverter->weights.s16[iChannel][iChannel] = ma_channel_converter_float_to_fixed(1);
40601  }
40602  }
40603  }
40604  } break;
40605 
40607  default:
40608  {
40609  /* Fallthrough. */
40610  } break;
40611  }
40612 
40613 
40614  return MA_SUCCESS;
40615 }
40616 
40618 {
40619  if (pConverter == NULL) {
40620  return;
40621  }
40622 }
40623 
40624 static ma_result ma_channel_converter_process_pcm_frames__passthrough(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
40625 {
40626  MA_ASSERT(pConverter != NULL);
40627  MA_ASSERT(pFramesOut != NULL);
40628  MA_ASSERT(pFramesIn != NULL);
40629 
40630  ma_copy_memory_64(pFramesOut, pFramesIn, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
40631  return MA_SUCCESS;
40632 }
40633 
40634 static ma_result ma_channel_converter_process_pcm_frames__simple_shuffle(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
40635 {
40636  ma_uint32 iFrame;
40637  ma_uint32 iChannelIn;
40638 
40639  MA_ASSERT(pConverter != NULL);
40640  MA_ASSERT(pFramesOut != NULL);
40641  MA_ASSERT(pFramesIn != NULL);
40642  MA_ASSERT(pConverter->channelsIn == pConverter->channelsOut);
40643 
40644  switch (pConverter->format)
40645  {
40646  case ma_format_u8:
40647  {
40648  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
40649  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
40650 
40651  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40652  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40653  pFramesOutU8[pConverter->shuffleTable[iChannelIn]] = pFramesInU8[iChannelIn];
40654  }
40655 
40656  pFramesOutU8 += pConverter->channelsOut;
40657  pFramesInU8 += pConverter->channelsIn;
40658  }
40659  } break;
40660 
40661  case ma_format_s16:
40662  {
40663  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
40664  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
40665 
40666  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40667  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40668  pFramesOutS16[pConverter->shuffleTable[iChannelIn]] = pFramesInS16[iChannelIn];
40669  }
40670 
40671  pFramesOutS16 += pConverter->channelsOut;
40672  pFramesInS16 += pConverter->channelsIn;
40673  }
40674  } break;
40675 
40676  case ma_format_s24:
40677  {
40678  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
40679  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
40680 
40681  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40682  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40683  ma_uint32 iChannelOut = pConverter->shuffleTable[iChannelIn];
40684  pFramesOutS24[iChannelOut*3 + 0] = pFramesInS24[iChannelIn*3 + 0];
40685  pFramesOutS24[iChannelOut*3 + 1] = pFramesInS24[iChannelIn*3 + 1];
40686  pFramesOutS24[iChannelOut*3 + 2] = pFramesInS24[iChannelIn*3 + 2];
40687  }
40688 
40689  pFramesOutS24 += pConverter->channelsOut*3;
40690  pFramesInS24 += pConverter->channelsIn*3;
40691  }
40692  } break;
40693 
40694  case ma_format_s32:
40695  {
40696  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
40697  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
40698 
40699  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40700  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40701  pFramesOutS32[pConverter->shuffleTable[iChannelIn]] = pFramesInS32[iChannelIn];
40702  }
40703 
40704  pFramesOutS32 += pConverter->channelsOut;
40705  pFramesInS32 += pConverter->channelsIn;
40706  }
40707  } break;
40708 
40709  case ma_format_f32:
40710  {
40711  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
40712  const float* pFramesInF32 = (const float*)pFramesIn;
40713 
40714  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40715  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40716  pFramesOutF32[pConverter->shuffleTable[iChannelIn]] = pFramesInF32[iChannelIn];
40717  }
40718 
40719  pFramesOutF32 += pConverter->channelsOut;
40720  pFramesInF32 += pConverter->channelsIn;
40721  }
40722  } break;
40723 
40724  default: return MA_INVALID_OPERATION; /* Unknown format. */
40725  }
40726 
40727  return MA_SUCCESS;
40728 }
40729 
40730 static ma_result ma_channel_converter_process_pcm_frames__simple_mono_expansion(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
40731 {
40732  ma_uint64 iFrame;
40733 
40734  MA_ASSERT(pConverter != NULL);
40735  MA_ASSERT(pFramesOut != NULL);
40736  MA_ASSERT(pFramesIn != NULL);
40737  MA_ASSERT(pConverter->channelsIn == 1);
40738 
40739  switch (pConverter->format)
40740  {
40741  case ma_format_u8:
40742  {
40743  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
40744  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
40745 
40746  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40747  ma_uint32 iChannel;
40748  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
40749  pFramesOutU8[iFrame*pConverter->channelsOut + iChannel] = pFramesInU8[iFrame];
40750  }
40751  }
40752  } break;
40753 
40754  case ma_format_s16:
40755  {
40756  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
40757  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
40758 
40759  if (pConverter->channelsOut == 2) {
40760  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40761  pFramesOutS16[iFrame*2 + 0] = pFramesInS16[iFrame];
40762  pFramesOutS16[iFrame*2 + 1] = pFramesInS16[iFrame];
40763  }
40764  } else {
40765  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40766  ma_uint32 iChannel;
40767  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
40768  pFramesOutS16[iFrame*pConverter->channelsOut + iChannel] = pFramesInS16[iFrame];
40769  }
40770  }
40771  }
40772  } break;
40773 
40774  case ma_format_s24:
40775  {
40776  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
40777  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
40778 
40779  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40780  ma_uint32 iChannel;
40781  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
40782  ma_uint64 iSampleOut = iFrame*pConverter->channelsOut + iChannel;
40783  ma_uint64 iSampleIn = iFrame;
40784  pFramesOutS24[iSampleOut*3 + 0] = pFramesInS24[iSampleIn*3 + 0];
40785  pFramesOutS24[iSampleOut*3 + 1] = pFramesInS24[iSampleIn*3 + 1];
40786  pFramesOutS24[iSampleOut*3 + 2] = pFramesInS24[iSampleIn*3 + 2];
40787  }
40788  }
40789  } break;
40790 
40791  case ma_format_s32:
40792  {
40793  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
40794  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
40795 
40796  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40797  ma_uint32 iChannel;
40798  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
40799  pFramesOutS32[iFrame*pConverter->channelsOut + iChannel] = pFramesInS32[iFrame];
40800  }
40801  }
40802  } break;
40803 
40804  case ma_format_f32:
40805  {
40806  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
40807  const float* pFramesInF32 = (const float*)pFramesIn;
40808 
40809  if (pConverter->channelsOut == 2) {
40810  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40811  pFramesOutF32[iFrame*2 + 0] = pFramesInF32[iFrame];
40812  pFramesOutF32[iFrame*2 + 1] = pFramesInF32[iFrame];
40813  }
40814  } else {
40815  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40816  ma_uint32 iChannel;
40817  for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
40818  pFramesOutF32[iFrame*pConverter->channelsOut + iChannel] = pFramesInF32[iFrame];
40819  }
40820  }
40821  }
40822  } break;
40823 
40824  default: return MA_INVALID_OPERATION; /* Unknown format. */
40825  }
40826 
40827  return MA_SUCCESS;
40828 }
40829 
40830 static ma_result ma_channel_converter_process_pcm_frames__stereo_to_mono(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
40831 {
40832  ma_uint64 iFrame;
40833 
40834  MA_ASSERT(pConverter != NULL);
40835  MA_ASSERT(pFramesOut != NULL);
40836  MA_ASSERT(pFramesIn != NULL);
40837  MA_ASSERT(pConverter->channelsIn == 2);
40838  MA_ASSERT(pConverter->channelsOut == 1);
40839 
40840  switch (pConverter->format)
40841  {
40842  case ma_format_u8:
40843  {
40844  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
40845  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
40846 
40847  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40848  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));
40849  }
40850  } break;
40851 
40852  case ma_format_s16:
40853  {
40854  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
40855  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
40856 
40857  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40858  pFramesOutS16[iFrame] = (ma_int16)(((ma_int32)pFramesInS16[iFrame*2+0] + (ma_int32)pFramesInS16[iFrame*2+1]) / 2);
40859  }
40860  } break;
40861 
40862  case ma_format_s24:
40863  {
40864  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
40865  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
40866 
40867  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40868  ma_int64 s24_0 = ma_pcm_sample_s24_to_s32_no_scale(&pFramesInS24[(iFrame*2+0)*3]);
40869  ma_int64 s24_1 = ma_pcm_sample_s24_to_s32_no_scale(&pFramesInS24[(iFrame*2+1)*3]);
40870  ma_pcm_sample_s32_to_s24_no_scale((s24_0 + s24_1) / 2, &pFramesOutS24[iFrame*3]);
40871  }
40872  } break;
40873 
40874  case ma_format_s32:
40875  {
40876  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
40877  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
40878 
40879  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40880  pFramesOutS32[iFrame] = (ma_int16)(((ma_int32)pFramesInS32[iFrame*2+0] + (ma_int32)pFramesInS32[iFrame*2+1]) / 2);
40881  }
40882  } break;
40883 
40884  case ma_format_f32:
40885  {
40886  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
40887  const float* pFramesInF32 = (const float*)pFramesIn;
40888 
40889  for (iFrame = 0; iFrame < frameCount; ++iFrame) {
40890  pFramesOutF32[iFrame] = (pFramesInF32[iFrame*2+0] + pFramesInF32[iFrame*2+1]) * 0.5f;
40891  }
40892  } break;
40893 
40894  default: return MA_INVALID_OPERATION; /* Unknown format. */
40895  }
40896 
40897  return MA_SUCCESS;
40898 }
40899 
40900 static ma_result ma_channel_converter_process_pcm_frames__weights(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
40901 {
40902  ma_uint32 iFrame;
40903  ma_uint32 iChannelIn;
40904  ma_uint32 iChannelOut;
40905 
40906  MA_ASSERT(pConverter != NULL);
40907  MA_ASSERT(pFramesOut != NULL);
40908  MA_ASSERT(pFramesIn != NULL);
40909 
40910  /* This is the more complicated case. Each of the output channels is accumulated with 0 or more input channels. */
40911 
40912  /* Clear. */
40913  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
40914 
40915  /* Accumulate. */
40916  switch (pConverter->format)
40917  {
40918  case ma_format_u8:
40919  {
40920  /* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
40921  const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
40922 
40923  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40924  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40925  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40926  ma_int16 u8_O = ma_pcm_sample_u8_to_s16_no_scale(pFramesOutU8[iFrame*pConverter->channelsOut + iChannelOut]);
40927  ma_int16 u8_I = ma_pcm_sample_u8_to_s16_no_scale(pFramesInU8 [iFrame*pConverter->channelsIn + iChannelIn ]);
40928  ma_int32 s = (ma_int32)ma_clamp(u8_O + ((u8_I * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT), -128, 127);
40929  pFramesOutU8[iFrame*pConverter->channelsOut + iChannelOut] = ma_clip_u8((ma_int16)s);
40930  }
40931  }
40932  }
40933  } break;
40934 
40935  case ma_format_s16:
40936  {
40937  /* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
40938  const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
40939 
40940  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40941  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40942  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40943  ma_int32 s = pFramesOutS16[iFrame*pConverter->channelsOut + iChannelOut];
40944  s += (pFramesInS16[iFrame*pConverter->channelsIn + iChannelIn] * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT;
40945 
40946  pFramesOutS16[iFrame*pConverter->channelsOut + iChannelOut] = (ma_int16)ma_clamp(s, -32768, 32767);
40947  }
40948  }
40949  }
40950  } break;
40951 
40952  case ma_format_s24:
40953  {
40954  /* */ ma_uint8* pFramesOutS24 = ( ma_uint8*)pFramesOut;
40955  const ma_uint8* pFramesInS24 = (const ma_uint8*)pFramesIn;
40956 
40957  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40958  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40959  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40960  ma_int64 s24_O = ma_pcm_sample_s24_to_s32_no_scale(&pFramesOutS24[(iFrame*pConverter->channelsOut + iChannelOut)*3]);
40961  ma_int64 s24_I = ma_pcm_sample_s24_to_s32_no_scale(&pFramesInS24 [(iFrame*pConverter->channelsIn + iChannelIn )*3]);
40962  ma_int64 s24 = (ma_int32)ma_clamp(s24_O + ((s24_I * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT), -8388608, 8388607);
40963  ma_pcm_sample_s32_to_s24_no_scale(s24, &pFramesOutS24[(iFrame*pConverter->channelsOut + iChannelOut)*3]);
40964  }
40965  }
40966  }
40967  } break;
40968 
40969  case ma_format_s32:
40970  {
40971  /* */ ma_int32* pFramesOutS32 = ( ma_int32*)pFramesOut;
40972  const ma_int32* pFramesInS32 = (const ma_int32*)pFramesIn;
40973 
40974  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40975  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40976  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40977  ma_int64 s = pFramesOutS32[iFrame*pConverter->channelsOut + iChannelOut];
40978  s += ((ma_int64)pFramesInS32[iFrame*pConverter->channelsIn + iChannelIn] * pConverter->weights.s16[iChannelIn][iChannelOut]) >> MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT;
40979 
40980  pFramesOutS32[iFrame*pConverter->channelsOut + iChannelOut] = ma_clip_s32(s);
40981  }
40982  }
40983  }
40984  } break;
40985 
40986  case ma_format_f32:
40987  {
40988  /* */ float* pFramesOutF32 = ( float*)pFramesOut;
40989  const float* pFramesInF32 = (const float*)pFramesIn;
40990 
40991  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
40992  for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
40993  for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
40994  pFramesOutF32[iFrame*pConverter->channelsOut + iChannelOut] += pFramesInF32[iFrame*pConverter->channelsIn + iChannelIn] * pConverter->weights.f32[iChannelIn][iChannelOut];
40995  }
40996  }
40997  }
40998  } break;
40999 
41000  default: return MA_INVALID_OPERATION; /* Unknown format. */
41001  }
41002 
41003  return MA_SUCCESS;
41004 }
41005 
41006 MA_API ma_result ma_channel_converter_process_pcm_frames(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
41007 {
41008  if (pConverter == NULL) {
41009  return MA_INVALID_ARGS;
41010  }
41011 
41012  if (pFramesOut == NULL) {
41013  return MA_INVALID_ARGS;
41014  }
41015 
41016  if (pFramesIn == NULL) {
41017  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
41018  return MA_SUCCESS;
41019  }
41020 
41021  if (pConverter->isPassthrough) {
41022  return ma_channel_converter_process_pcm_frames__passthrough(pConverter, pFramesOut, pFramesIn, frameCount);
41023  } else if (pConverter->isSimpleShuffle) {
41024  return ma_channel_converter_process_pcm_frames__simple_shuffle(pConverter, pFramesOut, pFramesIn, frameCount);
41025  } else if (pConverter->isSimpleMonoExpansion) {
41026  return ma_channel_converter_process_pcm_frames__simple_mono_expansion(pConverter, pFramesOut, pFramesIn, frameCount);
41027  } else if (pConverter->isStereoToMono) {
41028  return ma_channel_converter_process_pcm_frames__stereo_to_mono(pConverter, pFramesOut, pFramesIn, frameCount);
41029  } else {
41030  return ma_channel_converter_process_pcm_frames__weights(pConverter, pFramesOut, pFramesIn, frameCount);
41031  }
41032 }
41033 
41034 
41035 /**************************************************************************************************************************************************************
41036 
41037 Data Conversion
41038 
41039 **************************************************************************************************************************************************************/
41041 {
41044 
41045  config.ditherMode = ma_dither_mode_none;
41046  config.resampling.algorithm = ma_resample_algorithm_linear;
41047  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. */
41048 
41049  /* Linear resampling defaults. */
41050  config.resampling.linear.lpfOrder = 1;
41051  config.resampling.linear.lpfNyquistFactor = 1;
41052 
41053  /* Speex resampling defaults. */
41054  config.resampling.speex.quality = 3;
41055 
41056  return config;
41057 }
41058 
41059 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)
41060 {
41062  config.formatIn = formatIn;
41063  config.formatOut = formatOut;
41064  config.channelsIn = ma_min(channelsIn, MA_MAX_CHANNELS);
41065  config.channelsOut = ma_min(channelsOut, MA_MAX_CHANNELS);
41066  config.sampleRateIn = sampleRateIn;
41067  config.sampleRateOut = sampleRateOut;
41068 
41069  return config;
41070 }
41071 
41073 {
41074  ma_result result;
41075  ma_format midFormat;
41076 
41077  if (pConverter == NULL) {
41078  return MA_INVALID_ARGS;
41079  }
41080 
41081  MA_ZERO_OBJECT(pConverter);
41082 
41083  if (pConfig == NULL) {
41084  return MA_INVALID_ARGS;
41085  }
41086 
41087  pConverter->config = *pConfig;
41088 
41089  /* Basic validation. */
41090  if (pConfig->channelsIn < MA_MIN_CHANNELS || pConfig->channelsOut < MA_MIN_CHANNELS ||
41091  pConfig->channelsIn > MA_MAX_CHANNELS || pConfig->channelsOut > MA_MAX_CHANNELS) {
41092  return MA_INVALID_ARGS;
41093  }
41094 
41095  /*
41096  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
41097  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
41098  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
41099  use f32.
41100  */
41101  /* */ if (pConverter->config.formatOut == ma_format_s16 || pConverter->config.formatOut == ma_format_f32) {
41102  midFormat = pConverter->config.formatOut;
41103  } else if (pConverter->config.formatIn == ma_format_s16 || pConverter->config.formatIn == ma_format_f32) {
41104  midFormat = pConverter->config.formatIn;
41105  } else {
41106  midFormat = ma_format_f32;
41107  }
41108 
41109  /* Channel converter. We always initialize this, but we check if it configures itself as a passthrough to determine whether or not it's needed. */
41110  {
41111  ma_uint32 iChannelIn;
41112  ma_uint32 iChannelOut;
41113  ma_channel_converter_config channelConverterConfig;
41114 
41115  channelConverterConfig = ma_channel_converter_config_init(midFormat, pConverter->config.channelsIn, pConverter->config.channelMapIn, pConverter->config.channelsOut, pConverter->config.channelMapOut, pConverter->config.channelMixMode);
41116 
41117  /* Channel weights. */
41118  for (iChannelIn = 0; iChannelIn < pConverter->config.channelsIn; iChannelIn += 1) {
41119  for (iChannelOut = 0; iChannelOut < pConverter->config.channelsOut; iChannelOut += 1) {
41120  channelConverterConfig.weights[iChannelIn][iChannelOut] = pConverter->config.channelWeights[iChannelIn][iChannelOut];
41121  }
41122  }
41123 
41124  result = ma_channel_converter_init(&channelConverterConfig, &pConverter->channelConverter);
41125  if (result != MA_SUCCESS) {
41126  return result;
41127  }
41128 
41129  /* If the channel converter is not a passthrough we need to enable it. Otherwise we can skip it. */
41130  if (pConverter->channelConverter.isPassthrough == MA_FALSE) {
41131  pConverter->hasChannelConverter = MA_TRUE;
41132  }
41133  }
41134 
41135 
41136  /* 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. */
41137  if (pConverter->config.resampling.allowDynamicSampleRate == MA_FALSE) {
41138  pConverter->config.resampling.allowDynamicSampleRate = pConverter->config.sampleRateIn != pConverter->config.sampleRateOut;
41139  }
41140 
41141  /* Resampler. */
41142  if (pConverter->config.resampling.allowDynamicSampleRate) {
41143  ma_resampler_config resamplerConfig;
41144  ma_uint32 resamplerChannels;
41145 
41146  /* 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. */
41147  if (pConverter->config.channelsIn < pConverter->config.channelsOut) {
41148  resamplerChannels = pConverter->config.channelsIn;
41149  } else {
41150  resamplerChannels = pConverter->config.channelsOut;
41151  }
41152 
41153  resamplerConfig = ma_resampler_config_init(midFormat, resamplerChannels, pConverter->config.sampleRateIn, pConverter->config.sampleRateOut, pConverter->config.resampling.algorithm);
41154  resamplerConfig.linear.lpfOrder = pConverter->config.resampling.linear.lpfOrder;
41155  resamplerConfig.linear.lpfNyquistFactor = pConverter->config.resampling.linear.lpfNyquistFactor;
41156  resamplerConfig.speex.quality = pConverter->config.resampling.speex.quality;
41157 
41158  result = ma_resampler_init(&resamplerConfig, &pConverter->resampler);
41159  if (result != MA_SUCCESS) {
41160  return result;
41161  }
41162 
41163  pConverter->hasResampler = MA_TRUE;
41164  }
41165 
41166 
41167  /* We can simplify pre- and post-format conversion if we have neither channel conversion nor resampling. */
41168  if (pConverter->hasChannelConverter == MA_FALSE && pConverter->hasResampler == MA_FALSE) {
41169  /* 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. */
41170  if (pConverter->config.formatIn == pConverter->config.formatOut) {
41171  /* The formats are the same so we can just pass through. */
41172  pConverter->hasPreFormatConversion = MA_FALSE;
41173  pConverter->hasPostFormatConversion = MA_FALSE;
41174  } else {
41175  /* The formats are different so we need to do either pre- or post-format conversion. It doesn't matter which. */
41176  pConverter->hasPreFormatConversion = MA_FALSE;
41177  pConverter->hasPostFormatConversion = MA_TRUE;
41178  }
41179  } else {
41180  /* We have a channel converter and/or resampler so we'll need channel conversion based on the mid format. */
41181  if (pConverter->config.formatIn != midFormat) {
41182  pConverter->hasPreFormatConversion = MA_TRUE;
41183  }
41184  if (pConverter->config.formatOut != midFormat) {
41185  pConverter->hasPostFormatConversion = MA_TRUE;
41186  }
41187  }
41188 
41189  /* We can enable passthrough optimizations if applicable. Note that we'll only be able to do this if the sample rate is static. */
41190  if (pConverter->hasPreFormatConversion == MA_FALSE &&
41191  pConverter->hasPostFormatConversion == MA_FALSE &&
41192  pConverter->hasChannelConverter == MA_FALSE &&
41193  pConverter->hasResampler == MA_FALSE) {
41194  pConverter->isPassthrough = MA_TRUE;
41195  }
41196 
41197  return MA_SUCCESS;
41198 }
41199 
41201 {
41202  if (pConverter == NULL) {
41203  return;
41204  }
41205 
41206  if (pConverter->hasResampler) {
41207  ma_resampler_uninit(&pConverter->resampler);
41208  }
41209 }
41210 
41211 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)
41212 {
41213  ma_uint64 frameCountIn;
41214  ma_uint64 frameCountOut;
41215  ma_uint64 frameCount;
41216 
41217  MA_ASSERT(pConverter != NULL);
41218 
41219  frameCountIn = 0;
41220  if (pFrameCountIn != NULL) {
41221  frameCountIn = *pFrameCountIn;
41222  }
41223 
41224  frameCountOut = 0;
41225  if (pFrameCountOut != NULL) {
41226  frameCountOut = *pFrameCountOut;
41227  }
41228 
41229  frameCount = ma_min(frameCountIn, frameCountOut);
41230 
41231  if (pFramesOut != NULL) {
41232  if (pFramesIn != NULL) {
41233  ma_copy_memory_64(pFramesOut, pFramesIn, frameCount * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41234  } else {
41235  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41236  }
41237  }
41238 
41239  if (pFrameCountIn != NULL) {
41240  *pFrameCountIn = frameCount;
41241  }
41242  if (pFrameCountOut != NULL) {
41243  *pFrameCountOut = frameCount;
41244  }
41245 
41246  return MA_SUCCESS;
41247 }
41248 
41249 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)
41250 {
41251  ma_uint64 frameCountIn;
41252  ma_uint64 frameCountOut;
41253  ma_uint64 frameCount;
41254 
41255  MA_ASSERT(pConverter != NULL);
41256 
41257  frameCountIn = 0;
41258  if (pFrameCountIn != NULL) {
41259  frameCountIn = *pFrameCountIn;
41260  }
41261 
41262  frameCountOut = 0;
41263  if (pFrameCountOut != NULL) {
41264  frameCountOut = *pFrameCountOut;
41265  }
41266 
41267  frameCount = ma_min(frameCountIn, frameCountOut);
41268 
41269  if (pFramesOut != NULL) {
41270  if (pFramesIn != NULL) {
41271  ma_convert_pcm_frames_format(pFramesOut, pConverter->config.formatOut, pFramesIn, pConverter->config.formatIn, frameCount, pConverter->config.channelsIn, pConverter->config.ditherMode);
41272  } else {
41273  ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41274  }
41275  }
41276 
41277  if (pFrameCountIn != NULL) {
41278  *pFrameCountIn = frameCount;
41279  }
41280  if (pFrameCountOut != NULL) {
41281  *pFrameCountOut = frameCount;
41282  }
41283 
41284  return MA_SUCCESS;
41285 }
41286 
41287 
41288 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)
41289 {
41290  ma_result result = MA_SUCCESS;
41291  ma_uint64 frameCountIn;
41292  ma_uint64 frameCountOut;
41293  ma_uint64 framesProcessedIn;
41294  ma_uint64 framesProcessedOut;
41295 
41296  MA_ASSERT(pConverter != NULL);
41297 
41298  frameCountIn = 0;
41299  if (pFrameCountIn != NULL) {
41300  frameCountIn = *pFrameCountIn;
41301  }
41302 
41303  frameCountOut = 0;
41304  if (pFrameCountOut != NULL) {
41305  frameCountOut = *pFrameCountOut;
41306  }
41307 
41308  framesProcessedIn = 0;
41309  framesProcessedOut = 0;
41310 
41311  while (framesProcessedOut < frameCountOut) {
41312  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
41313  const ma_uint32 tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
41314  const void* pFramesInThisIteration;
41315  /* */ void* pFramesOutThisIteration;
41316  ma_uint64 frameCountInThisIteration;
41317  ma_uint64 frameCountOutThisIteration;
41318 
41319  if (pFramesIn != NULL) {
41320  pFramesInThisIteration = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
41321  } else {
41322  pFramesInThisIteration = NULL;
41323  }
41324 
41325  if (pFramesOut != NULL) {
41326  pFramesOutThisIteration = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41327  } else {
41328  pFramesOutThisIteration = NULL;
41329  }
41330 
41331  /* Do a pre format conversion if necessary. */
41332  if (pConverter->hasPreFormatConversion) {
41333  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
41334  const ma_uint32 tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
41335 
41336  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
41337  if (frameCountInThisIteration > tempBufferInCap) {
41338  frameCountInThisIteration = tempBufferInCap;
41339  }
41340 
41341  if (pConverter->hasPostFormatConversion) {
41342  if (frameCountInThisIteration > tempBufferOutCap) {
41343  frameCountInThisIteration = tempBufferOutCap;
41344  }
41345  }
41346 
41347  if (pFramesInThisIteration != NULL) {
41348  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->resampler.config.format, pFramesInThisIteration, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
41349  } else {
41350  MA_ZERO_MEMORY(pTempBufferIn, sizeof(pTempBufferIn));
41351  }
41352 
41353  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
41354 
41355  if (pConverter->hasPostFormatConversion) {
41356  /* Both input and output conversion required. Output to the temp buffer. */
41357  if (frameCountOutThisIteration > tempBufferOutCap) {
41358  frameCountOutThisIteration = tempBufferOutCap;
41359  }
41360 
41361  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferIn, &frameCountInThisIteration, pTempBufferOut, &frameCountOutThisIteration);
41362  } else {
41363  /* Only pre-format required. Output straight to the output buffer. */
41364  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferIn, &frameCountInThisIteration, pFramesOutThisIteration, &frameCountOutThisIteration);
41365  }
41366 
41367  if (result != MA_SUCCESS) {
41368  break;
41369  }
41370  } else {
41371  /* No pre-format required. Just read straight from the input buffer. */
41372  MA_ASSERT(pConverter->hasPostFormatConversion == MA_TRUE);
41373 
41374  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
41375  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
41376  if (frameCountOutThisIteration > tempBufferOutCap) {
41377  frameCountOutThisIteration = tempBufferOutCap;
41378  }
41379 
41380  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pFramesInThisIteration, &frameCountInThisIteration, pTempBufferOut, &frameCountOutThisIteration);
41381  if (result != MA_SUCCESS) {
41382  break;
41383  }
41384  }
41385 
41386  /* If we are doing a post format conversion we need to do that now. */
41387  if (pConverter->hasPostFormatConversion) {
41388  if (pFramesOutThisIteration != NULL) {
41389  ma_convert_pcm_frames_format(pFramesOutThisIteration, pConverter->config.formatOut, pTempBufferOut, pConverter->resampler.config.format, frameCountOutThisIteration, pConverter->resampler.config.channels, pConverter->config.ditherMode);
41390  }
41391  }
41392 
41393  framesProcessedIn += frameCountInThisIteration;
41394  framesProcessedOut += frameCountOutThisIteration;
41395 
41396  MA_ASSERT(framesProcessedIn <= frameCountIn);
41397  MA_ASSERT(framesProcessedOut <= frameCountOut);
41398 
41399  if (frameCountOutThisIteration == 0) {
41400  break; /* Consumed all of our input data. */
41401  }
41402  }
41403 
41404  if (pFrameCountIn != NULL) {
41405  *pFrameCountIn = framesProcessedIn;
41406  }
41407  if (pFrameCountOut != NULL) {
41408  *pFrameCountOut = framesProcessedOut;
41409  }
41410 
41411  return result;
41412 }
41413 
41414 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)
41415 {
41416  MA_ASSERT(pConverter != NULL);
41417 
41418  if (pConverter->hasPreFormatConversion == MA_FALSE && pConverter->hasPostFormatConversion == MA_FALSE) {
41419  /* Neither pre- nor post-format required. This is simple case where only resampling is required. */
41420  return ma_resampler_process_pcm_frames(&pConverter->resampler, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41421  } else {
41422  /* Format conversion required. */
41423  return ma_data_converter_process_pcm_frames__resample_with_format_conversion(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41424  }
41425 }
41426 
41427 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)
41428 {
41429  ma_result result;
41430  ma_uint64 frameCountIn;
41431  ma_uint64 frameCountOut;
41432  ma_uint64 frameCount;
41433 
41434  MA_ASSERT(pConverter != NULL);
41435 
41436  frameCountIn = 0;
41437  if (pFrameCountIn != NULL) {
41438  frameCountIn = *pFrameCountIn;
41439  }
41440 
41441  frameCountOut = 0;
41442  if (pFrameCountOut != NULL) {
41443  frameCountOut = *pFrameCountOut;
41444  }
41445 
41446  frameCount = ma_min(frameCountIn, frameCountOut);
41447 
41448  if (pConverter->hasPreFormatConversion == MA_FALSE && pConverter->hasPostFormatConversion == MA_FALSE) {
41449  /* No format conversion required. */
41450  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pFramesOut, pFramesIn, frameCount);
41451  if (result != MA_SUCCESS) {
41452  return result;
41453  }
41454  } else {
41455  /* Format conversion required. */
41456  ma_uint64 framesProcessed = 0;
41457 
41458  while (framesProcessed < frameCount) {
41459  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
41460  const ma_uint32 tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
41461  const void* pFramesInThisIteration;
41462  /* */ void* pFramesOutThisIteration;
41463  ma_uint64 frameCountThisIteration;
41464 
41465  if (pFramesIn != NULL) {
41466  pFramesInThisIteration = ma_offset_ptr(pFramesIn, framesProcessed * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
41467  } else {
41468  pFramesInThisIteration = NULL;
41469  }
41470 
41471  if (pFramesOut != NULL) {
41472  pFramesOutThisIteration = ma_offset_ptr(pFramesOut, framesProcessed * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41473  } else {
41474  pFramesOutThisIteration = NULL;
41475  }
41476 
41477  /* Do a pre format conversion if necessary. */
41478  if (pConverter->hasPreFormatConversion) {
41479  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
41480  const ma_uint32 tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsIn);
41481 
41482  frameCountThisIteration = (frameCount - framesProcessed);
41483  if (frameCountThisIteration > tempBufferInCap) {
41484  frameCountThisIteration = tempBufferInCap;
41485  }
41486 
41487  if (pConverter->hasPostFormatConversion) {
41488  if (frameCountThisIteration > tempBufferOutCap) {
41489  frameCountThisIteration = tempBufferOutCap;
41490  }
41491  }
41492 
41493  if (pFramesInThisIteration != NULL) {
41494  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->channelConverter.format, pFramesInThisIteration, pConverter->config.formatIn, frameCountThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
41495  } else {
41496  MA_ZERO_MEMORY(pTempBufferIn, sizeof(pTempBufferIn));
41497  }
41498 
41499  if (pConverter->hasPostFormatConversion) {
41500  /* Both input and output conversion required. Output to the temp buffer. */
41501  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferOut, pTempBufferIn, frameCountThisIteration);
41502  } else {
41503  /* Only pre-format required. Output straight to the output buffer. */
41504  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pFramesOutThisIteration, pTempBufferIn, frameCountThisIteration);
41505  }
41506 
41507  if (result != MA_SUCCESS) {
41508  break;
41509  }
41510  } else {
41511  /* No pre-format required. Just read straight from the input buffer. */
41512  MA_ASSERT(pConverter->hasPostFormatConversion == MA_TRUE);
41513 
41514  frameCountThisIteration = (frameCount - framesProcessed);
41515  if (frameCountThisIteration > tempBufferOutCap) {
41516  frameCountThisIteration = tempBufferOutCap;
41517  }
41518 
41519  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferOut, pFramesInThisIteration, frameCountThisIteration);
41520  if (result != MA_SUCCESS) {
41521  break;
41522  }
41523  }
41524 
41525  /* If we are doing a post format conversion we need to do that now. */
41526  if (pConverter->hasPostFormatConversion) {
41527  if (pFramesOutThisIteration != NULL) {
41528  ma_convert_pcm_frames_format(pFramesOutThisIteration, pConverter->config.formatOut, pTempBufferOut, pConverter->channelConverter.format, frameCountThisIteration, pConverter->channelConverter.channelsOut, pConverter->config.ditherMode);
41529  }
41530  }
41531 
41532  framesProcessed += frameCountThisIteration;
41533  }
41534  }
41535 
41536  if (pFrameCountIn != NULL) {
41537  *pFrameCountIn = frameCount;
41538  }
41539  if (pFrameCountOut != NULL) {
41540  *pFrameCountOut = frameCount;
41541  }
41542 
41543  return MA_SUCCESS;
41544 }
41545 
41546 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)
41547 {
41548  ma_result result;
41549  ma_uint64 frameCountIn;
41550  ma_uint64 frameCountOut;
41551  ma_uint64 framesProcessedIn;
41552  ma_uint64 framesProcessedOut;
41553  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format. */
41554  ma_uint64 tempBufferInCap;
41555  ma_uint8 pTempBufferMid[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format, channel converter input format. */
41556  ma_uint64 tempBufferMidCap;
41557  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In channel converter output format. */
41558  ma_uint64 tempBufferOutCap;
41559 
41560  MA_ASSERT(pConverter != NULL);
41561  MA_ASSERT(pConverter->resampler.config.format == pConverter->channelConverter.format);
41562  MA_ASSERT(pConverter->resampler.config.channels == pConverter->channelConverter.channelsIn);
41563  MA_ASSERT(pConverter->resampler.config.channels < pConverter->channelConverter.channelsOut);
41564 
41565  frameCountIn = 0;
41566  if (pFrameCountIn != NULL) {
41567  frameCountIn = *pFrameCountIn;
41568  }
41569 
41570  frameCountOut = 0;
41571  if (pFrameCountOut != NULL) {
41572  frameCountOut = *pFrameCountOut;
41573  }
41574 
41575  framesProcessedIn = 0;
41576  framesProcessedOut = 0;
41577 
41578  tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
41579  tempBufferMidCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
41580  tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
41581 
41582  while (framesProcessedOut < frameCountOut) {
41583  ma_uint64 frameCountInThisIteration;
41584  ma_uint64 frameCountOutThisIteration;
41585  const void* pRunningFramesIn = NULL;
41586  void* pRunningFramesOut = NULL;
41587  const void* pResampleBufferIn;
41588  void* pChannelsBufferOut;
41589 
41590  if (pFramesIn != NULL) {
41591  pRunningFramesIn = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
41592  }
41593  if (pFramesOut != NULL) {
41594  pRunningFramesOut = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41595  }
41596 
41597  /* Run input data through the resampler and output it to the temporary buffer. */
41598  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
41599 
41600  if (pConverter->hasPreFormatConversion) {
41601  if (frameCountInThisIteration > tempBufferInCap) {
41602  frameCountInThisIteration = tempBufferInCap;
41603  }
41604  }
41605 
41606  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
41607  if (frameCountOutThisIteration > tempBufferMidCap) {
41608  frameCountOutThisIteration = tempBufferMidCap;
41609  }
41610 
41611  /* We can't read more frames than can fit in the output buffer. */
41612  if (pConverter->hasPostFormatConversion) {
41613  if (frameCountOutThisIteration > tempBufferOutCap) {
41614  frameCountOutThisIteration = tempBufferOutCap;
41615  }
41616  }
41617 
41618  /* 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. */
41619  {
41620  ma_uint64 requiredInputFrameCount = ma_resampler_get_required_input_frame_count(&pConverter->resampler, frameCountOutThisIteration);
41621  if (frameCountInThisIteration > requiredInputFrameCount) {
41622  frameCountInThisIteration = requiredInputFrameCount;
41623  }
41624  }
41625 
41626  if (pConverter->hasPreFormatConversion) {
41627  if (pFramesIn != NULL) {
41628  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->resampler.config.format, pRunningFramesIn, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
41629  pResampleBufferIn = pTempBufferIn;
41630  } else {
41631  pResampleBufferIn = NULL;
41632  }
41633  } else {
41634  pResampleBufferIn = pRunningFramesIn;
41635  }
41636 
41637  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pResampleBufferIn, &frameCountInThisIteration, pTempBufferMid, &frameCountOutThisIteration);
41638  if (result != MA_SUCCESS) {
41639  return result;
41640  }
41641 
41642 
41643  /*
41644  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
41645  this part if we have an output buffer.
41646  */
41647  if (pFramesOut != NULL) {
41648  if (pConverter->hasPostFormatConversion) {
41649  pChannelsBufferOut = pTempBufferOut;
41650  } else {
41651  pChannelsBufferOut = pRunningFramesOut;
41652  }
41653 
41654  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pChannelsBufferOut, pTempBufferMid, frameCountOutThisIteration);
41655  if (result != MA_SUCCESS) {
41656  return result;
41657  }
41658 
41659  /* Finally we do post format conversion. */
41660  if (pConverter->hasPostFormatConversion) {
41661  ma_convert_pcm_frames_format(pRunningFramesOut, pConverter->config.formatOut, pChannelsBufferOut, pConverter->channelConverter.format, frameCountOutThisIteration, pConverter->channelConverter.channelsOut, pConverter->config.ditherMode);
41662  }
41663  }
41664 
41665 
41666  framesProcessedIn += frameCountInThisIteration;
41667  framesProcessedOut += frameCountOutThisIteration;
41668 
41669  MA_ASSERT(framesProcessedIn <= frameCountIn);
41670  MA_ASSERT(framesProcessedOut <= frameCountOut);
41671 
41672  if (frameCountOutThisIteration == 0) {
41673  break; /* Consumed all of our input data. */
41674  }
41675  }
41676 
41677  if (pFrameCountIn != NULL) {
41678  *pFrameCountIn = framesProcessedIn;
41679  }
41680  if (pFrameCountOut != NULL) {
41681  *pFrameCountOut = framesProcessedOut;
41682  }
41683 
41684  return MA_SUCCESS;
41685 }
41686 
41687 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)
41688 {
41689  ma_result result;
41690  ma_uint64 frameCountIn;
41691  ma_uint64 frameCountOut;
41692  ma_uint64 framesProcessedIn;
41693  ma_uint64 framesProcessedOut;
41694  ma_uint8 pTempBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format. */
41695  ma_uint64 tempBufferInCap;
41696  ma_uint8 pTempBufferMid[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In resampler format, channel converter input format. */
41697  ma_uint64 tempBufferMidCap;
41698  ma_uint8 pTempBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In channel converter output format. */
41699  ma_uint64 tempBufferOutCap;
41700 
41701  MA_ASSERT(pConverter != NULL);
41702  MA_ASSERT(pConverter->resampler.config.format == pConverter->channelConverter.format);
41703  MA_ASSERT(pConverter->resampler.config.channels == pConverter->channelConverter.channelsOut);
41704  MA_ASSERT(pConverter->resampler.config.channels < pConverter->channelConverter.channelsIn);
41705 
41706  frameCountIn = 0;
41707  if (pFrameCountIn != NULL) {
41708  frameCountIn = *pFrameCountIn;
41709  }
41710 
41711  frameCountOut = 0;
41712  if (pFrameCountOut != NULL) {
41713  frameCountOut = *pFrameCountOut;
41714  }
41715 
41716  framesProcessedIn = 0;
41717  framesProcessedOut = 0;
41718 
41719  tempBufferInCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsIn);
41720  tempBufferMidCap = sizeof(pTempBufferIn) / ma_get_bytes_per_frame(pConverter->channelConverter.format, pConverter->channelConverter.channelsOut);
41721  tempBufferOutCap = sizeof(pTempBufferOut) / ma_get_bytes_per_frame(pConverter->resampler.config.format, pConverter->resampler.config.channels);
41722 
41723  while (framesProcessedOut < frameCountOut) {
41724  ma_uint64 frameCountInThisIteration;
41725  ma_uint64 frameCountOutThisIteration;
41726  const void* pRunningFramesIn = NULL;
41727  void* pRunningFramesOut = NULL;
41728  const void* pChannelsBufferIn;
41729  void* pResampleBufferOut;
41730 
41731  if (pFramesIn != NULL) {
41732  pRunningFramesIn = ma_offset_ptr(pFramesIn, framesProcessedIn * ma_get_bytes_per_frame(pConverter->config.formatIn, pConverter->config.channelsIn));
41733  }
41734  if (pFramesOut != NULL) {
41735  pRunningFramesOut = ma_offset_ptr(pFramesOut, framesProcessedOut * ma_get_bytes_per_frame(pConverter->config.formatOut, pConverter->config.channelsOut));
41736  }
41737 
41738  /* Run input data through the channel converter and output it to the temporary buffer. */
41739  frameCountInThisIteration = (frameCountIn - framesProcessedIn);
41740 
41741  if (pConverter->hasPreFormatConversion) {
41742  if (frameCountInThisIteration > tempBufferInCap) {
41743  frameCountInThisIteration = tempBufferInCap;
41744  }
41745 
41746  if (pRunningFramesIn != NULL) {
41747  ma_convert_pcm_frames_format(pTempBufferIn, pConverter->channelConverter.format, pRunningFramesIn, pConverter->config.formatIn, frameCountInThisIteration, pConverter->config.channelsIn, pConverter->config.ditherMode);
41748  pChannelsBufferIn = pTempBufferIn;
41749  } else {
41750  pChannelsBufferIn = NULL;
41751  }
41752  } else {
41753  pChannelsBufferIn = pRunningFramesIn;
41754  }
41755 
41756  /*
41757  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
41758  in this case which means we should always have capacity, but I'm leaving it here just for safety for future maintenance.
41759  */
41760  if (frameCountInThisIteration > tempBufferMidCap) {
41761  frameCountInThisIteration = tempBufferMidCap;
41762  }
41763 
41764  /*
41765  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
41766  input samples and will end up glitching.
41767  */
41768  frameCountOutThisIteration = (frameCountOut - framesProcessedOut);
41769  if (frameCountOutThisIteration > tempBufferMidCap) {
41770  frameCountOutThisIteration = tempBufferMidCap;
41771  }
41772 
41773  if (pConverter->hasPostFormatConversion) {
41774  ma_uint64 requiredInputFrameCount;
41775 
41776  if (frameCountOutThisIteration > tempBufferOutCap) {
41777  frameCountOutThisIteration = tempBufferOutCap;
41778  }
41779 
41780  requiredInputFrameCount = ma_resampler_get_required_input_frame_count(&pConverter->resampler, frameCountOutThisIteration);
41781  if (frameCountInThisIteration > requiredInputFrameCount) {
41782  frameCountInThisIteration = requiredInputFrameCount;
41783  }
41784  }
41785 
41786  result = ma_channel_converter_process_pcm_frames(&pConverter->channelConverter, pTempBufferMid, pChannelsBufferIn, frameCountInThisIteration);
41787  if (result != MA_SUCCESS) {
41788  return result;
41789  }
41790 
41791 
41792  /* At this point we have converted the channels to the output channel count which we now need to resample. */
41793  if (pConverter->hasPostFormatConversion) {
41794  pResampleBufferOut = pTempBufferOut;
41795  } else {
41796  pResampleBufferOut = pRunningFramesOut;
41797  }
41798 
41799  result = ma_resampler_process_pcm_frames(&pConverter->resampler, pTempBufferMid, &frameCountInThisIteration, pResampleBufferOut, &frameCountOutThisIteration);
41800  if (result != MA_SUCCESS) {
41801  return result;
41802  }
41803 
41804  /* Finally we can do the post format conversion. */
41805  if (pConverter->hasPostFormatConversion) {
41806  if (pRunningFramesOut != NULL) {
41807  ma_convert_pcm_frames_format(pRunningFramesOut, pConverter->config.formatOut, pResampleBufferOut, pConverter->resampler.config.format, frameCountOutThisIteration, pConverter->config.channelsOut, pConverter->config.ditherMode);
41808  }
41809  }
41810 
41811  framesProcessedIn += frameCountInThisIteration;
41812  framesProcessedOut += frameCountOutThisIteration;
41813 
41814  MA_ASSERT(framesProcessedIn <= frameCountIn);
41815  MA_ASSERT(framesProcessedOut <= frameCountOut);
41816 
41817  if (frameCountOutThisIteration == 0) {
41818  break; /* Consumed all of our input data. */
41819  }
41820  }
41821 
41822  if (pFrameCountIn != NULL) {
41823  *pFrameCountIn = framesProcessedIn;
41824  }
41825  if (pFrameCountOut != NULL) {
41826  *pFrameCountOut = framesProcessedOut;
41827  }
41828 
41829  return MA_SUCCESS;
41830 }
41831 
41832 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)
41833 {
41834  if (pConverter == NULL) {
41835  return MA_INVALID_ARGS;
41836  }
41837 
41838  if (pConverter->isPassthrough) {
41839  return ma_data_converter_process_pcm_frames__passthrough(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41840  }
41841 
41842  /*
41843  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
41844  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
41845  that it has less work (resampling is the most expensive part of format conversion).
41846  */
41847  if (pConverter->config.channelsIn < pConverter->config.channelsOut) {
41848  /* Do resampling first, if necessary. */
41849  MA_ASSERT(pConverter->hasChannelConverter == MA_TRUE);
41850 
41851  if (pConverter->hasResampler) {
41852  /* Resampling first. */
41853  return ma_data_converter_process_pcm_frames__resampling_first(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41854  } else {
41855  /* Resampling not required. */
41856  return ma_data_converter_process_pcm_frames__channels_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41857  }
41858  } else {
41859  /* Do channel conversion first, if necessary. */
41860  if (pConverter->hasChannelConverter) {
41861  if (pConverter->hasResampler) {
41862  /* Channel routing first. */
41863  return ma_data_converter_process_pcm_frames__channels_first(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41864  } else {
41865  /* Resampling not required. */
41866  return ma_data_converter_process_pcm_frames__channels_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41867  }
41868  } else {
41869  /* Channel routing not required. */
41870  if (pConverter->hasResampler) {
41871  /* Resampling only. */
41872  return ma_data_converter_process_pcm_frames__resample_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41873  } else {
41874  /* No channel routing nor resampling required. Just format conversion. */
41875  return ma_data_converter_process_pcm_frames__format_only(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
41876  }
41877  }
41878  }
41879 }
41880 
41881 MA_API ma_result ma_data_converter_set_rate(ma_data_converter* pConverter, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
41882 {
41883  if (pConverter == NULL) {
41884  return MA_INVALID_ARGS;
41885  }
41886 
41887  if (pConverter->hasResampler == MA_FALSE) {
41888  return MA_INVALID_OPERATION; /* Dynamic resampling not enabled. */
41889  }
41890 
41891  return ma_resampler_set_rate(&pConverter->resampler, sampleRateIn, sampleRateOut);
41892 }
41893 
41895 {
41896  if (pConverter == NULL) {
41897  return MA_INVALID_ARGS;
41898  }
41899 
41900  if (pConverter->hasResampler == MA_FALSE) {
41901  return MA_INVALID_OPERATION; /* Dynamic resampling not enabled. */
41902  }
41903 
41904  return ma_resampler_set_rate_ratio(&pConverter->resampler, ratioInOut);
41905 }
41906 
41908 {
41909  if (pConverter == NULL) {
41910  return 0;
41911  }
41912 
41913  if (pConverter->hasResampler) {
41914  return ma_resampler_get_required_input_frame_count(&pConverter->resampler, outputFrameCount);
41915  } else {
41916  return outputFrameCount; /* 1:1 */
41917  }
41918 }
41919 
41921 {
41922  if (pConverter == NULL) {
41923  return 0;
41924  }
41925 
41926  if (pConverter->hasResampler) {
41927  return ma_resampler_get_expected_output_frame_count(&pConverter->resampler, inputFrameCount);
41928  } else {
41929  return inputFrameCount; /* 1:1 */
41930  }
41931 }
41932 
41934 {
41935  if (pConverter == NULL) {
41936  return 0;
41937  }
41938 
41939  if (pConverter->hasResampler) {
41940  return ma_resampler_get_input_latency(&pConverter->resampler);
41941  }
41942 
41943  return 0; /* No latency without a resampler. */
41944 }
41945 
41947 {
41948  if (pConverter == NULL) {
41949  return 0;
41950  }
41951 
41952  if (pConverter->hasResampler) {
41953  return ma_resampler_get_output_latency(&pConverter->resampler);
41954  }
41955 
41956  return 0; /* No latency without a resampler. */
41957 }
41958 
41959 
41960 
41961 /**************************************************************************************************************************************************************
41962 
41963 Channel Maps
41964 
41965 **************************************************************************************************************************************************************/
41967 {
41968  if (channelCount == 0 || channelIndex >= channelCount) {
41969  return MA_CHANNEL_NONE;
41970  }
41971 
41972  /* 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 */
41973  switch (channelCount)
41974  {
41975  case 0: return MA_CHANNEL_NONE;
41976 
41977  case 1:
41978  {
41979  return MA_CHANNEL_MONO;
41980  } break;
41981 
41982  case 2:
41983  {
41984  switch (channelIndex) {
41985  case 0: return MA_CHANNEL_FRONT_LEFT;
41986  case 1: return MA_CHANNEL_FRONT_RIGHT;
41987  }
41988  } break;
41989 
41990  case 3: /* No defined, but best guess. */
41991  {
41992  switch (channelIndex) {
41993  case 0: return MA_CHANNEL_FRONT_LEFT;
41994  case 1: return MA_CHANNEL_FRONT_RIGHT;
41995  case 2: return MA_CHANNEL_FRONT_CENTER;
41996  }
41997  } break;
41998 
41999  case 4:
42000  {
42001  switch (channelIndex) {
42002  #ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
42003  /* Surround. Using the Surround profile has the advantage of the 3rd channel (MA_CHANNEL_FRONT_CENTER) mapping nicely with higher channel counts. */
42004  case 0: return MA_CHANNEL_FRONT_LEFT;
42005  case 1: return MA_CHANNEL_FRONT_RIGHT;
42006  case 2: return MA_CHANNEL_FRONT_CENTER;
42007  case 3: return MA_CHANNEL_BACK_CENTER;
42008  #else
42009  /* Quad. */
42010  case 0: return MA_CHANNEL_FRONT_LEFT;
42011  case 1: return MA_CHANNEL_FRONT_RIGHT;
42012  case 2: return MA_CHANNEL_BACK_LEFT;
42013  case 3: return MA_CHANNEL_BACK_RIGHT;
42014  #endif
42015  }
42016  } break;
42017 
42018  case 5: /* Not defined, but best guess. */
42019  {
42020  switch (channelIndex) {
42021  case 0: return MA_CHANNEL_FRONT_LEFT;
42022  case 1: return MA_CHANNEL_FRONT_RIGHT;
42023  case 2: return MA_CHANNEL_FRONT_CENTER;
42024  case 3: return MA_CHANNEL_BACK_LEFT;
42025  case 4: return MA_CHANNEL_BACK_RIGHT;
42026  }
42027  } break;
42028 
42029  case 6:
42030  {
42031  switch (channelIndex) {
42032  case 0: return MA_CHANNEL_FRONT_LEFT;
42033  case 1: return MA_CHANNEL_FRONT_RIGHT;
42034  case 2: return MA_CHANNEL_FRONT_CENTER;
42035  case 3: return MA_CHANNEL_LFE;
42036  case 4: return MA_CHANNEL_SIDE_LEFT;
42037  case 5: return MA_CHANNEL_SIDE_RIGHT;
42038  }
42039  } break;
42040 
42041  case 7: /* Not defined, but best guess. */
42042  {
42043  switch (channelIndex) {
42044  case 0: return MA_CHANNEL_FRONT_LEFT;
42045  case 1: return MA_CHANNEL_FRONT_RIGHT;
42046  case 2: return MA_CHANNEL_FRONT_CENTER;
42047  case 3: return MA_CHANNEL_LFE;
42048  case 4: return MA_CHANNEL_BACK_CENTER;
42049  case 5: return MA_CHANNEL_SIDE_LEFT;
42050  case 6: return MA_CHANNEL_SIDE_RIGHT;
42051  }
42052  } break;
42053 
42054  case 8:
42055  default:
42056  {
42057  switch (channelIndex) {
42058  case 0: return MA_CHANNEL_FRONT_LEFT;
42059  case 1: return MA_CHANNEL_FRONT_RIGHT;
42060  case 2: return MA_CHANNEL_FRONT_CENTER;
42061  case 3: return MA_CHANNEL_LFE;
42062  case 4: return MA_CHANNEL_BACK_LEFT;
42063  case 5: return MA_CHANNEL_BACK_RIGHT;
42064  case 6: return MA_CHANNEL_SIDE_LEFT;
42065  case 7: return MA_CHANNEL_SIDE_RIGHT;
42066  }
42067  } break;
42068  }
42069 
42070  if (channelCount > 8) {
42071  if (channelIndex < 32) { /* We have 32 AUX channels. */
42072  return (ma_channel)(MA_CHANNEL_AUX_0 + (channelIndex - 8));
42073  }
42074  }
42075 
42076  /* Getting here means we don't know how to map the channel position so just return MA_CHANNEL_NONE. */
42077  return MA_CHANNEL_NONE;
42078 }
42079 
42080 MA_API ma_channel ma_channel_map_get_channel(const ma_channel* pChannelMap, ma_uint32 channelCount, ma_uint32 channelIndex)
42081 {
42082  if (pChannelMap == NULL) {
42083  return ma_channel_map_get_default_channel(channelCount, channelIndex);
42084  } else {
42085  if (channelIndex >= channelCount) {
42086  return MA_CHANNEL_NONE;
42087  }
42088 
42089  return pChannelMap[channelIndex];
42090  }
42091 }
42092 
42093 
42094 MA_API void ma_channel_map_init_blank(ma_uint32 channels, ma_channel* pChannelMap)
42095 {
42096  if (pChannelMap == NULL) {
42097  return;
42098  }
42099 
42100  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channels);
42101 }
42102 
42103 static void ma_get_standard_channel_map_microsoft(ma_uint32 channels, ma_channel* pChannelMap)
42104 {
42105  /* Based off the speaker configurations mentioned here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ksmedia/ns-ksmedia-ksaudio_channel_config */
42106  switch (channels)
42107  {
42108  case 1:
42109  {
42110  pChannelMap[0] = MA_CHANNEL_MONO;
42111  } break;
42112 
42113  case 2:
42114  {
42115  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42116  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42117  } break;
42118 
42119  case 3: /* Not defined, but best guess. */
42120  {
42121  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42122  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42123  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42124  } break;
42125 
42126  case 4:
42127  {
42128 #ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
42129  /* Surround. Using the Surround profile has the advantage of the 3rd channel (MA_CHANNEL_FRONT_CENTER) mapping nicely with higher channel counts. */
42130  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42131  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42132  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42133  pChannelMap[3] = MA_CHANNEL_BACK_CENTER;
42134 #else
42135  /* Quad. */
42136  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42137  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42138  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42139  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42140 #endif
42141  } break;
42142 
42143  case 5: /* Not defined, but best guess. */
42144  {
42145  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42146  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42147  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42148  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
42149  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
42150  } break;
42151 
42152  case 6:
42153  {
42154  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42155  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42156  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42157  pChannelMap[3] = MA_CHANNEL_LFE;
42158  pChannelMap[4] = MA_CHANNEL_SIDE_LEFT;
42159  pChannelMap[5] = MA_CHANNEL_SIDE_RIGHT;
42160  } break;
42161 
42162  case 7: /* Not defined, but best guess. */
42163  {
42164  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42165  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42166  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42167  pChannelMap[3] = MA_CHANNEL_LFE;
42168  pChannelMap[4] = MA_CHANNEL_BACK_CENTER;
42169  pChannelMap[5] = MA_CHANNEL_SIDE_LEFT;
42170  pChannelMap[6] = MA_CHANNEL_SIDE_RIGHT;
42171  } break;
42172 
42173  case 8:
42174  default:
42175  {
42176  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42177  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42178  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42179  pChannelMap[3] = MA_CHANNEL_LFE;
42180  pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
42181  pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
42182  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
42183  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
42184  } break;
42185  }
42186 
42187  /* Remainder. */
42188  if (channels > 8) {
42189  ma_uint32 iChannel;
42190  for (iChannel = 8; iChannel < channels; ++iChannel) {
42191  if (iChannel < MA_MAX_CHANNELS) {
42192  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
42193  } else {
42194  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42195  }
42196  }
42197  }
42198 }
42199 
42200 static void ma_get_standard_channel_map_alsa(ma_uint32 channels, ma_channel* pChannelMap)
42201 {
42202  switch (channels)
42203  {
42204  case 1:
42205  {
42206  pChannelMap[0] = MA_CHANNEL_MONO;
42207  } break;
42208 
42209  case 2:
42210  {
42211  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42212  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42213  } break;
42214 
42215  case 3:
42216  {
42217  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42218  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42219  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42220  } break;
42221 
42222  case 4:
42223  {
42224  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42225  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42226  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42227  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42228  } break;
42229 
42230  case 5:
42231  {
42232  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42233  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42234  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42235  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42236  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42237  } break;
42238 
42239  case 6:
42240  {
42241  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42242  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42243  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42244  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42245  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42246  pChannelMap[5] = MA_CHANNEL_LFE;
42247  } break;
42248 
42249  case 7:
42250  {
42251  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42252  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42253  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42254  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42255  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42256  pChannelMap[5] = MA_CHANNEL_LFE;
42257  pChannelMap[6] = MA_CHANNEL_BACK_CENTER;
42258  } break;
42259 
42260  case 8:
42261  default:
42262  {
42263  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42264  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42265  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42266  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42267  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42268  pChannelMap[5] = MA_CHANNEL_LFE;
42269  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
42270  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
42271  } break;
42272  }
42273 
42274  /* Remainder. */
42275  if (channels > 8) {
42276  ma_uint32 iChannel;
42277  for (iChannel = 8; iChannel < channels; ++iChannel) {
42278  if (iChannel < MA_MAX_CHANNELS) {
42279  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
42280  } else {
42281  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42282  }
42283  }
42284  }
42285 }
42286 
42287 static void ma_get_standard_channel_map_rfc3551(ma_uint32 channels, ma_channel* pChannelMap)
42288 {
42289  switch (channels)
42290  {
42291  case 1:
42292  {
42293  pChannelMap[0] = MA_CHANNEL_MONO;
42294  } break;
42295 
42296  case 2:
42297  {
42298  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42299  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42300  } break;
42301 
42302  case 3:
42303  {
42304  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42305  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42306  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42307  } break;
42308 
42309  case 4:
42310  {
42311  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42312  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
42313  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
42314  pChannelMap[3] = MA_CHANNEL_BACK_CENTER;
42315  } break;
42316 
42317  case 5:
42318  {
42319  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42320  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42321  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42322  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
42323  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
42324  } break;
42325 
42326  case 6:
42327  {
42328  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42329  pChannelMap[1] = MA_CHANNEL_SIDE_LEFT;
42330  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42331  pChannelMap[3] = MA_CHANNEL_FRONT_RIGHT;
42332  pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
42333  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
42334  } break;
42335  }
42336 
42337  /* Remainder. */
42338  if (channels > 8) {
42339  ma_uint32 iChannel;
42340  for (iChannel = 6; iChannel < channels; ++iChannel) {
42341  if (iChannel < MA_MAX_CHANNELS) {
42342  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-6));
42343  } else {
42344  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42345  }
42346  }
42347  }
42348 }
42349 
42350 static void ma_get_standard_channel_map_flac(ma_uint32 channels, ma_channel* pChannelMap)
42351 {
42352  switch (channels)
42353  {
42354  case 1:
42355  {
42356  pChannelMap[0] = MA_CHANNEL_MONO;
42357  } break;
42358 
42359  case 2:
42360  {
42361  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42362  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42363  } break;
42364 
42365  case 3:
42366  {
42367  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42368  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42369  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42370  } break;
42371 
42372  case 4:
42373  {
42374  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42375  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42376  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42377  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42378  } break;
42379 
42380  case 5:
42381  {
42382  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42383  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42384  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42385  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
42386  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
42387  } break;
42388 
42389  case 6:
42390  {
42391  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42392  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42393  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42394  pChannelMap[3] = MA_CHANNEL_LFE;
42395  pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
42396  pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
42397  } break;
42398 
42399  case 7:
42400  {
42401  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42402  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42403  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42404  pChannelMap[3] = MA_CHANNEL_LFE;
42405  pChannelMap[4] = MA_CHANNEL_BACK_CENTER;
42406  pChannelMap[5] = MA_CHANNEL_SIDE_LEFT;
42407  pChannelMap[6] = MA_CHANNEL_SIDE_RIGHT;
42408  } break;
42409 
42410  case 8:
42411  default:
42412  {
42413  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42414  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42415  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42416  pChannelMap[3] = MA_CHANNEL_LFE;
42417  pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
42418  pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
42419  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
42420  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
42421  } break;
42422  }
42423 
42424  /* Remainder. */
42425  if (channels > 8) {
42426  ma_uint32 iChannel;
42427  for (iChannel = 8; iChannel < channels; ++iChannel) {
42428  if (iChannel < MA_MAX_CHANNELS) {
42429  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
42430  } else {
42431  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42432  }
42433  }
42434  }
42435 }
42436 
42437 static void ma_get_standard_channel_map_vorbis(ma_uint32 channels, ma_channel* pChannelMap)
42438 {
42439  /* 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?! */
42440  switch (channels)
42441  {
42442  case 1:
42443  {
42444  pChannelMap[0] = MA_CHANNEL_MONO;
42445  } break;
42446 
42447  case 2:
42448  {
42449  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42450  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42451  } break;
42452 
42453  case 3:
42454  {
42455  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42456  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
42457  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
42458  } break;
42459 
42460  case 4:
42461  {
42462  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42463  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42464  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42465  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42466  } break;
42467 
42468  case 5:
42469  {
42470  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42471  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
42472  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
42473  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
42474  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
42475  } break;
42476 
42477  case 6:
42478  {
42479  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42480  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
42481  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
42482  pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
42483  pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
42484  pChannelMap[5] = MA_CHANNEL_LFE;
42485  } break;
42486 
42487  case 7:
42488  {
42489  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42490  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
42491  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
42492  pChannelMap[3] = MA_CHANNEL_SIDE_LEFT;
42493  pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
42494  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
42495  pChannelMap[6] = MA_CHANNEL_LFE;
42496  } break;
42497 
42498  case 8:
42499  default:
42500  {
42501  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42502  pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
42503  pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
42504  pChannelMap[3] = MA_CHANNEL_SIDE_LEFT;
42505  pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
42506  pChannelMap[5] = MA_CHANNEL_BACK_LEFT;
42507  pChannelMap[6] = MA_CHANNEL_BACK_RIGHT;
42508  pChannelMap[7] = MA_CHANNEL_LFE;
42509  } break;
42510  }
42511 
42512  /* Remainder. */
42513  if (channels > 8) {
42514  ma_uint32 iChannel;
42515  for (iChannel = 8; iChannel < channels; ++iChannel) {
42516  if (iChannel < MA_MAX_CHANNELS) {
42517  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
42518  } else {
42519  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42520  }
42521  }
42522  }
42523 }
42524 
42525 static void ma_get_standard_channel_map_sound4(ma_uint32 channels, ma_channel* pChannelMap)
42526 {
42527  switch (channels)
42528  {
42529  case 1:
42530  {
42531  pChannelMap[0] = MA_CHANNEL_MONO;
42532  } break;
42533 
42534  case 2:
42535  {
42536  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42537  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42538  } break;
42539 
42540  case 3:
42541  {
42542  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42543  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42544  pChannelMap[2] = MA_CHANNEL_BACK_CENTER;
42545  } break;
42546 
42547  case 4:
42548  {
42549  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42550  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42551  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42552  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42553  } break;
42554 
42555  case 5:
42556  {
42557  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42558  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42559  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42560  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42561  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42562  } break;
42563 
42564  case 6:
42565  {
42566  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42567  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42568  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42569  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42570  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42571  pChannelMap[5] = MA_CHANNEL_LFE;
42572  } break;
42573 
42574  case 7:
42575  {
42576  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42577  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42578  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42579  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42580  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42581  pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
42582  pChannelMap[6] = MA_CHANNEL_LFE;
42583  } break;
42584 
42585  case 8:
42586  default:
42587  {
42588  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42589  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42590  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42591  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42592  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42593  pChannelMap[5] = MA_CHANNEL_LFE;
42594  pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
42595  pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
42596  } break;
42597  }
42598 
42599  /* Remainder. */
42600  if (channels > 8) {
42601  ma_uint32 iChannel;
42602  for (iChannel = 8; iChannel < MA_MAX_CHANNELS; ++iChannel) {
42603  if (iChannel < MA_MAX_CHANNELS) {
42604  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-8));
42605  } else {
42606  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42607  }
42608  }
42609  }
42610 }
42611 
42612 static void ma_get_standard_channel_map_sndio(ma_uint32 channels, ma_channel* pChannelMap)
42613 {
42614  switch (channels)
42615  {
42616  case 1:
42617  {
42618  pChannelMap[0] = MA_CHANNEL_MONO;
42619  } break;
42620 
42621  case 2:
42622  {
42623  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42624  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42625  } break;
42626 
42627  case 3:
42628  {
42629  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42630  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42631  pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
42632  } break;
42633 
42634  case 4:
42635  {
42636  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42637  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42638  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42639  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42640  } break;
42641 
42642  case 5:
42643  {
42644  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42645  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42646  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42647  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42648  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42649  } break;
42650 
42651  case 6:
42652  default:
42653  {
42654  pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
42655  pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
42656  pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
42657  pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
42658  pChannelMap[4] = MA_CHANNEL_FRONT_CENTER;
42659  pChannelMap[5] = MA_CHANNEL_LFE;
42660  } break;
42661  }
42662 
42663  /* Remainder. */
42664  if (channels > 6) {
42665  ma_uint32 iChannel;
42666  for (iChannel = 6; iChannel < channels && iChannel < MA_MAX_CHANNELS; ++iChannel) {
42667  if (iChannel < MA_MAX_CHANNELS) {
42668  pChannelMap[iChannel] = (ma_channel)(MA_CHANNEL_AUX_0 + (iChannel-6));
42669  } else {
42670  pChannelMap[iChannel] = MA_CHANNEL_NONE;
42671  }
42672  }
42673  }
42674 }
42675 
42676 MA_API void ma_get_standard_channel_map(ma_standard_channel_map standardChannelMap, ma_uint32 channels, ma_channel* pChannelMap)
42677 {
42678  switch (standardChannelMap)
42679  {
42681  {
42682  ma_get_standard_channel_map_alsa(channels, pChannelMap);
42683  } break;
42684 
42686  {
42687  ma_get_standard_channel_map_rfc3551(channels, pChannelMap);
42688  } break;
42689 
42691  {
42692  ma_get_standard_channel_map_flac(channels, pChannelMap);
42693  } break;
42694 
42696  {
42697  ma_get_standard_channel_map_vorbis(channels, pChannelMap);
42698  } break;
42699 
42701  {
42702  ma_get_standard_channel_map_sound4(channels, pChannelMap);
42703  } break;
42704 
42706  {
42707  ma_get_standard_channel_map_sndio(channels, pChannelMap);
42708  } break;
42709 
42710  case ma_standard_channel_map_microsoft: /* Also default. */
42711  /*case ma_standard_channel_map_default;*/
42712  default:
42713  {
42714  ma_get_standard_channel_map_microsoft(channels, pChannelMap);
42715  } break;
42716  }
42717 }
42718 
42719 MA_API void ma_channel_map_copy(ma_channel* pOut, const ma_channel* pIn, ma_uint32 channels)
42720 {
42721  if (pOut != NULL && pIn != NULL && channels > 0) {
42722  MA_COPY_MEMORY(pOut, pIn, sizeof(*pOut) * channels);
42723  }
42724 }
42725 
42726 MA_API void ma_channel_map_copy_or_default(ma_channel* pOut, const ma_channel* pIn, ma_uint32 channels)
42727 {
42728  if (pOut == NULL || channels == 0) {
42729  return;
42730  }
42731 
42732  if (pIn != NULL) {
42733  ma_channel_map_copy(pOut, pIn, channels);
42734  } else {
42736  }
42737 }
42738 
42739 MA_API ma_bool32 ma_channel_map_valid(ma_uint32 channels, const ma_channel* pChannelMap)
42740 {
42741  if (pChannelMap == NULL) {
42742  return MA_FALSE;
42743  }
42744 
42745  /* A channel count of 0 is invalid. */
42746  if (channels == 0) {
42747  return MA_FALSE;
42748  }
42749 
42750  /* It does not make sense to have a mono channel when there is more than 1 channel. */
42751  if (channels > 1) {
42752  ma_uint32 iChannel;
42753  for (iChannel = 0; iChannel < channels; ++iChannel) {
42754  if (pChannelMap[iChannel] == MA_CHANNEL_MONO) {
42755  return MA_FALSE;
42756  }
42757  }
42758  }
42759 
42760  return MA_TRUE;
42761 }
42762 
42763 MA_API ma_bool32 ma_channel_map_equal(ma_uint32 channels, const ma_channel* pChannelMapA, const ma_channel* pChannelMapB)
42764 {
42765  ma_uint32 iChannel;
42766 
42767  if (pChannelMapA == pChannelMapB) {
42768  return MA_TRUE;
42769  }
42770 
42771  for (iChannel = 0; iChannel < channels; ++iChannel) {
42772  if (ma_channel_map_get_channel(pChannelMapA, channels, iChannel) != ma_channel_map_get_channel(pChannelMapB, channels, iChannel)) {
42773  return MA_FALSE;
42774  }
42775  }
42776 
42777  return MA_TRUE;
42778 }
42779 
42780 MA_API ma_bool32 ma_channel_map_blank(ma_uint32 channels, const ma_channel* pChannelMap)
42781 {
42782  ma_uint32 iChannel;
42783 
42784  /* A null channel map is equivalent to the default channel map. */
42785  if (pChannelMap == NULL) {
42786  return MA_FALSE;
42787  }
42788 
42789  for (iChannel = 0; iChannel < channels; ++iChannel) {
42790  if (pChannelMap[iChannel] != MA_CHANNEL_NONE) {
42791  return MA_FALSE;
42792  }
42793  }
42794 
42795  return MA_TRUE;
42796 }
42797 
42798 MA_API ma_bool32 ma_channel_map_contains_channel_position(ma_uint32 channels, const ma_channel* pChannelMap, ma_channel channelPosition)
42799 {
42800  ma_uint32 iChannel;
42801 
42802  for (iChannel = 0; iChannel < channels; ++iChannel) {
42803  if (ma_channel_map_get_channel(pChannelMap, channels, iChannel) == channelPosition) {
42804  return MA_TRUE;
42805  }
42806  }
42807 
42808  return MA_FALSE;
42809 }
42810 
42811 
42812 
42813 /**************************************************************************************************************************************************************
42814 
42815 Conversion Helpers
42816 
42817 **************************************************************************************************************************************************************/
42818 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)
42819 {
42821 
42822  config = ma_data_converter_config_init(formatIn, formatOut, channelsIn, channelsOut, sampleRateIn, sampleRateOut);
42825  config.resampling.linear.lpfOrder = ma_min(MA_DEFAULT_RESAMPLER_LPF_ORDER, MA_MAX_FILTER_ORDER);
42826 
42827  return ma_convert_frames_ex(pOut, frameCountOut, pIn, frameCountIn, &config);
42828 }
42829 
42830 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)
42831 {
42832  ma_result result;
42833  ma_data_converter converter;
42834 
42835  if (frameCountIn == 0 || pConfig == NULL) {
42836  return 0;
42837  }
42838 
42839  result = ma_data_converter_init(pConfig, &converter);
42840  if (result != MA_SUCCESS) {
42841  return 0; /* Failed to initialize the data converter. */
42842  }
42843 
42844  if (pOut == NULL) {
42845  frameCountOut = ma_data_converter_get_expected_output_frame_count(&converter, frameCountIn);
42846  } else {
42847  result = ma_data_converter_process_pcm_frames(&converter, pIn, &frameCountIn, pOut, &frameCountOut);
42848  if (result != MA_SUCCESS) {
42849  frameCountOut = 0;
42850  }
42851  }
42852 
42853  ma_data_converter_uninit(&converter);
42854  return frameCountOut;
42855 }
42856 
42857 
42858 /**************************************************************************************************************************************************************
42859 
42860 Ring Buffer
42861 
42862 **************************************************************************************************************************************************************/
42864 {
42865  return encodedOffset & 0x7FFFFFFF;
42866 }
42867 
42869 {
42870  return encodedOffset & 0x80000000;
42871 }
42872 
42873 static MA_INLINE void* ma_rb__get_read_ptr(ma_rb* pRB)
42874 {
42875  MA_ASSERT(pRB != NULL);
42877 }
42878 
42879 static MA_INLINE void* ma_rb__get_write_ptr(ma_rb* pRB)
42880 {
42881  MA_ASSERT(pRB != NULL);
42883 }
42884 
42885 static MA_INLINE ma_uint32 ma_rb__construct_offset(ma_uint32 offsetInBytes, ma_uint32 offsetLoopFlag)
42886 {
42887  return offsetLoopFlag | offsetInBytes;
42888 }
42889 
42890 static MA_INLINE void ma_rb__deconstruct_offset(ma_uint32 encodedOffset, ma_uint32* pOffsetInBytes, ma_uint32* pOffsetLoopFlag)
42891 {
42892  MA_ASSERT(pOffsetInBytes != NULL);
42893  MA_ASSERT(pOffsetLoopFlag != NULL);
42894 
42895  *pOffsetInBytes = ma_rb__extract_offset_in_bytes(encodedOffset);
42896  *pOffsetLoopFlag = ma_rb__extract_offset_loop_flag(encodedOffset);
42897 }
42898 
42899 
42900 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)
42901 {
42902  ma_result result;
42903  const ma_uint32 maxSubBufferSize = 0x7FFFFFFF - (MA_SIMD_ALIGNMENT-1);
42904 
42905  if (pRB == NULL) {
42906  return MA_INVALID_ARGS;
42907  }
42908 
42909  if (subbufferSizeInBytes == 0 || subbufferCount == 0) {
42910  return MA_INVALID_ARGS;
42911  }
42912 
42913  if (subbufferSizeInBytes > maxSubBufferSize) {
42914  return MA_INVALID_ARGS; /* Maximum buffer size is ~2GB. The most significant bit is a flag for use internally. */
42915  }
42916 
42917 
42918  MA_ZERO_OBJECT(pRB);
42919 
42920  result = ma_allocation_callbacks_init_copy(&pRB->allocationCallbacks, pAllocationCallbacks);
42921  if (result != MA_SUCCESS) {
42922  return result;
42923  }
42924 
42925  pRB->subbufferSizeInBytes = (ma_uint32)subbufferSizeInBytes;
42926  pRB->subbufferCount = (ma_uint32)subbufferCount;
42927 
42928  if (pOptionalPreallocatedBuffer != NULL) {
42929  pRB->subbufferStrideInBytes = (ma_uint32)subbufferStrideInBytes;
42930  pRB->pBuffer = pOptionalPreallocatedBuffer;
42931  } else {
42932  size_t bufferSizeInBytes;
42933 
42934  /*
42935  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
42936  we need to make sure the stride is a multiple of MA_SIMD_ALIGNMENT.
42937  */
42939 
42940  bufferSizeInBytes = (size_t)pRB->subbufferCount*pRB->subbufferStrideInBytes;
42941  pRB->pBuffer = ma_aligned_malloc(bufferSizeInBytes, MA_SIMD_ALIGNMENT, &pRB->allocationCallbacks);
42942  if (pRB->pBuffer == NULL) {
42943  return MA_OUT_OF_MEMORY;
42944  }
42945 
42946  MA_ZERO_MEMORY(pRB->pBuffer, bufferSizeInBytes);
42947  pRB->ownsBuffer = MA_TRUE;
42948  }
42949 
42950  return MA_SUCCESS;
42951 }
42952 
42953 MA_API ma_result ma_rb_init(size_t bufferSizeInBytes, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_rb* pRB)
42954 {
42955  return ma_rb_init_ex(bufferSizeInBytes, 1, 0, pOptionalPreallocatedBuffer, pAllocationCallbacks, pRB);
42956 }
42957 
42958 MA_API void ma_rb_uninit(ma_rb* pRB)
42959 {
42960  if (pRB == NULL) {
42961  return;
42962  }
42963 
42964  if (pRB->ownsBuffer) {
42966  }
42967 }
42968 
42969 MA_API void ma_rb_reset(ma_rb* pRB)
42970 {
42971  if (pRB == NULL) {
42972  return;
42973  }
42974 
42977 }
42978 
42979 MA_API ma_result ma_rb_acquire_read(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut)
42980 {
42981  ma_uint32 writeOffset;
42982  ma_uint32 writeOffsetInBytes;
42983  ma_uint32 writeOffsetLoopFlag;
42984  ma_uint32 readOffset;
42985  ma_uint32 readOffsetInBytes;
42986  ma_uint32 readOffsetLoopFlag;
42987  size_t bytesAvailable;
42988  size_t bytesRequested;
42989 
42990  if (pRB == NULL || pSizeInBytes == NULL || ppBufferOut == NULL) {
42991  return MA_INVALID_ARGS;
42992  }
42993 
42994  /* The returned buffer should never move ahead of the write pointer. */
42995  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
42996  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
42997 
42998  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
42999  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
43000 
43001  /*
43002  The number of bytes available depends on whether or not the read and write pointers are on the same loop iteration. If so, we
43003  can only read up to the write pointer. If not, we can only read up to the end of the buffer.
43004  */
43005  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
43006  bytesAvailable = writeOffsetInBytes - readOffsetInBytes;
43007  } else {
43008  bytesAvailable = pRB->subbufferSizeInBytes - readOffsetInBytes;
43009  }
43010 
43011  bytesRequested = *pSizeInBytes;
43012  if (bytesRequested > bytesAvailable) {
43013  bytesRequested = bytesAvailable;
43014  }
43015 
43016  *pSizeInBytes = bytesRequested;
43017  (*ppBufferOut) = ma_rb__get_read_ptr(pRB);
43018 
43019  return MA_SUCCESS;
43020 }
43021 
43022 MA_API ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut)
43023 {
43024  ma_uint32 readOffset;
43025  ma_uint32 readOffsetInBytes;
43026  ma_uint32 readOffsetLoopFlag;
43027  ma_uint32 newReadOffsetInBytes;
43028  ma_uint32 newReadOffsetLoopFlag;
43029 
43030  if (pRB == NULL) {
43031  return MA_INVALID_ARGS;
43032  }
43033 
43034  /* Validate the buffer. */
43035  if (pBufferOut != ma_rb__get_read_ptr(pRB)) {
43036  return MA_INVALID_ARGS;
43037  }
43038 
43039  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
43040  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
43041 
43042  /* Check that sizeInBytes is correct. It should never go beyond the end of the buffer. */
43043  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + sizeInBytes);
43044  if (newReadOffsetInBytes > pRB->subbufferSizeInBytes) {
43045  return MA_INVALID_ARGS; /* <-- sizeInBytes will cause the read offset to overflow. */
43046  }
43047 
43048  /* Move the read pointer back to the start if necessary. */
43049  newReadOffsetLoopFlag = readOffsetLoopFlag;
43050  if (newReadOffsetInBytes == pRB->subbufferSizeInBytes) {
43051  newReadOffsetInBytes = 0;
43052  newReadOffsetLoopFlag ^= 0x80000000;
43053  }
43054 
43055  c89atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetLoopFlag, newReadOffsetInBytes));
43056 
43057  if (ma_rb_pointer_distance(pRB) == 0) {
43058  return MA_AT_END;
43059  } else {
43060  return MA_SUCCESS;
43061  }
43062 }
43063 
43064 MA_API ma_result ma_rb_acquire_write(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut)
43065 {
43066  ma_uint32 readOffset;
43067  ma_uint32 readOffsetInBytes;
43068  ma_uint32 readOffsetLoopFlag;
43069  ma_uint32 writeOffset;
43070  ma_uint32 writeOffsetInBytes;
43071  ma_uint32 writeOffsetLoopFlag;
43072  size_t bytesAvailable;
43073  size_t bytesRequested;
43074 
43075  if (pRB == NULL || pSizeInBytes == NULL || ppBufferOut == NULL) {
43076  return MA_INVALID_ARGS;
43077  }
43078 
43079  /* The returned buffer should never overtake the read buffer. */
43080  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
43081  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
43082 
43083  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
43084  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
43085 
43086  /*
43087  In the case of writing, if the write pointer and the read pointer are on the same loop iteration we can only
43088  write up to the end of the buffer. Otherwise we can only write up to the read pointer. The write pointer should
43089  never overtake the read pointer.
43090  */
43091  if (writeOffsetLoopFlag == readOffsetLoopFlag) {
43092  bytesAvailable = pRB->subbufferSizeInBytes - writeOffsetInBytes;
43093  } else {
43094  bytesAvailable = readOffsetInBytes - writeOffsetInBytes;
43095  }
43096 
43097  bytesRequested = *pSizeInBytes;
43098  if (bytesRequested > bytesAvailable) {
43099  bytesRequested = bytesAvailable;
43100  }
43101 
43102  *pSizeInBytes = bytesRequested;
43103  *ppBufferOut = ma_rb__get_write_ptr(pRB);
43104 
43105  /* Clear the buffer if desired. */
43106  if (pRB->clearOnWriteAcquire) {
43107  MA_ZERO_MEMORY(*ppBufferOut, *pSizeInBytes);
43108  }
43109 
43110  return MA_SUCCESS;
43111 }
43112 
43113 MA_API ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut)
43114 {
43115  ma_uint32 writeOffset;
43116  ma_uint32 writeOffsetInBytes;
43117  ma_uint32 writeOffsetLoopFlag;
43118  ma_uint32 newWriteOffsetInBytes;
43119  ma_uint32 newWriteOffsetLoopFlag;
43120 
43121  if (pRB == NULL) {
43122  return MA_INVALID_ARGS;
43123  }
43124 
43125  /* Validate the buffer. */
43126  if (pBufferOut != ma_rb__get_write_ptr(pRB)) {
43127  return MA_INVALID_ARGS;
43128  }
43129 
43130  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
43131  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
43132 
43133  /* Check that sizeInBytes is correct. It should never go beyond the end of the buffer. */
43134  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + sizeInBytes);
43135  if (newWriteOffsetInBytes > pRB->subbufferSizeInBytes) {
43136  return MA_INVALID_ARGS; /* <-- sizeInBytes will cause the read offset to overflow. */
43137  }
43138 
43139  /* Move the read pointer back to the start if necessary. */
43140  newWriteOffsetLoopFlag = writeOffsetLoopFlag;
43141  if (newWriteOffsetInBytes == pRB->subbufferSizeInBytes) {
43142  newWriteOffsetInBytes = 0;
43143  newWriteOffsetLoopFlag ^= 0x80000000;
43144  }
43145 
43146  c89atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetLoopFlag, newWriteOffsetInBytes));
43147 
43148  if (ma_rb_pointer_distance(pRB) == 0) {
43149  return MA_AT_END;
43150  } else {
43151  return MA_SUCCESS;
43152  }
43153 }
43154 
43155 MA_API ma_result ma_rb_seek_read(ma_rb* pRB, size_t offsetInBytes)
43156 {
43157  ma_uint32 readOffset;
43158  ma_uint32 readOffsetInBytes;
43159  ma_uint32 readOffsetLoopFlag;
43160  ma_uint32 writeOffset;
43161  ma_uint32 writeOffsetInBytes;
43162  ma_uint32 writeOffsetLoopFlag;
43163  ma_uint32 newReadOffsetInBytes;
43164  ma_uint32 newReadOffsetLoopFlag;
43165 
43166  if (pRB == NULL || offsetInBytes > pRB->subbufferSizeInBytes) {
43167  return MA_INVALID_ARGS;
43168  }
43169 
43170  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
43171  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
43172 
43173  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
43174  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
43175 
43176  newReadOffsetLoopFlag = readOffsetLoopFlag;
43177 
43178  /* We cannot go past the write buffer. */
43179  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
43180  if ((readOffsetInBytes + offsetInBytes) > writeOffsetInBytes) {
43181  newReadOffsetInBytes = writeOffsetInBytes;
43182  } else {
43183  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + offsetInBytes);
43184  }
43185  } else {
43186  /* May end up looping. */
43187  if ((readOffsetInBytes + offsetInBytes) >= pRB->subbufferSizeInBytes) {
43188  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + offsetInBytes) - pRB->subbufferSizeInBytes;
43189  newReadOffsetLoopFlag ^= 0x80000000; /* <-- Looped. */
43190  } else {
43191  newReadOffsetInBytes = (ma_uint32)(readOffsetInBytes + offsetInBytes);
43192  }
43193  }
43194 
43195  c89atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetInBytes, newReadOffsetLoopFlag));
43196  return MA_SUCCESS;
43197 }
43198 
43199 MA_API ma_result ma_rb_seek_write(ma_rb* pRB, size_t offsetInBytes)
43200 {
43201  ma_uint32 readOffset;
43202  ma_uint32 readOffsetInBytes;
43203  ma_uint32 readOffsetLoopFlag;
43204  ma_uint32 writeOffset;
43205  ma_uint32 writeOffsetInBytes;
43206  ma_uint32 writeOffsetLoopFlag;
43207  ma_uint32 newWriteOffsetInBytes;
43208  ma_uint32 newWriteOffsetLoopFlag;
43209 
43210  if (pRB == NULL) {
43211  return MA_INVALID_ARGS;
43212  }
43213 
43214  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
43215  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
43216 
43217  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
43218  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
43219 
43220  newWriteOffsetLoopFlag = writeOffsetLoopFlag;
43221 
43222  /* We cannot go past the write buffer. */
43223  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
43224  /* May end up looping. */
43225  if ((writeOffsetInBytes + offsetInBytes) >= pRB->subbufferSizeInBytes) {
43226  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + offsetInBytes) - pRB->subbufferSizeInBytes;
43227  newWriteOffsetLoopFlag ^= 0x80000000; /* <-- Looped. */
43228  } else {
43229  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + offsetInBytes);
43230  }
43231  } else {
43232  if ((writeOffsetInBytes + offsetInBytes) > readOffsetInBytes) {
43233  newWriteOffsetInBytes = readOffsetInBytes;
43234  } else {
43235  newWriteOffsetInBytes = (ma_uint32)(writeOffsetInBytes + offsetInBytes);
43236  }
43237  }
43238 
43239  c89atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetInBytes, newWriteOffsetLoopFlag));
43240  return MA_SUCCESS;
43241 }
43242 
43244 {
43245  ma_uint32 readOffset;
43246  ma_uint32 readOffsetInBytes;
43247  ma_uint32 readOffsetLoopFlag;
43248  ma_uint32 writeOffset;
43249  ma_uint32 writeOffsetInBytes;
43250  ma_uint32 writeOffsetLoopFlag;
43251 
43252  if (pRB == NULL) {
43253  return 0;
43254  }
43255 
43256  readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
43257  ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
43258 
43259  writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
43260  ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
43261 
43262  if (readOffsetLoopFlag == writeOffsetLoopFlag) {
43263  return writeOffsetInBytes - readOffsetInBytes;
43264  } else {
43265  return writeOffsetInBytes + (pRB->subbufferSizeInBytes - readOffsetInBytes);
43266  }
43267 }
43268 
43270 {
43271  ma_int32 dist;
43272 
43273  if (pRB == NULL) {
43274  return 0;
43275  }
43276 
43277  dist = ma_rb_pointer_distance(pRB);
43278  if (dist < 0) {
43279  return 0;
43280  }
43281 
43282  return dist;
43283 }
43284 
43286 {
43287  if (pRB == NULL) {
43288  return 0;
43289  }
43290 
43292 }
43293 
43295 {
43296  if (pRB == NULL) {
43297  return 0;
43298  }
43299 
43300  return pRB->subbufferSizeInBytes;
43301 }
43302 
43304 {
43305  if (pRB == NULL) {
43306  return 0;
43307  }
43308 
43309  if (pRB->subbufferStrideInBytes == 0) {
43310  return (size_t)pRB->subbufferSizeInBytes;
43311  }
43312 
43313  return (size_t)pRB->subbufferStrideInBytes;
43314 }
43315 
43316 MA_API size_t ma_rb_get_subbuffer_offset(ma_rb* pRB, size_t subbufferIndex)
43317 {
43318  if (pRB == NULL) {
43319  return 0;
43320  }
43321 
43322  return subbufferIndex * ma_rb_get_subbuffer_stride(pRB);
43323 }
43324 
43325 MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pBuffer)
43326 {
43327  if (pRB == NULL) {
43328  return NULL;
43329  }
43330 
43331  return ma_offset_ptr(pBuffer, ma_rb_get_subbuffer_offset(pRB, subbufferIndex));
43332 }
43333 
43334 
43335 
43337 {
43338  MA_ASSERT(pRB != NULL);
43339 
43340  return ma_get_bytes_per_frame(pRB->format, pRB->channels);
43341 }
43342 
43343 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)
43344 {
43345  ma_uint32 bpf;
43346  ma_result result;
43347 
43348  if (pRB == NULL) {
43349  return MA_INVALID_ARGS;
43350  }
43351 
43352  MA_ZERO_OBJECT(pRB);
43353 
43354  bpf = ma_get_bytes_per_frame(format, channels);
43355  if (bpf == 0) {
43356  return MA_INVALID_ARGS;
43357  }
43358 
43359  result = ma_rb_init_ex(subbufferSizeInFrames*bpf, subbufferCount, subbufferStrideInFrames*bpf, pOptionalPreallocatedBuffer, pAllocationCallbacks, &pRB->rb);
43360  if (result != MA_SUCCESS) {
43361  return result;
43362  }
43363 
43364  pRB->format = format;
43365  pRB->channels = channels;
43366 
43367  return MA_SUCCESS;
43368 }
43369 
43370 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)
43371 {
43372  return ma_pcm_rb_init_ex(format, channels, bufferSizeInFrames, 1, 0, pOptionalPreallocatedBuffer, pAllocationCallbacks, pRB);
43373 }
43374 
43376 {
43377  if (pRB == NULL) {
43378  return;
43379  }
43380 
43381  ma_rb_uninit(&pRB->rb);
43382 }
43383 
43384 MA_API void ma_pcm_rb_reset(ma_pcm_rb* pRB)
43385 {
43386  if (pRB == NULL) {
43387  return;
43388  }
43389 
43390  ma_rb_reset(&pRB->rb);
43391 }
43392 
43393 MA_API ma_result ma_pcm_rb_acquire_read(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut)
43394 {
43395  size_t sizeInBytes;
43396  ma_result result;
43397 
43398  if (pRB == NULL || pSizeInFrames == NULL) {
43399  return MA_INVALID_ARGS;
43400  }
43401 
43402  sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
43403 
43404  result = ma_rb_acquire_read(&pRB->rb, &sizeInBytes, ppBufferOut);
43405  if (result != MA_SUCCESS) {
43406  return result;
43407  }
43408 
43409  *pSizeInFrames = (ma_uint32)(sizeInBytes / (size_t)ma_pcm_rb_get_bpf(pRB));
43410  return MA_SUCCESS;
43411 }
43412 
43413 MA_API ma_result ma_pcm_rb_commit_read(ma_pcm_rb* pRB, ma_uint32 sizeInFrames, void* pBufferOut)
43414 {
43415  if (pRB == NULL) {
43416  return MA_INVALID_ARGS;
43417  }
43418 
43419  return ma_rb_commit_read(&pRB->rb, sizeInFrames * ma_pcm_rb_get_bpf(pRB), pBufferOut);
43420 }
43421 
43422 MA_API ma_result ma_pcm_rb_acquire_write(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut)
43423 {
43424  size_t sizeInBytes;
43425  ma_result result;
43426 
43427  if (pRB == NULL) {
43428  return MA_INVALID_ARGS;
43429  }
43430 
43431  sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
43432 
43433  result = ma_rb_acquire_write(&pRB->rb, &sizeInBytes, ppBufferOut);
43434  if (result != MA_SUCCESS) {
43435  return result;
43436  }
43437 
43438  *pSizeInFrames = (ma_uint32)(sizeInBytes / ma_pcm_rb_get_bpf(pRB));
43439  return MA_SUCCESS;
43440 }
43441 
43442 MA_API ma_result ma_pcm_rb_commit_write(ma_pcm_rb* pRB, ma_uint32 sizeInFrames, void* pBufferOut)
43443 {
43444  if (pRB == NULL) {
43445  return MA_INVALID_ARGS;
43446  }
43447 
43448  return ma_rb_commit_write(&pRB->rb, sizeInFrames * ma_pcm_rb_get_bpf(pRB), pBufferOut);
43449 }
43450 
43452 {
43453  if (pRB == NULL) {
43454  return MA_INVALID_ARGS;
43455  }
43456 
43457  return ma_rb_seek_read(&pRB->rb, offsetInFrames * ma_pcm_rb_get_bpf(pRB));
43458 }
43459 
43461 {
43462  if (pRB == NULL) {
43463  return MA_INVALID_ARGS;
43464  }
43465 
43466  return ma_rb_seek_write(&pRB->rb, offsetInFrames * ma_pcm_rb_get_bpf(pRB));
43467 }
43468 
43470 {
43471  if (pRB == NULL) {
43472  return 0;
43473  }
43474 
43475  return ma_rb_pointer_distance(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
43476 }
43477 
43479 {
43480  if (pRB == NULL) {
43481  return 0;
43482  }
43483 
43484  return ma_rb_available_read(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
43485 }
43486 
43488 {
43489  if (pRB == NULL) {
43490  return 0;
43491  }
43492 
43493  return ma_rb_available_write(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
43494 }
43495 
43497 {
43498  if (pRB == NULL) {
43499  return 0;
43500  }
43501 
43502  return (ma_uint32)(ma_rb_get_subbuffer_size(&pRB->rb) / ma_pcm_rb_get_bpf(pRB));
43503 }
43504 
43506 {
43507  if (pRB == NULL) {
43508  return 0;
43509  }
43510 
43511  return (ma_uint32)(ma_rb_get_subbuffer_stride(&pRB->rb) / ma_pcm_rb_get_bpf(pRB));
43512 }
43513 
43515 {
43516  if (pRB == NULL) {
43517  return 0;
43518  }
43519 
43520  return (ma_uint32)(ma_rb_get_subbuffer_offset(&pRB->rb, subbufferIndex) / ma_pcm_rb_get_bpf(pRB));
43521 }
43522 
43523 MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer)
43524 {
43525  if (pRB == NULL) {
43526  return NULL;
43527  }
43528 
43529  return ma_rb_get_subbuffer_ptr(&pRB->rb, subbufferIndex, pBuffer);
43530 }
43531 
43532 
43533 
43534 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)
43535 {
43536  ma_result result;
43537  ma_uint32 sizeInFrames;
43538 
43539  sizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(sampleRate, captureInternalSampleRate, captureInternalPeriodSizeInFrames * 5);
43540  if (sizeInFrames == 0) {
43541  return MA_INVALID_ARGS;
43542  }
43543 
43544  result = ma_pcm_rb_init(captureFormat, captureChannels, sizeInFrames, NULL, pAllocationCallbacks, &pRB->rb);
43545  if (result != MA_SUCCESS) {
43546  return result;
43547  }
43548 
43549  /* Seek forward a bit so we have a bit of a buffer in case of desyncs. */
43550  ma_pcm_rb_seek_write((ma_pcm_rb*)pRB, captureInternalPeriodSizeInFrames * 2);
43551 
43552  return MA_SUCCESS;
43553 }
43554 
43556 {
43557  ma_pcm_rb_uninit((ma_pcm_rb*)pRB);
43558  return MA_SUCCESS;
43559 }
43560 
43561 
43562 
43563 /**************************************************************************************************************************************************************
43564 
43565 Miscellaneous Helpers
43566 
43567 **************************************************************************************************************************************************************/
43568 MA_API const char* ma_result_description(ma_result result)
43569 {
43570  switch (result)
43571  {
43572  case MA_SUCCESS: return "No error";
43573  case MA_ERROR: return "Unknown error";
43574  case MA_INVALID_ARGS: return "Invalid argument";
43575  case MA_INVALID_OPERATION: return "Invalid operation";
43576  case MA_OUT_OF_MEMORY: return "Out of memory";
43577  case MA_OUT_OF_RANGE: return "Out of range";
43578  case MA_ACCESS_DENIED: return "Permission denied";
43579  case MA_DOES_NOT_EXIST: return "Resource does not exist";
43580  case MA_ALREADY_EXISTS: return "Resource already exists";
43581  case MA_TOO_MANY_OPEN_FILES: return "Too many open files";
43582  case MA_INVALID_FILE: return "Invalid file";
43583  case MA_TOO_BIG: return "Too large";
43584  case MA_PATH_TOO_LONG: return "Path too long";
43585  case MA_NAME_TOO_LONG: return "Name too long";
43586  case MA_NOT_DIRECTORY: return "Not a directory";
43587  case MA_IS_DIRECTORY: return "Is a directory";
43588  case MA_DIRECTORY_NOT_EMPTY: return "Directory not empty";
43589  case MA_AT_END: return "At end";
43590  case MA_NO_SPACE: return "No space available";
43591  case MA_BUSY: return "Device or resource busy";
43592  case MA_IO_ERROR: return "Input/output error";
43593  case MA_INTERRUPT: return "Interrupted";
43594  case MA_UNAVAILABLE: return "Resource unavailable";
43595  case MA_ALREADY_IN_USE: return "Resource already in use";
43596  case MA_BAD_ADDRESS: return "Bad address";
43597  case MA_BAD_SEEK: return "Illegal seek";
43598  case MA_BAD_PIPE: return "Broken pipe";
43599  case MA_DEADLOCK: return "Deadlock";
43600  case MA_TOO_MANY_LINKS: return "Too many links";
43601  case MA_NOT_IMPLEMENTED: return "Not implemented";
43602  case MA_NO_MESSAGE: return "No message of desired type";
43603  case MA_BAD_MESSAGE: return "Invalid message";
43604  case MA_NO_DATA_AVAILABLE: return "No data available";
43605  case MA_INVALID_DATA: return "Invalid data";
43606  case MA_TIMEOUT: return "Timeout";
43607  case MA_NO_NETWORK: return "Network unavailable";
43608  case MA_NOT_UNIQUE: return "Not unique";
43609  case MA_NOT_SOCKET: return "Socket operation on non-socket";
43610  case MA_NO_ADDRESS: return "Destination address required";
43611  case MA_BAD_PROTOCOL: return "Protocol wrong type for socket";
43612  case MA_PROTOCOL_UNAVAILABLE: return "Protocol not available";
43613  case MA_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
43614  case MA_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
43615  case MA_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
43616  case MA_SOCKET_NOT_SUPPORTED: return "Socket type not supported";
43617  case MA_CONNECTION_RESET: return "Connection reset";
43618  case MA_ALREADY_CONNECTED: return "Already connected";
43619  case MA_NOT_CONNECTED: return "Not connected";
43620  case MA_CONNECTION_REFUSED: return "Connection refused";
43621  case MA_NO_HOST: return "No host";
43622  case MA_IN_PROGRESS: return "Operation in progress";
43623  case MA_CANCELLED: return "Operation cancelled";
43624  case MA_MEMORY_ALREADY_MAPPED: return "Memory already mapped";
43625 
43626  case MA_FORMAT_NOT_SUPPORTED: return "Format not supported";
43627  case MA_DEVICE_TYPE_NOT_SUPPORTED: return "Device type not supported";
43628  case MA_SHARE_MODE_NOT_SUPPORTED: return "Share mode not supported";
43629  case MA_NO_BACKEND: return "No backend";
43630  case MA_NO_DEVICE: return "No device";
43631  case MA_API_NOT_FOUND: return "API not found";
43632  case MA_INVALID_DEVICE_CONFIG: return "Invalid device config";
43633 
43634  case MA_DEVICE_NOT_INITIALIZED: return "Device not initialized";
43635  case MA_DEVICE_NOT_STARTED: return "Device not started";
43636 
43637  case MA_FAILED_TO_INIT_BACKEND: return "Failed to initialize backend";
43638  case MA_FAILED_TO_OPEN_BACKEND_DEVICE: return "Failed to open backend device";
43639  case MA_FAILED_TO_START_BACKEND_DEVICE: return "Failed to start backend device";
43640  case MA_FAILED_TO_STOP_BACKEND_DEVICE: return "Failed to stop backend device";
43641 
43642  default: return "Unknown error";
43643  }
43644 }
43645 
43646 MA_API void* ma_malloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
43647 {
43648  if (pAllocationCallbacks != NULL) {
43649  return ma__malloc_from_callbacks(sz, pAllocationCallbacks);
43650  } else {
43651  return ma__malloc_default(sz, NULL);
43652  }
43653 }
43654 
43655 MA_API void* ma_realloc(void* p, size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
43656 {
43657  if (pAllocationCallbacks != NULL) {
43658  if (pAllocationCallbacks->onRealloc != NULL) {
43659  return pAllocationCallbacks->onRealloc(p, sz, pAllocationCallbacks->pUserData);
43660  } else {
43661  return NULL; /* This requires a native implementation of realloc(). */
43662  }
43663  } else {
43664  return ma__realloc_default(p, sz, NULL);
43665  }
43666 }
43667 
43668 MA_API void ma_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
43669 {
43670  if (pAllocationCallbacks != NULL) {
43671  ma__free_from_callbacks(p, pAllocationCallbacks);
43672  } else {
43673  ma__free_default(p, NULL);
43674  }
43675 }
43676 
43677 MA_API void* ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks* pAllocationCallbacks)
43678 {
43679  size_t extraBytes;
43680  void* pUnaligned;
43681  void* pAligned;
43682 
43683  if (alignment == 0) {
43684  return 0;
43685  }
43686 
43687  extraBytes = alignment-1 + sizeof(void*);
43688 
43689  pUnaligned = ma_malloc(sz + extraBytes, pAllocationCallbacks);
43690  if (pUnaligned == NULL) {
43691  return NULL;
43692  }
43693 
43694  pAligned = (void*)(((ma_uintptr)pUnaligned + extraBytes) & ~((ma_uintptr)(alignment-1)));
43695  ((void**)pAligned)[-1] = pUnaligned;
43696 
43697  return pAligned;
43698 }
43699 
43700 MA_API void ma_aligned_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
43701 {
43702  ma_free(((void**)p)[-1], pAllocationCallbacks);
43703 }
43704 
43705 MA_API const char* ma_get_format_name(ma_format format)
43706 {
43707  switch (format)
43708  {
43709  case ma_format_unknown: return "Unknown";
43710  case ma_format_u8: return "8-bit Unsigned Integer";
43711  case ma_format_s16: return "16-bit Signed Integer";
43712  case ma_format_s24: return "24-bit Signed Integer (Tightly Packed)";
43713  case ma_format_s32: return "32-bit Signed Integer";
43714  case ma_format_f32: return "32-bit IEEE Floating Point";
43715  default: return "Invalid";
43716  }
43717 }
43718 
43719 MA_API void ma_blend_f32(float* pOut, float* pInA, float* pInB, float factor, ma_uint32 channels)
43720 {
43721  ma_uint32 i;
43722  for (i = 0; i < channels; ++i) {
43723  pOut[i] = ma_mix_f32(pInA[i], pInB[i], factor);
43724  }
43725 }
43726 
43727 
43729 {
43730  ma_uint32 sizes[] = {
43731  0, /* unknown */
43732  1, /* u8 */
43733  2, /* s16 */
43734  3, /* s24 */
43735  4, /* s32 */
43736  4, /* f32 */
43737  };
43738  return sizes[format];
43739 }
43740 
43741 
43742 
43744 {
43746 
43748 
43749  return config;
43750 }
43751 
43752 
43754 {
43755  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
43756 
43757  if (pDataSource == NULL) {
43758  return MA_INVALID_ARGS;
43759  }
43760 
43761  MA_ZERO_OBJECT(pDataSourceBase);
43762 
43763  if (pConfig == NULL) {
43764  return MA_INVALID_ARGS;
43765  }
43766 
43767  pDataSourceBase->vtable = pConfig->vtable;
43768  pDataSourceBase->rangeBegInFrames = 0;
43769  pDataSourceBase->rangeEndInFrames = ~((ma_uint64)0);
43770  pDataSourceBase->loopBegInFrames = 0;
43771  pDataSourceBase->loopEndInFrames = ~((ma_uint64)0);
43772  pDataSourceBase->pCurrent = pDataSource; /* Always read from ourself by default. */
43773  pDataSourceBase->pNext = NULL;
43774  pDataSourceBase->onGetNext = NULL;
43775 
43776  /* Compatibility: Need to make a copy of the callbacks. This will be removed in version 0.11. */
43777  if (pConfig->vtable != NULL) {
43778  pDataSourceBase->cb = *pConfig->vtable;
43779  }
43780 
43781  return MA_SUCCESS;
43782 }
43783 
43784 MA_API void ma_data_source_uninit(ma_data_source* pDataSource)
43785 {
43786  if (pDataSource == NULL) {
43787  return;
43788  }
43789 
43790  /*
43791  This is placeholder in case we need this later. Data sources need to call this in their
43792  uninitialization routine to ensure things work later on if something is added here.
43793  */
43794 }
43795 
43796 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
43797 static ma_result ma_data_source_resolve_current(ma_data_source* pDataSource, ma_data_source** ppCurrentDataSource)
43798 {
43799  ma_data_source_base* pCurrentDataSource = (ma_data_source_base*)pDataSource;
43800 
43801  MA_ASSERT(pDataSource != NULL);
43802  MA_ASSERT(ppCurrentDataSource != NULL);
43803 
43804  if (pCurrentDataSource->pCurrent == NULL) {
43805  /*
43806  The current data source is NULL. If we're using this in the context of a chain we need to return NULL
43807  here so that we don't end up looping. Otherwise we just return the data source itself.
43808  */
43809  if (pCurrentDataSource->pNext != NULL || pCurrentDataSource->onGetNext != NULL) {
43810  pCurrentDataSource = NULL;
43811  } else {
43812  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. */
43813  }
43814  } else {
43815  pCurrentDataSource = (ma_data_source_base*)pCurrentDataSource->pCurrent;
43816  }
43817 
43818  *ppCurrentDataSource = pCurrentDataSource;
43819 
43820  return MA_SUCCESS;
43821 }
43822 
43823 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)
43824 {
43825  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
43826 
43827  if (pDataSourceBase == NULL) {
43828  return MA_AT_END;
43829  }
43830 
43831  if (pDataSourceBase->rangeEndInFrames == ~((ma_uint64)0) && (pDataSourceBase->loopEndInFrames == ~((ma_uint64)0) || loop == MA_FALSE)) {
43832  /* No range is set - just read like normal. The data source itself will tell us when the end is reached. */
43833  return pDataSourceBase->cb.onRead(pDataSourceBase, pFramesOut, frameCount, pFramesRead);
43834  } else {
43835  /* Need to clamp to within the range. */
43836  ma_result result;
43837  ma_uint64 cursor;
43838  ma_uint64 framesRead = 0;
43839  ma_uint64 rangeEnd;
43840 
43841  result = ma_data_source_get_cursor_in_pcm_frames(pDataSourceBase, &cursor);
43842  if (result != MA_SUCCESS) {
43843  /* 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. */
43844  return pDataSourceBase->cb.onRead(pDataSourceBase, pFramesOut, frameCount, pFramesRead);
43845  }
43846 
43847  /* We have the cursor. We need to make sure we don't read beyond our range. */
43848  rangeEnd = pDataSourceBase->rangeEndInFrames;
43849 
43850  /* If looping, make sure we're within range. */
43851  if (loop) {
43852  if (pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) {
43853  rangeEnd = ma_min(rangeEnd, pDataSourceBase->rangeBegInFrames + pDataSourceBase->loopEndInFrames);
43854  }
43855  }
43856 
43857  if (frameCount > (rangeEnd - cursor) && rangeEnd != ~((ma_uint64)0)) {
43858  frameCount = (rangeEnd - cursor);
43859  }
43860 
43861  result = pDataSourceBase->cb.onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead);
43862 
43863  if (pFramesRead != NULL) {
43864  *pFramesRead = framesRead;
43865  }
43866 
43867  /* We need to make sure MA_AT_END is returned if we hit the end of the range. */
43868  if (result != MA_AT_END && framesRead == 0) {
43869  result = MA_AT_END;
43870  }
43871 
43872  return result;
43873  }
43874 }
43875 #endif
43876 
43877 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)
43878 {
43879 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
43880  ma_result result = MA_SUCCESS;
43881  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
43882  ma_data_source_base* pCurrentDataSource;
43883  void* pRunningFramesOut = pFramesOut;
43884  ma_uint64 totalFramesProcessed = 0;
43885  ma_format format;
43886  ma_uint32 channels;
43887  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. */
43888 
43889  if (pFramesRead != NULL) {
43890  *pFramesRead = 0;
43891  }
43892 
43893  if (pDataSourceBase == NULL) {
43894  return MA_INVALID_ARGS;
43895  }
43896 
43897  /*
43898  We need to know the data format so we can advance the output buffer as we read frames. If this
43899  fails, chaining will not work and we'll just read as much as we can from the current source.
43900  */
43901  if (ma_data_source_get_data_format(pDataSource, &format, &channels, NULL) != MA_SUCCESS) {
43902  result = ma_data_source_resolve_current(pDataSource, (ma_data_source**)&pCurrentDataSource);
43903  if (result != MA_SUCCESS) {
43904  return result;
43905  }
43906 
43907  return ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pFramesOut, frameCount, pFramesRead, loop);
43908  }
43909 
43910  /*
43911  Looping is a bit of a special case. When the `loop` argument is true, chaining will not work and
43912  only the current data source will be read from.
43913  */
43914 
43915  /* Keep reading until we've read as many frames as possible. */
43916  while (totalFramesProcessed < frameCount) {
43917  ma_uint64 framesProcessed;
43918  ma_uint64 framesRemaining = frameCount - totalFramesProcessed;
43919 
43920  /* We need to resolve the data source that we'll actually be reading from. */
43921  result = ma_data_source_resolve_current(pDataSource, (ma_data_source**)&pCurrentDataSource);
43922  if (result != MA_SUCCESS) {
43923  break;
43924  }
43925 
43926  if (pCurrentDataSource == NULL) {
43927  break;
43928  }
43929 
43930  result = ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pRunningFramesOut, framesRemaining, &framesProcessed, loop);
43931  totalFramesProcessed += framesProcessed;
43932 
43933  /*
43934  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
43935  not necessarily considered an error.
43936  */
43937  if (result != MA_SUCCESS && result != MA_AT_END) {
43938  break;
43939  }
43940 
43941  /*
43942  We can determine if we've reached the end by checking the return value of the onRead()
43943  callback. To loop back to the start, all we need to do is seek back to the first frame.
43944  */
43945  if (result == MA_AT_END) {
43946  /*
43947  We reached the end. If we're looping, we just loop back to the start of the current
43948  data source. If we're not looping we need to check if we have another in the chain, and
43949  if so, switch to it.
43950  */
43951  if (loop) {
43952  if (framesProcessed == 0) {
43953  emptyLoopCounter += 1;
43954  if (emptyLoopCounter > 1) {
43955  break; /* Infinite loop detected. Get out. */
43956  }
43957  } else {
43958  emptyLoopCounter = 0;
43959  }
43960 
43961  if (ma_data_source_seek_to_pcm_frame(pCurrentDataSource, pCurrentDataSource->loopBegInFrames) != MA_SUCCESS) {
43962  break; /* Failed to loop. Abort. */
43963  }
43964 
43965  /* Don't return MA_AT_END for looping sounds. */
43966  result = MA_SUCCESS;
43967  } else {
43968  if (pCurrentDataSource->pNext != NULL) {
43969  pDataSourceBase->pCurrent = pCurrentDataSource->pNext;
43970  } else if (pCurrentDataSource->onGetNext != NULL) {
43971  pDataSourceBase->pCurrent = pCurrentDataSource->onGetNext(pCurrentDataSource);
43972  if (pDataSourceBase->pCurrent == NULL) {
43973  break; /* Our callback did not return a next data source. We're done. */
43974  }
43975  } else {
43976  /* Reached the end of the chain. We're done. */
43977  break;
43978  }
43979 
43980  /* The next data source needs to be rewound to ensure data is read in looping scenarios. */
43981  ma_data_source_seek_to_pcm_frame(pDataSourceBase->pCurrent, 0);
43982 
43983  /*
43984  We need to make sure we clear the MA_AT_END result so we don't accidentally return
43985  it in the event that we coincidentally ended reading at the exact transition point
43986  of two data sources in a chain.
43987  */
43988  result = MA_SUCCESS;
43989  }
43990  }
43991 
43992  if (pRunningFramesOut != NULL) {
43993  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesProcessed * ma_get_bytes_per_frame(format, channels));
43994  }
43995  }
43996 
43997  if (pFramesRead != NULL) {
43998  *pFramesRead = totalFramesProcessed;
43999  }
44000 
44001  return result;
44002 #else
44003  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44004 
44005  /* Safety. */
44006  if (pFramesRead != NULL) {
44007  *pFramesRead = 0;
44008  }
44009 
44010  if (pCallbacks == NULL) {
44011  return MA_INVALID_ARGS;
44012  }
44013 
44014  if (pCallbacks->onRead == NULL) {
44015  return MA_NOT_IMPLEMENTED;
44016  }
44017 
44018  /* A very small optimization for the non looping case. */
44019  if (loop == MA_FALSE) {
44020  return pCallbacks->onRead(pDataSource, pFramesOut, frameCount, pFramesRead);
44021  } else {
44022  ma_format format;
44023  ma_uint32 channels;
44024  ma_uint32 sampleRate;
44025  if (ma_data_source_get_data_format(pDataSource, &format, &channels, &sampleRate) != MA_SUCCESS) {
44026  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. */
44027  } else {
44028  ma_result result = MA_SUCCESS;
44029  ma_uint64 totalFramesProcessed;
44030  void* pRunningFramesOut = pFramesOut;
44031 
44032  totalFramesProcessed = 0;
44033  while (totalFramesProcessed < frameCount) {
44034  ma_uint64 framesProcessed;
44035  ma_uint64 framesRemaining = frameCount - totalFramesProcessed;
44036 
44037  result = pCallbacks->onRead(pDataSource, pRunningFramesOut, framesRemaining, &framesProcessed);
44038  totalFramesProcessed += framesProcessed;
44039 
44040  /*
44041  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
44042  not necessarily considered an error.
44043  */
44044  if (result != MA_SUCCESS && result != MA_AT_END) {
44045  break;
44046  }
44047 
44048  /*
44049  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
44050  we've reached the end. To loop back to the start, all we need to do is seek back to the first frame.
44051  */
44052  if (framesProcessed < framesRemaining || result == MA_AT_END) {
44053  if (ma_data_source_seek_to_pcm_frame(pDataSource, 0) != MA_SUCCESS) {
44054  break;
44055  }
44056  }
44057 
44058  if (pRunningFramesOut != NULL) {
44059  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesProcessed * ma_get_bytes_per_frame(format, channels));
44060  }
44061  }
44062 
44063  if (pFramesRead != NULL) {
44064  *pFramesRead = totalFramesProcessed;
44065  }
44066 
44067  return result;
44068  }
44069  }
44070 #endif
44071 }
44072 
44073 MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked, ma_bool32 loop)
44074 {
44075  return ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, pFramesSeeked, loop);
44076 }
44077 
44079 {
44080 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
44081  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44082 
44083  if (pDataSourceBase == NULL) {
44084  return MA_SUCCESS;
44085  }
44086 
44087  if (pDataSourceBase->cb.onSeek == NULL) {
44088  return MA_NOT_IMPLEMENTED;
44089  }
44090 
44091  if (frameIndex > pDataSourceBase->rangeEndInFrames) {
44092  return MA_INVALID_OPERATION; /* Trying to seek to far forward. */
44093  }
44094 
44095  return pDataSourceBase->cb.onSeek(pDataSource, pDataSourceBase->rangeBegInFrames + frameIndex);
44096 #else
44097  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44098  if (pCallbacks == NULL) {
44099  return MA_INVALID_ARGS;
44100  }
44101 
44102  if (pCallbacks->onSeek == NULL) {
44103  return MA_NOT_IMPLEMENTED;
44104  }
44105 
44106  return pCallbacks->onSeek(pDataSource, frameIndex);
44107 #endif
44108 }
44109 
44110 MA_API ma_result ma_data_source_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount)
44111 {
44112  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44113  if (pCallbacks == NULL) {
44114  return MA_INVALID_ARGS;
44115  }
44116 
44117  if (pCallbacks->onMap == NULL) {
44118  return MA_NOT_IMPLEMENTED;
44119  }
44120 
44121  return pCallbacks->onMap(pDataSource, ppFramesOut, pFrameCount);
44122 }
44123 
44125 {
44126  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44127  if (pCallbacks == NULL) {
44128  return MA_INVALID_ARGS;
44129  }
44130 
44131  if (pCallbacks->onUnmap == NULL) {
44132  return MA_NOT_IMPLEMENTED;
44133  }
44134 
44135  return pCallbacks->onUnmap(pDataSource, frameCount);
44136 }
44137 
44138 MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
44139 {
44140  ma_result result;
44141  ma_format format;
44142  ma_uint32 channels;
44143  ma_uint32 sampleRate;
44144  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44145 
44146  if (pFormat != NULL) {
44147  *pFormat = ma_format_unknown;
44148  }
44149 
44150  if (pChannels != NULL) {
44151  *pChannels = 0;
44152  }
44153 
44154  if (pSampleRate != NULL) {
44155  *pSampleRate = 0;
44156  }
44157 
44158  if (pCallbacks == NULL) {
44159  return MA_INVALID_ARGS;
44160  }
44161 
44162  if (pCallbacks->onGetDataFormat == NULL) {
44163  return MA_NOT_IMPLEMENTED;
44164  }
44165 
44166  result = pCallbacks->onGetDataFormat(pDataSource, &format, &channels, &sampleRate);
44167  if (result != MA_SUCCESS) {
44168  return result;
44169  }
44170 
44171  if (pFormat != NULL) {
44172  *pFormat = format;
44173  }
44174  if (pChannels != NULL) {
44175  *pChannels = channels;
44176  }
44177  if (pSampleRate != NULL) {
44178  *pSampleRate = sampleRate;
44179  }
44180 
44181  return MA_SUCCESS;
44182 }
44183 
44185 {
44186 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
44187  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44188  ma_result result;
44189  ma_uint64 cursor;
44190 
44191  if (pCursor == NULL) {
44192  return MA_INVALID_ARGS;
44193  }
44194 
44195  *pCursor = 0;
44196 
44197  if (pDataSourceBase == NULL) {
44198  return MA_SUCCESS;
44199  }
44200 
44201  if (pDataSourceBase->cb.onGetCursor == NULL) {
44202  return MA_NOT_IMPLEMENTED;
44203  }
44204 
44205  result = pDataSourceBase->cb.onGetCursor(pDataSourceBase, &cursor);
44206  if (result != MA_SUCCESS) {
44207  return result;
44208  }
44209 
44210  /* The cursor needs to be made relative to the start of the range. */
44211  if (cursor < pDataSourceBase->rangeBegInFrames) { /* Safety check so we don't return some huge number. */
44212  *pCursor = 0;
44213  } else {
44214  *pCursor = cursor - pDataSourceBase->rangeBegInFrames;
44215  }
44216 
44217  return MA_SUCCESS;
44218 #else
44219  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44220 
44221  if (pCursor == NULL) {
44222  return MA_INVALID_ARGS;
44223  }
44224 
44225  *pCursor = 0;
44226 
44227  if (pCallbacks == NULL) {
44228  return MA_INVALID_ARGS;
44229  }
44230 
44231  if (pCallbacks->onGetCursor == NULL) {
44232  return MA_NOT_IMPLEMENTED;
44233  }
44234 
44235  return pCallbacks->onGetCursor(pDataSource, pCursor);
44236 #endif
44237 }
44238 
44240 {
44241 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
44242  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44243 
44244  if (pLength == NULL) {
44245  return MA_INVALID_ARGS;
44246  }
44247 
44248  *pLength = 0;
44249 
44250  if (pDataSourceBase == NULL) {
44251  return MA_INVALID_ARGS;
44252  }
44253 
44254  /*
44255  If we have a range defined we'll use that to determine the length. This is one of rare times
44256  where we'll actually trust the caller. If they've set the range, I think it's mostly safe to
44257  assume they've set it based on some higher level knowledge of the structure of the sound bank.
44258  */
44259  if (pDataSourceBase->rangeEndInFrames != ~((ma_uint64)0)) {
44260  *pLength = pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames;
44261  return MA_SUCCESS;
44262  }
44263 
44264  /*
44265  Getting here means a range is not defined so we'll need to get the data source itself to tell
44266  us the length.
44267  */
44268  if (pDataSourceBase->cb.onGetLength == NULL) {
44269  return MA_NOT_IMPLEMENTED;
44270  }
44271 
44272  return pDataSourceBase->cb.onGetLength(pDataSource, pLength);
44273 #else
44274  ma_data_source_callbacks* pCallbacks = (ma_data_source_callbacks*)pDataSource;
44275 
44276  if (pLength == NULL) {
44277  return MA_INVALID_ARGS;
44278  }
44279 
44280  *pLength = 0;
44281 
44282  if (pCallbacks == NULL) {
44283  return MA_INVALID_ARGS;
44284  }
44285 
44286  if (pCallbacks->onGetLength == NULL) {
44287  return MA_NOT_IMPLEMENTED;
44288  }
44289 
44290  return pCallbacks->onGetLength(pDataSource, pLength);
44291 #endif
44292 }
44293 
44294 
44295 #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
44296 MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames)
44297 {
44298  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44299  ma_result result;
44300  ma_uint64 cursor;
44301  ma_uint64 loopBegAbsolute;
44302  ma_uint64 loopEndAbsolute;
44303 
44304  if (pDataSource == NULL) {
44305  return MA_INVALID_ARGS;
44306  }
44307 
44308  if (rangeEndInFrames < rangeBegInFrames) {
44309  return MA_INVALID_ARGS; /* The end of the range must come after the beginning. */
44310  }
44311 
44312  /*
44313  The loop points need to be updated. We'll be storing the loop points relative to the range. We'll update
44314  these so that they maintain their absolute positioning. The loop points will then be clamped to the range.
44315  */
44316  loopBegAbsolute = pDataSourceBase->loopBegInFrames + pDataSourceBase->rangeBegInFrames;
44317  loopEndAbsolute = pDataSourceBase->loopEndInFrames + ((pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) ? pDataSourceBase->rangeBegInFrames : 0);
44318 
44319  pDataSourceBase->rangeBegInFrames = rangeBegInFrames;
44320  pDataSourceBase->rangeEndInFrames = rangeEndInFrames;
44321 
44322  /* Make the loop points relative again, and make sure they're clamped to within the range. */
44323  if (loopBegAbsolute > pDataSourceBase->rangeBegInFrames) {
44324  pDataSourceBase->loopBegInFrames = loopBegAbsolute - pDataSourceBase->rangeBegInFrames;
44325  } else {
44326  pDataSourceBase->loopBegInFrames = 0;
44327  }
44328 
44329  if (pDataSourceBase->loopBegInFrames > pDataSourceBase->rangeEndInFrames) {
44330  pDataSourceBase->loopBegInFrames = pDataSourceBase->rangeEndInFrames;
44331  }
44332 
44333  /* Only need to update the loop end point if it's not -1. */
44334  if (loopEndAbsolute != ~((ma_uint64)0)) {
44335  if (loopEndAbsolute > pDataSourceBase->rangeBegInFrames) {
44336  pDataSourceBase->loopEndInFrames = loopEndAbsolute - pDataSourceBase->rangeBegInFrames;
44337  } else {
44338  pDataSourceBase->loopEndInFrames = 0;
44339  }
44340 
44341  if (pDataSourceBase->loopEndInFrames > pDataSourceBase->rangeEndInFrames && pDataSourceBase->loopEndInFrames) {
44342  pDataSourceBase->loopEndInFrames = pDataSourceBase->rangeEndInFrames;
44343  }
44344  }
44345 
44346 
44347  /* If the new range is past the current cursor position we need to seek to it. */
44348  result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursor);
44349  if (result == MA_SUCCESS) {
44350  /* Seek to within range. Note that our seek positions here are relative to the new range. */
44351  if (cursor < rangeBegInFrames) {
44352  ma_data_source_seek_to_pcm_frame(pDataSource, 0);
44353  } else if (cursor > rangeEndInFrames) {
44354  ma_data_source_seek_to_pcm_frame(pDataSource, rangeEndInFrames - rangeBegInFrames);
44355  }
44356  } else {
44357  /* 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. */
44358  }
44359 
44360  return MA_SUCCESS;
44361 }
44362 
44363 MA_API void ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames)
44364 {
44365  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44366 
44367  if (pDataSource == NULL) {
44368  return;
44369  }
44370 
44371  if (pRangeBegInFrames != NULL) {
44372  *pRangeBegInFrames = pDataSourceBase->rangeBegInFrames;
44373  }
44374 
44375  if (pRangeEndInFrames != NULL) {
44376  *pRangeEndInFrames = pDataSourceBase->rangeEndInFrames;
44377  }
44378 }
44379 
44380 MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames)
44381 {
44382  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44383 
44384  if (pDataSource == NULL) {
44385  return MA_INVALID_ARGS;
44386  }
44387 
44388  if (loopEndInFrames < loopBegInFrames) {
44389  return MA_INVALID_ARGS; /* The end of the loop point must come after the beginning. */
44390  }
44391 
44392  if (loopEndInFrames > pDataSourceBase->rangeEndInFrames && loopEndInFrames != ~((ma_uint64)0)) {
44393  return MA_INVALID_ARGS; /* The end of the loop point must not go beyond the range. */
44394  }
44395 
44396  pDataSourceBase->loopBegInFrames = loopBegInFrames;
44397  pDataSourceBase->loopEndInFrames = loopEndInFrames;
44398 
44399  /* The end cannot exceed the range. */
44400  if (pDataSourceBase->loopEndInFrames > (pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames) && pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) {
44401  pDataSourceBase->loopEndInFrames = (pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames);
44402  }
44403 
44404  return MA_SUCCESS;
44405 }
44406 
44407 MA_API void ma_data_source_get_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLoopBegInFrames, ma_uint64* pLoopEndInFrames)
44408 {
44409  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44410 
44411  if (pDataSource == NULL) {
44412  return;
44413  }
44414 
44415  if (pLoopBegInFrames != NULL) {
44416  *pLoopBegInFrames = pDataSourceBase->loopBegInFrames;
44417  }
44418 
44419  if (pLoopEndInFrames != NULL) {
44420  *pLoopEndInFrames = pDataSourceBase->loopEndInFrames;
44421  }
44422 }
44423 
44424 MA_API ma_result ma_data_source_set_current(ma_data_source* pDataSource, ma_data_source* pCurrentDataSource)
44425 {
44426  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44427 
44428  if (pDataSource == NULL) {
44429  return MA_INVALID_ARGS;
44430  }
44431 
44432  pDataSourceBase->pCurrent = pCurrentDataSource;
44433 
44434  return MA_SUCCESS;
44435 }
44436 
44437 MA_API ma_data_source* ma_data_source_get_current(ma_data_source* pDataSource)
44438 {
44439  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44440 
44441  if (pDataSource == NULL) {
44442  return NULL;
44443  }
44444 
44445  return pDataSourceBase->pCurrent;
44446 }
44447 
44448 MA_API ma_result ma_data_source_set_next(ma_data_source* pDataSource, ma_data_source* pNextDataSource)
44449 {
44450  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44451 
44452  if (pDataSource == NULL) {
44453  return MA_INVALID_ARGS;
44454  }
44455 
44456  pDataSourceBase->pNext = pNextDataSource;
44457 
44458  return MA_SUCCESS;
44459 }
44460 
44461 MA_API ma_data_source* ma_data_source_get_next(ma_data_source* pDataSource)
44462 {
44463  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44464 
44465  if (pDataSource == NULL) {
44466  return NULL;
44467  }
44468 
44469  return pDataSourceBase->pNext;
44470 }
44471 
44472 MA_API ma_result ma_data_source_set_next_callback(ma_data_source* pDataSource, ma_data_source_get_next_proc onGetNext)
44473 {
44474  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44475 
44476  if (pDataSource == NULL) {
44477  return MA_INVALID_ARGS;
44478  }
44479 
44480  pDataSourceBase->onGetNext = onGetNext;
44481 
44482  return MA_SUCCESS;
44483 }
44484 
44485 MA_API ma_data_source_get_next_proc ma_data_source_get_next_callback(ma_data_source* pDataSource)
44486 {
44487  ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
44488 
44489  if (pDataSource == NULL) {
44490  return NULL;
44491  }
44492 
44493  return pDataSourceBase->onGetNext;
44494 }
44495 #endif
44496 
44497 
44498 static ma_result ma_audio_buffer_ref__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
44499 {
44500  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
44501  ma_uint64 framesRead = ma_audio_buffer_ref_read_pcm_frames(pAudioBufferRef, pFramesOut, frameCount, MA_FALSE);
44502 
44503  if (pFramesRead != NULL) {
44504  *pFramesRead = framesRead;
44505  }
44506 
44507  if (framesRead < frameCount || framesRead == 0) {
44508  return MA_AT_END;
44509  }
44510 
44511  return MA_SUCCESS;
44512 }
44513 
44515 {
44516  return ma_audio_buffer_ref_seek_to_pcm_frame((ma_audio_buffer_ref*)pDataSource, frameIndex);
44517 }
44518 
44519 static ma_result ma_audio_buffer_ref__data_source_on_map(ma_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount)
44520 {
44521  return ma_audio_buffer_ref_map((ma_audio_buffer_ref*)pDataSource, ppFramesOut, pFrameCount);
44522 }
44523 
44525 {
44526  return ma_audio_buffer_ref_unmap((ma_audio_buffer_ref*)pDataSource, frameCount);
44527 }
44528 
44529 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)
44530 {
44531  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
44532 
44533  *pFormat = pAudioBufferRef->format;
44534  *pChannels = pAudioBufferRef->channels;
44535  *pSampleRate = 0; /* There is no notion of a sample rate with audio buffers. */
44536 
44537  return MA_SUCCESS;
44538 }
44539 
44541 {
44542  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
44543 
44544  *pCursor = pAudioBufferRef->cursor;
44545 
44546  return MA_SUCCESS;
44547 }
44548 
44550 {
44551  ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
44552 
44553  *pLength = pAudioBufferRef->sizeInFrames;
44554 
44555  return MA_SUCCESS;
44556 }
44557 
44559 {
44567 };
44568 
44569 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)
44570 {
44571  ma_result result;
44572  ma_data_source_config dataSourceConfig;
44573 
44574  if (pAudioBufferRef == NULL) {
44575  return MA_INVALID_ARGS;
44576  }
44577 
44578  MA_ZERO_OBJECT(pAudioBufferRef);
44579 
44580  dataSourceConfig = ma_data_source_config_init();
44582 
44583  result = ma_data_source_init(&dataSourceConfig, &pAudioBufferRef->ds);
44584  if (result != MA_SUCCESS) {
44585  return result;
44586  }
44587 
44588  pAudioBufferRef->format = format;
44589  pAudioBufferRef->channels = channels;
44590  pAudioBufferRef->cursor = 0;
44591  pAudioBufferRef->sizeInFrames = sizeInFrames;
44592  pAudioBufferRef->pData = pData;
44593 
44594  return MA_SUCCESS;
44595 }
44596 
44598 {
44599  if (pAudioBufferRef == NULL) {
44600  return;
44601  }
44602 
44603  ma_data_source_uninit(&pAudioBufferRef->ds);
44604 }
44605 
44606 MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames)
44607 {
44608  if (pAudioBufferRef == NULL) {
44609  return MA_INVALID_ARGS;
44610  }
44611 
44612  pAudioBufferRef->cursor = 0;
44613  pAudioBufferRef->sizeInFrames = sizeInFrames;
44614  pAudioBufferRef->pData = pData;
44615 
44616  return MA_SUCCESS;
44617 }
44618 
44619 MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop)
44620 {
44621  ma_uint64 totalFramesRead = 0;
44622 
44623  if (pAudioBufferRef == NULL) {
44624  return 0;
44625  }
44626 
44627  if (frameCount == 0) {
44628  return 0;
44629  }
44630 
44631  while (totalFramesRead < frameCount) {
44632  ma_uint64 framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
44633  ma_uint64 framesRemaining = frameCount - totalFramesRead;
44634  ma_uint64 framesToRead;
44635 
44636  framesToRead = framesRemaining;
44637  if (framesToRead > framesAvailable) {
44638  framesToRead = framesAvailable;
44639  }
44640 
44641  if (pFramesOut != NULL) {
44642  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);
44643  }
44644 
44645  totalFramesRead += framesToRead;
44646 
44647  pAudioBufferRef->cursor += framesToRead;
44648  if (pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames) {
44649  if (loop) {
44650  pAudioBufferRef->cursor = 0;
44651  } else {
44652  break; /* We've reached the end and we're not looping. Done. */
44653  }
44654  }
44655 
44656  MA_ASSERT(pAudioBufferRef->cursor < pAudioBufferRef->sizeInFrames);
44657  }
44658 
44659  return totalFramesRead;
44660 }
44661 
44663 {
44664  if (pAudioBufferRef == NULL) {
44665  return MA_INVALID_ARGS;
44666  }
44667 
44668  if (frameIndex > pAudioBufferRef->sizeInFrames) {
44669  return MA_INVALID_ARGS;
44670  }
44671 
44672  pAudioBufferRef->cursor = (size_t)frameIndex;
44673 
44674  return MA_SUCCESS;
44675 }
44676 
44677 MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount)
44678 {
44679  ma_uint64 framesAvailable;
44680  ma_uint64 frameCount = 0;
44681 
44682  if (ppFramesOut != NULL) {
44683  *ppFramesOut = NULL; /* Safety. */
44684  }
44685 
44686  if (pFrameCount != NULL) {
44687  frameCount = *pFrameCount;
44688  *pFrameCount = 0; /* Safety. */
44689  }
44690 
44691  if (pAudioBufferRef == NULL || ppFramesOut == NULL || pFrameCount == NULL) {
44692  return MA_INVALID_ARGS;
44693  }
44694 
44695  framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
44696  if (frameCount > framesAvailable) {
44697  frameCount = framesAvailable;
44698  }
44699 
44700  *ppFramesOut = ma_offset_ptr(pAudioBufferRef->pData, pAudioBufferRef->cursor * ma_get_bytes_per_frame(pAudioBufferRef->format, pAudioBufferRef->channels));
44701  *pFrameCount = frameCount;
44702 
44703  return MA_SUCCESS;
44704 }
44705 
44707 {
44708  ma_uint64 framesAvailable;
44709 
44710  if (pAudioBufferRef == NULL) {
44711  return MA_INVALID_ARGS;
44712  }
44713 
44714  framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
44715  if (frameCount > framesAvailable) {
44716  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. */
44717  }
44718 
44719  pAudioBufferRef->cursor += frameCount;
44720 
44721  if (pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames) {
44722  return MA_AT_END; /* Successful. Need to tell the caller that the end has been reached so that it can loop if desired. */
44723  } else {
44724  return MA_SUCCESS;
44725  }
44726 }
44727 
44729 {
44730  if (pAudioBufferRef == NULL) {
44731  return MA_FALSE;
44732  }
44733 
44734  return pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames;
44735 }
44736 
44738 {
44739  if (pCursor == NULL) {
44740  return MA_INVALID_ARGS;
44741  }
44742 
44743  *pCursor = 0;
44744 
44745  if (pAudioBufferRef == NULL) {
44746  return MA_INVALID_ARGS;
44747  }
44748 
44749  *pCursor = pAudioBufferRef->cursor;
44750 
44751  return MA_SUCCESS;
44752 }
44753 
44755 {
44756  if (pLength == NULL) {
44757  return MA_INVALID_ARGS;
44758  }
44759 
44760  *pLength = 0;
44761 
44762  if (pAudioBufferRef == NULL) {
44763  return MA_INVALID_ARGS;
44764  }
44765 
44766  *pLength = pAudioBufferRef->sizeInFrames;
44767 
44768  return MA_SUCCESS;
44769 }
44770 
44772 {
44773  if (pAvailableFrames == NULL) {
44774  return MA_INVALID_ARGS;
44775  }
44776 
44777  *pAvailableFrames = 0;
44778 
44779  if (pAudioBufferRef == NULL) {
44780  return MA_INVALID_ARGS;
44781  }
44782 
44783  if (pAudioBufferRef->sizeInFrames <= pAudioBufferRef->cursor) {
44784  *pAvailableFrames = 0;
44785  } else {
44786  *pAvailableFrames = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
44787  }
44788 
44789  return MA_SUCCESS;
44790 }
44791 
44792 
44793 
44794 
44795 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)
44796 {
44798 
44800  config.format = format;
44801  config.channels = channels;
44802  config.sizeInFrames = sizeInFrames;
44803  config.pData = pData;
44804  ma_allocation_callbacks_init_copy(&config.allocationCallbacks, pAllocationCallbacks);
44805 
44806  return config;
44807 }
44808 
44809 static ma_result ma_audio_buffer_init_ex(const ma_audio_buffer_config* pConfig, ma_bool32 doCopy, ma_audio_buffer* pAudioBuffer)
44810 {
44811  ma_result result;
44812 
44813  if (pAudioBuffer == NULL) {
44814  return MA_INVALID_ARGS;
44815  }
44816 
44817  MA_ZERO_MEMORY(pAudioBuffer, sizeof(*pAudioBuffer) - sizeof(pAudioBuffer->_pExtraData)); /* Safety. Don't overwrite the extra data. */
44818 
44819  if (pConfig == NULL) {
44820  return MA_INVALID_ARGS;
44821  }
44822 
44823  if (pConfig->sizeInFrames == 0) {
44824  return MA_INVALID_ARGS; /* Not allowing buffer sizes of 0 frames. */
44825  }
44826 
44827  result = ma_audio_buffer_ref_init(pConfig->format, pConfig->channels, NULL, 0, &pAudioBuffer->ref);
44828  if (result != MA_SUCCESS) {
44829  return result;
44830  }
44831 
44833 
44834  if (doCopy) {
44835  ma_uint64 allocationSizeInBytes;
44836  void* pData;
44837 
44838  allocationSizeInBytes = pConfig->sizeInFrames * ma_get_bytes_per_frame(pConfig->format, pConfig->channels);
44839  if (allocationSizeInBytes > MA_SIZE_MAX) {
44840  return MA_OUT_OF_MEMORY; /* Too big. */
44841  }
44842 
44843  pData = ma__malloc_from_callbacks((size_t)allocationSizeInBytes, &pAudioBuffer->allocationCallbacks); /* Safe cast to size_t. */
44844  if (pData == NULL) {
44845  return MA_OUT_OF_MEMORY;
44846  }
44847 
44848  if (pConfig->pData != NULL) {
44849  ma_copy_pcm_frames(pData, pConfig->pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
44850  } else {
44851  ma_silence_pcm_frames(pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
44852  }
44853 
44854  ma_audio_buffer_ref_set_data(&pAudioBuffer->ref, pData, pConfig->sizeInFrames);
44855  pAudioBuffer->ownsData = MA_TRUE;
44856  } else {
44857  ma_audio_buffer_ref_set_data(&pAudioBuffer->ref, pConfig->pData, pConfig->sizeInFrames);
44858  pAudioBuffer->ownsData = MA_FALSE;
44859  }
44860 
44861  return MA_SUCCESS;
44862 }
44863 
44864 static void ma_audio_buffer_uninit_ex(ma_audio_buffer* pAudioBuffer, ma_bool32 doFree)
44865 {
44866  if (pAudioBuffer == NULL) {
44867  return;
44868  }
44869 
44870  if (pAudioBuffer->ownsData && pAudioBuffer->ref.pData != &pAudioBuffer->_pExtraData[0]) {
44871  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. */
44872  }
44873 
44874  if (doFree) {
44875  ma__free_from_callbacks(pAudioBuffer, &pAudioBuffer->allocationCallbacks);
44876  }
44877 
44878  ma_audio_buffer_ref_uninit(&pAudioBuffer->ref);
44879 }
44880 
44882 {
44883  return ma_audio_buffer_init_ex(pConfig, MA_FALSE, pAudioBuffer);
44884 }
44885 
44887 {
44888  return ma_audio_buffer_init_ex(pConfig, MA_TRUE, pAudioBuffer);
44889 }
44890 
44892 {
44893  ma_result result;
44894  ma_audio_buffer* pAudioBuffer;
44895  ma_audio_buffer_config innerConfig; /* We'll be making some changes to the config, so need to make a copy. */
44896  ma_uint64 allocationSizeInBytes;
44897 
44898  if (ppAudioBuffer == NULL) {
44899  return MA_INVALID_ARGS;
44900  }
44901 
44902  *ppAudioBuffer = NULL; /* Safety. */
44903 
44904  if (pConfig == NULL) {
44905  return MA_INVALID_ARGS;
44906  }
44907 
44908  innerConfig = *pConfig;
44910 
44911  allocationSizeInBytes = sizeof(*pAudioBuffer) - sizeof(pAudioBuffer->_pExtraData) + (pConfig->sizeInFrames * ma_get_bytes_per_frame(pConfig->format, pConfig->channels));
44912  if (allocationSizeInBytes > MA_SIZE_MAX) {
44913  return MA_OUT_OF_MEMORY; /* Too big. */
44914  }
44915 
44916  pAudioBuffer = (ma_audio_buffer*)ma__malloc_from_callbacks((size_t)allocationSizeInBytes, &innerConfig.allocationCallbacks); /* Safe cast to size_t. */
44917  if (pAudioBuffer == NULL) {
44918  return MA_OUT_OF_MEMORY;
44919  }
44920 
44921  if (pConfig->pData != NULL) {
44922  ma_copy_pcm_frames(&pAudioBuffer->_pExtraData[0], pConfig->pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
44923  } else {
44924  ma_silence_pcm_frames(&pAudioBuffer->_pExtraData[0], pConfig->sizeInFrames, pConfig->format, pConfig->channels);
44925  }
44926 
44927  innerConfig.pData = &pAudioBuffer->_pExtraData[0];
44928 
44929  result = ma_audio_buffer_init_ex(&innerConfig, MA_FALSE, pAudioBuffer);
44930  if (result != MA_SUCCESS) {
44931  ma__free_from_callbacks(pAudioBuffer, &innerConfig.allocationCallbacks);
44932  return result;
44933  }
44934 
44935  *ppAudioBuffer = pAudioBuffer;
44936 
44937  return MA_SUCCESS;
44938 }
44939 
44940 MA_API void ma_audio_buffer_uninit(ma_audio_buffer* pAudioBuffer)
44941 {
44942  ma_audio_buffer_uninit_ex(pAudioBuffer, MA_FALSE);
44943 }
44944 
44946 {
44947  ma_audio_buffer_uninit_ex(pAudioBuffer, MA_TRUE);
44948 }
44949 
44950 MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop)
44951 {
44952  if (pAudioBuffer == NULL) {
44953  return 0;
44954  }
44955 
44956  return ma_audio_buffer_ref_read_pcm_frames(&pAudioBuffer->ref, pFramesOut, frameCount, loop);
44957 }
44958 
44960 {
44961  if (pAudioBuffer == NULL) {
44962  return MA_INVALID_ARGS;
44963  }
44964 
44965  return ma_audio_buffer_ref_seek_to_pcm_frame(&pAudioBuffer->ref, frameIndex);
44966 }
44967 
44968 MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount)
44969 {
44970  if (ppFramesOut != NULL) {
44971  *ppFramesOut = NULL; /* Safety. */
44972  }
44973 
44974  if (pAudioBuffer == NULL) {
44975  if (pFrameCount != NULL) {
44976  *pFrameCount = 0;
44977  }
44978 
44979  return MA_INVALID_ARGS;
44980  }
44981 
44982  return ma_audio_buffer_ref_map(&pAudioBuffer->ref, ppFramesOut, pFrameCount);
44983 }
44984 
44986 {
44987  if (pAudioBuffer == NULL) {
44988  return MA_INVALID_ARGS;
44989  }
44990 
44991  return ma_audio_buffer_ref_unmap(&pAudioBuffer->ref, frameCount);
44992 }
44993 
44995 {
44996  if (pAudioBuffer == NULL) {
44997  return MA_FALSE;
44998  }
44999 
45000  return ma_audio_buffer_ref_at_end(&pAudioBuffer->ref);
45001 }
45002 
45004 {
45005  if (pAudioBuffer == NULL) {
45006  return MA_INVALID_ARGS;
45007  }
45008 
45009  return ma_audio_buffer_ref_get_cursor_in_pcm_frames(&pAudioBuffer->ref, pCursor);
45010 }
45011 
45013 {
45014  if (pAudioBuffer == NULL) {
45015  return MA_INVALID_ARGS;
45016  }
45017 
45018  return ma_audio_buffer_ref_get_length_in_pcm_frames(&pAudioBuffer->ref, pLength);
45019 }
45020 
45021 MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames)
45022 {
45023  if (pAvailableFrames == NULL) {
45024  return MA_INVALID_ARGS;
45025  }
45026 
45027  *pAvailableFrames = 0;
45028 
45029  if (pAudioBuffer == NULL) {
45030  return MA_INVALID_ARGS;
45031  }
45032 
45033  return ma_audio_buffer_ref_get_available_frames(&pAudioBuffer->ref, pAvailableFrames);
45034 }
45035 
45036 
45037 
45038 /**************************************************************************************************************************************************************
45039 
45040 VFS
45041 
45042 **************************************************************************************************************************************************************/
45043 MA_API ma_result ma_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45044 {
45045  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45046 
45047  if (pFile == NULL) {
45048  return MA_INVALID_ARGS;
45049  }
45050 
45051  *pFile = NULL;
45052 
45053  if (pVFS == NULL || pFilePath == NULL || openMode == 0) {
45054  return MA_INVALID_ARGS;
45055  }
45056 
45057  if (pCallbacks->onOpen == NULL) {
45058  return MA_NOT_IMPLEMENTED;
45059  }
45060 
45061  return pCallbacks->onOpen(pVFS, pFilePath, openMode, pFile);
45062 }
45063 
45064 MA_API ma_result ma_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45065 {
45066  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45067 
45068  if (pFile == NULL) {
45069  return MA_INVALID_ARGS;
45070  }
45071 
45072  *pFile = NULL;
45073 
45074  if (pVFS == NULL || pFilePath == NULL || openMode == 0) {
45075  return MA_INVALID_ARGS;
45076  }
45077 
45078  if (pCallbacks->onOpenW == NULL) {
45079  return MA_NOT_IMPLEMENTED;
45080  }
45081 
45082  return pCallbacks->onOpenW(pVFS, pFilePath, openMode, pFile);
45083 }
45084 
45086 {
45087  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45088 
45089  if (pVFS == NULL || file == NULL) {
45090  return MA_INVALID_ARGS;
45091  }
45092 
45093  if (pCallbacks->onClose == NULL) {
45094  return MA_NOT_IMPLEMENTED;
45095  }
45096 
45097  return pCallbacks->onClose(pVFS, file);
45098 }
45099 
45100 MA_API ma_result ma_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
45101 {
45102  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45103 
45104  if (pBytesRead != NULL) {
45105  *pBytesRead = 0;
45106  }
45107 
45108  if (pVFS == NULL || file == NULL || pDst == NULL) {
45109  return MA_INVALID_ARGS;
45110  }
45111 
45112  if (pCallbacks->onRead == NULL) {
45113  return MA_NOT_IMPLEMENTED;
45114  }
45115 
45116  return pCallbacks->onRead(pVFS, file, pDst, sizeInBytes, pBytesRead);
45117 }
45118 
45119 MA_API ma_result ma_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
45120 {
45121  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45122 
45123  if (pBytesWritten != NULL) {
45124  *pBytesWritten = 0;
45125  }
45126 
45127  if (pVFS == NULL || file == NULL || pSrc == NULL) {
45128  return MA_INVALID_ARGS;
45129  }
45130 
45131  if (pCallbacks->onWrite == NULL) {
45132  return MA_NOT_IMPLEMENTED;
45133  }
45134 
45135  return pCallbacks->onWrite(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
45136 }
45137 
45139 {
45140  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45141 
45142  if (pVFS == NULL || file == NULL) {
45143  return MA_INVALID_ARGS;
45144  }
45145 
45146  if (pCallbacks->onSeek == NULL) {
45147  return MA_NOT_IMPLEMENTED;
45148  }
45149 
45150  return pCallbacks->onSeek(pVFS, file, offset, origin);
45151 }
45152 
45153 MA_API ma_result ma_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
45154 {
45155  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45156 
45157  if (pCursor == NULL) {
45158  return MA_INVALID_ARGS;
45159  }
45160 
45161  *pCursor = 0;
45162 
45163  if (pVFS == NULL || file == NULL) {
45164  return MA_INVALID_ARGS;
45165  }
45166 
45167  if (pCallbacks->onTell == NULL) {
45168  return MA_NOT_IMPLEMENTED;
45169  }
45170 
45171  return pCallbacks->onTell(pVFS, file, pCursor);
45172 }
45173 
45175 {
45176  ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
45177 
45178  if (pInfo == NULL) {
45179  return MA_INVALID_ARGS;
45180  }
45181 
45182  MA_ZERO_OBJECT(pInfo);
45183 
45184  if (pVFS == NULL || file == NULL) {
45185  return MA_INVALID_ARGS;
45186  }
45187 
45188  if (pCallbacks->onInfo == NULL) {
45189  return MA_NOT_IMPLEMENTED;
45190  }
45191 
45192  return pCallbacks->onInfo(pVFS, file, pInfo);
45193 }
45194 
45195 
45196 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)
45197 {
45198  ma_result result;
45199  ma_vfs_file file;
45200  ma_file_info info;
45201  void* pData;
45202  size_t bytesRead;
45203 
45204  (void)allocationType;
45205 
45206  if (ppData != NULL) {
45207  *ppData = NULL;
45208  }
45209  if (pSize != NULL) {
45210  *pSize = 0;
45211  }
45212 
45213  if (ppData == NULL) {
45214  return MA_INVALID_ARGS;
45215  }
45216 
45217  if (pFilePath != NULL) {
45218  result = ma_vfs_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
45219  } else {
45220  result = ma_vfs_open_w(pVFS, pFilePathW, MA_OPEN_MODE_READ, &file);
45221  }
45222  if (result != MA_SUCCESS) {
45223  return result;
45224  }
45225 
45226  result = ma_vfs_info(pVFS, file, &info);
45227  if (result != MA_SUCCESS) {
45228  ma_vfs_close(pVFS, file);
45229  return result;
45230  }
45231 
45232  if (info.sizeInBytes > MA_SIZE_MAX) {
45233  ma_vfs_close(pVFS, file);
45234  return MA_TOO_BIG;
45235  }
45236 
45237  pData = ma__malloc_from_callbacks((size_t)info.sizeInBytes, pAllocationCallbacks); /* Safe cast. */
45238  if (pData == NULL) {
45239  ma_vfs_close(pVFS, file);
45240  return result;
45241  }
45242 
45243  result = ma_vfs_read(pVFS, file, pData, (size_t)info.sizeInBytes, &bytesRead); /* Safe cast. */
45244  ma_vfs_close(pVFS, file);
45245 
45246  if (result != MA_SUCCESS) {
45247  ma__free_from_callbacks(pData, pAllocationCallbacks);
45248  return result;
45249  }
45250 
45251  if (pSize != NULL) {
45252  *pSize = bytesRead;
45253  }
45254 
45255  MA_ASSERT(ppData != NULL);
45256  *ppData = pData;
45257 
45258  return MA_SUCCESS;
45259 }
45260 
45261 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)
45262 {
45263  return ma_vfs_open_and_read_file_ex(pVFS, pFilePath, NULL, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/);
45264 }
45265 
45266 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)
45267 {
45268  return ma_vfs_open_and_read_file_ex(pVFS, NULL, pFilePath, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/);
45269 }
45270 
45271 
45272 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45273 static void ma_default_vfs__get_open_settings_win32(ma_uint32 openMode, DWORD* pDesiredAccess, DWORD* pShareMode, DWORD* pCreationDisposition)
45274 {
45275  *pDesiredAccess = 0;
45276  if ((openMode & MA_OPEN_MODE_READ) != 0) {
45277  *pDesiredAccess |= GENERIC_READ;
45278  }
45279  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
45280  *pDesiredAccess |= GENERIC_WRITE;
45281  }
45282 
45283  *pShareMode = 0;
45284  if ((openMode & MA_OPEN_MODE_READ) != 0) {
45285  *pShareMode |= FILE_SHARE_READ;
45286  }
45287 
45288  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
45289  *pCreationDisposition = CREATE_ALWAYS; /* Opening in write mode. Truncate. */
45290  } else {
45291  *pCreationDisposition = OPEN_EXISTING; /* Opening in read mode. File must exist. */
45292  }
45293 }
45294 
45295 static ma_result ma_default_vfs_open__win32(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45296 {
45297  HANDLE hFile;
45298  DWORD dwDesiredAccess;
45299  DWORD dwShareMode;
45300  DWORD dwCreationDisposition;
45301 
45302  (void)pVFS;
45303 
45304  ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
45305 
45306  hFile = CreateFileA(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
45307  if (hFile == INVALID_HANDLE_VALUE) {
45308  return ma_result_from_GetLastError(GetLastError());
45309  }
45310 
45311  *pFile = hFile;
45312  return MA_SUCCESS;
45313 }
45314 
45315 static ma_result ma_default_vfs_open_w__win32(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45316 {
45317  HANDLE hFile;
45318  DWORD dwDesiredAccess;
45319  DWORD dwShareMode;
45320  DWORD dwCreationDisposition;
45321 
45322  (void)pVFS;
45323 
45324  ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
45325 
45326  hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
45327  if (hFile == INVALID_HANDLE_VALUE) {
45328  return ma_result_from_GetLastError(GetLastError());
45329  }
45330 
45331  *pFile = hFile;
45332  return MA_SUCCESS;
45333 }
45334 
45335 static ma_result ma_default_vfs_close__win32(ma_vfs* pVFS, ma_vfs_file file)
45336 {
45337  (void)pVFS;
45338 
45339  if (CloseHandle((HANDLE)file) == 0) {
45340  return ma_result_from_GetLastError(GetLastError());
45341  }
45342 
45343  return MA_SUCCESS;
45344 }
45345 
45346 
45347 static ma_result ma_default_vfs_read__win32(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
45348 {
45349  ma_result result = MA_SUCCESS;
45350  size_t totalBytesRead;
45351 
45352  (void)pVFS;
45353 
45354  totalBytesRead = 0;
45355  while (totalBytesRead < sizeInBytes) {
45356  size_t bytesRemaining;
45357  DWORD bytesToRead;
45358  DWORD bytesRead;
45359  BOOL readResult;
45360 
45361  bytesRemaining = sizeInBytes - totalBytesRead;
45362  if (bytesRemaining >= 0xFFFFFFFF) {
45363  bytesToRead = 0xFFFFFFFF;
45364  } else {
45365  bytesToRead = (DWORD)bytesRemaining;
45366  }
45367 
45368  readResult = ReadFile((HANDLE)file, ma_offset_ptr(pDst, totalBytesRead), bytesToRead, &bytesRead, NULL);
45369  if (readResult == 1 && bytesRead == 0) {
45370  result = MA_AT_END;
45371  break; /* EOF */
45372  }
45373 
45374  totalBytesRead += bytesRead;
45375 
45376  if (bytesRead < bytesToRead) {
45377  break; /* EOF */
45378  }
45379 
45380  if (readResult == 0) {
45381  result = ma_result_from_GetLastError(GetLastError());
45382  break;
45383  }
45384  }
45385 
45386  if (pBytesRead != NULL) {
45387  *pBytesRead = totalBytesRead;
45388  }
45389 
45390  return result;
45391 }
45392 
45393 static ma_result ma_default_vfs_write__win32(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
45394 {
45395  ma_result result = MA_SUCCESS;
45396  size_t totalBytesWritten;
45397 
45398  (void)pVFS;
45399 
45400  totalBytesWritten = 0;
45401  while (totalBytesWritten < sizeInBytes) {
45402  size_t bytesRemaining;
45403  DWORD bytesToWrite;
45404  DWORD bytesWritten;
45405  BOOL writeResult;
45406 
45407  bytesRemaining = sizeInBytes - totalBytesWritten;
45408  if (bytesRemaining >= 0xFFFFFFFF) {
45409  bytesToWrite = 0xFFFFFFFF;
45410  } else {
45411  bytesToWrite = (DWORD)bytesRemaining;
45412  }
45413 
45414  writeResult = WriteFile((HANDLE)file, ma_offset_ptr(pSrc, totalBytesWritten), bytesToWrite, &bytesWritten, NULL);
45415  totalBytesWritten += bytesWritten;
45416 
45417  if (writeResult == 0) {
45418  result = ma_result_from_GetLastError(GetLastError());
45419  break;
45420  }
45421  }
45422 
45423  if (pBytesWritten != NULL) {
45424  *pBytesWritten = totalBytesWritten;
45425  }
45426 
45427  return result;
45428 }
45429 
45430 
45431 static ma_result ma_default_vfs_seek__win32(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
45432 {
45433  LARGE_INTEGER liDistanceToMove;
45434  DWORD dwMoveMethod;
45435  BOOL result;
45436 
45437  (void)pVFS;
45438 
45439  liDistanceToMove.QuadPart = offset;
45440 
45441  /* */ if (origin == ma_seek_origin_current) {
45442  dwMoveMethod = FILE_CURRENT;
45443  } else if (origin == ma_seek_origin_end) {
45444  dwMoveMethod = FILE_END;
45445  } else {
45446  dwMoveMethod = FILE_BEGIN;
45447  }
45448 
45449 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__DMC__)
45450  /* No SetFilePointerEx() so restrict to 31 bits. */
45451  if (origin > 0x7FFFFFFF) {
45452  return MA_OUT_OF_RANGE;
45453  }
45454 
45455  result = SetFilePointer((HANDLE)file, (LONG)liDistanceToMove.QuadPart, NULL, dwMoveMethod);
45456 #else
45457  result = SetFilePointerEx((HANDLE)file, liDistanceToMove, NULL, dwMoveMethod);
45458 #endif
45459  if (result == 0) {
45460  return ma_result_from_GetLastError(GetLastError());
45461  }
45462 
45463  return MA_SUCCESS;
45464 }
45465 
45466 static ma_result ma_default_vfs_tell__win32(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
45467 {
45468  LARGE_INTEGER liZero;
45469  LARGE_INTEGER liTell;
45470  BOOL result;
45471 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__DMC__)
45472  LONG tell;
45473 #endif
45474 
45475  (void)pVFS;
45476 
45477  liZero.QuadPart = 0;
45478 
45479 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__DMC__)
45480  result = SetFilePointer((HANDLE)file, (LONG)liZero.QuadPart, &tell, FILE_CURRENT);
45481  liTell.QuadPart = tell;
45482 #else
45483  result = SetFilePointerEx((HANDLE)file, liZero, &liTell, FILE_CURRENT);
45484 #endif
45485  if (result == 0) {
45486  return ma_result_from_GetLastError(GetLastError());
45487  }
45488 
45489  if (pCursor != NULL) {
45490  *pCursor = liTell.QuadPart;
45491  }
45492 
45493  return MA_SUCCESS;
45494 }
45495 
45496 static ma_result ma_default_vfs_info__win32(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
45497 {
45498  BY_HANDLE_FILE_INFORMATION fi;
45499  BOOL result;
45500 
45501  (void)pVFS;
45502 
45503  result = GetFileInformationByHandle((HANDLE)file, &fi);
45504  if (result == 0) {
45505  return ma_result_from_GetLastError(GetLastError());
45506  }
45507 
45508  pInfo->sizeInBytes = ((ma_uint64)fi.nFileSizeHigh << 32) | ((ma_uint64)fi.nFileSizeLow);
45509 
45510  return MA_SUCCESS;
45511 }
45512 #else
45513 static ma_result ma_default_vfs_open__stdio(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45514 {
45515  ma_result result;
45516  FILE* pFileStd;
45517  const char* pOpenModeStr;
45518 
45519  MA_ASSERT(pFilePath != NULL);
45520  MA_ASSERT(openMode != 0);
45521  MA_ASSERT(pFile != NULL);
45522 
45523  (void)pVFS;
45524 
45525  if ((openMode & MA_OPEN_MODE_READ) != 0) {
45526  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
45527  pOpenModeStr = "r+";
45528  } else {
45529  pOpenModeStr = "rb";
45530  }
45531  } else {
45532  pOpenModeStr = "wb";
45533  }
45534 
45535  result = ma_fopen(&pFileStd, pFilePath, pOpenModeStr);
45536  if (result != MA_SUCCESS) {
45537  return result;
45538  }
45539 
45540  *pFile = pFileStd;
45541 
45542  return MA_SUCCESS;
45543 }
45544 
45545 static ma_result ma_default_vfs_open_w__stdio(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45546 {
45547  ma_result result;
45548  FILE* pFileStd;
45549  const wchar_t* pOpenModeStr;
45550 
45551  MA_ASSERT(pFilePath != NULL);
45552  MA_ASSERT(openMode != 0);
45553  MA_ASSERT(pFile != NULL);
45554 
45555  (void)pVFS;
45556 
45557  if ((openMode & MA_OPEN_MODE_READ) != 0) {
45558  if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
45559  pOpenModeStr = L"r+";
45560  } else {
45561  pOpenModeStr = L"rb";
45562  }
45563  } else {
45564  pOpenModeStr = L"wb";
45565  }
45566 
45567  result = ma_wfopen(&pFileStd, pFilePath, pOpenModeStr, (pVFS != NULL) ? &((ma_default_vfs*)pVFS)->allocationCallbacks : NULL);
45568  if (result != MA_SUCCESS) {
45569  return result;
45570  }
45571 
45572  *pFile = pFileStd;
45573 
45574  return MA_SUCCESS;
45575 }
45576 
45578 {
45579  MA_ASSERT(file != NULL);
45580 
45581  (void)pVFS;
45582 
45583  fclose((FILE*)file);
45584 
45585  return MA_SUCCESS;
45586 }
45587 
45588 static ma_result ma_default_vfs_read__stdio(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
45589 {
45590  size_t result;
45591 
45592  MA_ASSERT(file != NULL);
45593  MA_ASSERT(pDst != NULL);
45594 
45595  (void)pVFS;
45596 
45597  result = fread(pDst, 1, sizeInBytes, (FILE*)file);
45598 
45599  if (pBytesRead != NULL) {
45600  *pBytesRead = result;
45601  }
45602 
45603  if (result != sizeInBytes) {
45604  if (result == 0 && feof((FILE*)file)) {
45605  return MA_AT_END;
45606  } else {
45607  return ma_result_from_errno(ferror((FILE*)file));
45608  }
45609  }
45610 
45611  return MA_SUCCESS;
45612 }
45613 
45614 static ma_result ma_default_vfs_write__stdio(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
45615 {
45616  size_t result;
45617 
45618  MA_ASSERT(file != NULL);
45619  MA_ASSERT(pSrc != NULL);
45620 
45621  (void)pVFS;
45622 
45623  result = fwrite(pSrc, 1, sizeInBytes, (FILE*)file);
45624 
45625  if (pBytesWritten != NULL) {
45626  *pBytesWritten = result;
45627  }
45628 
45629  if (result != sizeInBytes) {
45630  return ma_result_from_errno(ferror((FILE*)file));
45631  }
45632 
45633  return MA_SUCCESS;
45634 }
45635 
45637 {
45638  int result;
45639  int whence;
45640 
45641  MA_ASSERT(file != NULL);
45642 
45643  (void)pVFS;
45644 
45645  if (origin == ma_seek_origin_start) {
45646  whence = SEEK_SET;
45647  } else if (origin == ma_seek_origin_end) {
45648  whence = SEEK_END;
45649  } else {
45650  whence = SEEK_CUR;
45651  }
45652 
45653 #if defined(_WIN32)
45654  #if defined(_MSC_VER) && _MSC_VER > 1200
45655  result = _fseeki64((FILE*)file, offset, whence);
45656  #else
45657  /* No _fseeki64() so restrict to 31 bits. */
45658  if (origin > 0x7FFFFFFF) {
45659  return MA_OUT_OF_RANGE;
45660  }
45661 
45662  result = fseek((FILE*)file, (int)offset, whence);
45663  #endif
45664 #else
45665  result = fseek((FILE*)file, (long int)offset, whence);
45666 #endif
45667  if (result != 0) {
45668  return MA_ERROR;
45669  }
45670 
45671  return MA_SUCCESS;
45672 }
45673 
45674 static ma_result ma_default_vfs_tell__stdio(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
45675 {
45676  ma_int64 result;
45677 
45678  MA_ASSERT(file != NULL);
45679  MA_ASSERT(pCursor != NULL);
45680 
45681  (void)pVFS;
45682 
45683 #if defined(_WIN32)
45684  #if defined(_MSC_VER) && _MSC_VER > 1200
45685  result = _ftelli64((FILE*)file);
45686  #else
45687  result = ftell((FILE*)file);
45688  #endif
45689 #else
45690  result = ftell((FILE*)file);
45691 #endif
45692 
45693  *pCursor = result;
45694 
45695  return MA_SUCCESS;
45696 }
45697 
45698 #if !defined(_MSC_VER) && !((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)) && !defined(MA_BSD)
45699 int fileno(FILE *stream);
45700 #endif
45701 
45703 {
45704  int fd;
45705  struct stat info;
45706 
45707  MA_ASSERT(file != NULL);
45708  MA_ASSERT(pInfo != NULL);
45709 
45710  (void)pVFS;
45711 
45712 #if defined(_MSC_VER)
45713  fd = _fileno((FILE*)file);
45714 #else
45715  fd = fileno((FILE*)file);
45716 #endif
45717 
45718  if (fstat(fd, &info) != 0) {
45719  return ma_result_from_errno(errno);
45720  }
45721 
45722  pInfo->sizeInBytes = info.st_size;
45723 
45724  return MA_SUCCESS;
45725 }
45726 #endif
45727 
45728 
45729 static ma_result ma_default_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45730 {
45731  if (pFile == NULL) {
45732  return MA_INVALID_ARGS;
45733  }
45734 
45735  *pFile = NULL;
45736 
45737  if (pFilePath == NULL || openMode == 0) {
45738  return MA_INVALID_ARGS;
45739  }
45740 
45741 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45742  return ma_default_vfs_open__win32(pVFS, pFilePath, openMode, pFile);
45743 #else
45744  return ma_default_vfs_open__stdio(pVFS, pFilePath, openMode, pFile);
45745 #endif
45746 }
45747 
45748 static ma_result ma_default_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45749 {
45750  if (pFile == NULL) {
45751  return MA_INVALID_ARGS;
45752  }
45753 
45754  *pFile = NULL;
45755 
45756  if (pFilePath == NULL || openMode == 0) {
45757  return MA_INVALID_ARGS;
45758  }
45759 
45760 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45761  return ma_default_vfs_open_w__win32(pVFS, pFilePath, openMode, pFile);
45762 #else
45763  return ma_default_vfs_open_w__stdio(pVFS, pFilePath, openMode, pFile);
45764 #endif
45765 }
45766 
45768 {
45769  if (file == NULL) {
45770  return MA_INVALID_ARGS;
45771  }
45772 
45773 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45774  return ma_default_vfs_close__win32(pVFS, file);
45775 #else
45776  return ma_default_vfs_close__stdio(pVFS, file);
45777 #endif
45778 }
45779 
45780 static ma_result ma_default_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
45781 {
45782  if (pBytesRead != NULL) {
45783  *pBytesRead = 0;
45784  }
45785 
45786  if (file == NULL || pDst == NULL) {
45787  return MA_INVALID_ARGS;
45788  }
45789 
45790 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45791  return ma_default_vfs_read__win32(pVFS, file, pDst, sizeInBytes, pBytesRead);
45792 #else
45793  return ma_default_vfs_read__stdio(pVFS, file, pDst, sizeInBytes, pBytesRead);
45794 #endif
45795 }
45796 
45797 static ma_result ma_default_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
45798 {
45799  if (pBytesWritten != NULL) {
45800  *pBytesWritten = 0;
45801  }
45802 
45803  if (file == NULL || pSrc == NULL) {
45804  return MA_INVALID_ARGS;
45805  }
45806 
45807 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45808  return ma_default_vfs_write__win32(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
45809 #else
45810  return ma_default_vfs_write__stdio(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
45811 #endif
45812 }
45813 
45814 static ma_result ma_default_vfs_seek(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
45815 {
45816  if (file == NULL) {
45817  return MA_INVALID_ARGS;
45818  }
45819 
45820 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45821  return ma_default_vfs_seek__win32(pVFS, file, offset, origin);
45822 #else
45823  return ma_default_vfs_seek__stdio(pVFS, file, offset, origin);
45824 #endif
45825 }
45826 
45827 static ma_result ma_default_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
45828 {
45829  if (pCursor == NULL) {
45830  return MA_INVALID_ARGS;
45831  }
45832 
45833  *pCursor = 0;
45834 
45835  if (file == NULL) {
45836  return MA_INVALID_ARGS;
45837  }
45838 
45839 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45840  return ma_default_vfs_tell__win32(pVFS, file, pCursor);
45841 #else
45842  return ma_default_vfs_tell__stdio(pVFS, file, pCursor);
45843 #endif
45844 }
45845 
45846 static ma_result ma_default_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
45847 {
45848  if (pInfo == NULL) {
45849  return MA_INVALID_ARGS;
45850  }
45851 
45852  MA_ZERO_OBJECT(pInfo);
45853 
45854  if (file == NULL) {
45855  return MA_INVALID_ARGS;
45856  }
45857 
45858 #if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
45859  return ma_default_vfs_info__win32(pVFS, file, pInfo);
45860 #else
45861  return ma_default_vfs_info__stdio(pVFS, file, pInfo);
45862 #endif
45863 }
45864 
45865 
45867 {
45868  if (pVFS == NULL) {
45869  return MA_INVALID_ARGS;
45870  }
45871 
45872  pVFS->cb.onOpen = ma_default_vfs_open;
45875  pVFS->cb.onRead = ma_default_vfs_read;
45877  pVFS->cb.onSeek = ma_default_vfs_seek;
45878  pVFS->cb.onTell = ma_default_vfs_tell;
45879  pVFS->cb.onInfo = ma_default_vfs_info;
45880  ma_allocation_callbacks_init_copy(&pVFS->allocationCallbacks, pAllocationCallbacks);
45881 
45882  return MA_SUCCESS;
45883 }
45884 
45885 
45886 MA_API ma_result ma_vfs_or_default_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45887 {
45888  if (pVFS != NULL) {
45889  return ma_vfs_open(pVFS, pFilePath, openMode, pFile);
45890  } else {
45891  return ma_default_vfs_open(pVFS, pFilePath, openMode, pFile);
45892  }
45893 }
45894 
45895 MA_API ma_result ma_vfs_or_default_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
45896 {
45897  if (pVFS != NULL) {
45898  return ma_vfs_open_w(pVFS, pFilePath, openMode, pFile);
45899  } else {
45900  return ma_default_vfs_open_w(pVFS, pFilePath, openMode, pFile);
45901  }
45902 }
45903 
45905 {
45906  if (pVFS != NULL) {
45907  return ma_vfs_close(pVFS, file);
45908  } else {
45909  return ma_default_vfs_close(pVFS, file);
45910  }
45911 }
45912 
45913 MA_API ma_result ma_vfs_or_default_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
45914 {
45915  if (pVFS != NULL) {
45916  return ma_vfs_read(pVFS, file, pDst, sizeInBytes, pBytesRead);
45917  } else {
45918  return ma_default_vfs_read(pVFS, file, pDst, sizeInBytes, pBytesRead);
45919  }
45920 }
45921 
45922 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)
45923 {
45924  if (pVFS != NULL) {
45925  return ma_vfs_write(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
45926  } else {
45927  return ma_default_vfs_write(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
45928  }
45929 }
45930 
45932 {
45933  if (pVFS != NULL) {
45934  return ma_vfs_seek(pVFS, file, offset, origin);
45935  } else {
45936  return ma_default_vfs_seek(pVFS, file, offset, origin);
45937  }
45938 }
45939 
45941 {
45942  if (pVFS != NULL) {
45943  return ma_vfs_tell(pVFS, file, pCursor);
45944  } else {
45945  return ma_default_vfs_tell(pVFS, file, pCursor);
45946  }
45947 }
45948 
45950 {
45951  if (pVFS != NULL) {
45952  return ma_vfs_info(pVFS, file, pInfo);
45953  } else {
45954  return ma_default_vfs_info(pVFS, file, pInfo);
45955  }
45956 }
45957 
45958 
45959 
45960 /**************************************************************************************************************************************************************
45961 
45962 Decoding and Encoding Headers. These are auto-generated from a tool.
45963 
45964 **************************************************************************************************************************************************************/
45965 #if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING))
45966 /* dr_wav_h begin */
45967 #ifndef dr_wav_h
45968 #define dr_wav_h
45969 #ifdef __cplusplus
45970 extern "C" {
45971 #endif
45972 #define DRWAV_STRINGIFY(x) #x
45973 #define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
45974 #define DRWAV_VERSION_MAJOR 0
45975 #define DRWAV_VERSION_MINOR 13
45976 #define DRWAV_VERSION_REVISION 1
45977 #define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
45978 #include <stddef.h>
45979 typedef signed char drwav_int8;
45980 typedef unsigned char drwav_uint8;
45981 typedef signed short drwav_int16;
45982 typedef unsigned short drwav_uint16;
45983 typedef signed int drwav_int32;
45984 typedef unsigned int drwav_uint32;
45985 #if defined(_MSC_VER) && !defined(__clang__)
45986  typedef signed __int64 drwav_int64;
45987  typedef unsigned __int64 drwav_uint64;
45988 #else
45989  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
45990  #pragma GCC diagnostic push
45991  #pragma GCC diagnostic ignored "-Wlong-long"
45992  #if defined(__clang__)
45993  #pragma GCC diagnostic ignored "-Wc++11-long-long"
45994  #endif
45995  #endif
45996  typedef signed long long drwav_int64;
45997  typedef unsigned long long drwav_uint64;
45998  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
45999  #pragma GCC diagnostic pop
46000  #endif
46001 #endif
46002 #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__)
46003  typedef drwav_uint64 drwav_uintptr;
46004 #else
46005  typedef drwav_uint32 drwav_uintptr;
46006 #endif
46007 typedef drwav_uint8 drwav_bool8;
46008 typedef drwav_uint32 drwav_bool32;
46009 #define DRWAV_TRUE 1
46010 #define DRWAV_FALSE 0
46011 #if !defined(DRWAV_API)
46012  #if defined(DRWAV_DLL)
46013  #if defined(_WIN32)
46014  #define DRWAV_DLL_IMPORT __declspec(dllimport)
46015  #define DRWAV_DLL_EXPORT __declspec(dllexport)
46016  #define DRWAV_DLL_PRIVATE static
46017  #else
46018  #if defined(__GNUC__) && __GNUC__ >= 4
46019  #define DRWAV_DLL_IMPORT __attribute__((visibility("default")))
46020  #define DRWAV_DLL_EXPORT __attribute__((visibility("default")))
46021  #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
46022  #else
46023  #define DRWAV_DLL_IMPORT
46024  #define DRWAV_DLL_EXPORT
46025  #define DRWAV_DLL_PRIVATE static
46026  #endif
46027  #endif
46028  #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
46029  #define DRWAV_API DRWAV_DLL_EXPORT
46030  #else
46031  #define DRWAV_API DRWAV_DLL_IMPORT
46032  #endif
46033  #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
46034  #else
46035  #define DRWAV_API extern
46036  #define DRWAV_PRIVATE static
46037  #endif
46038 #endif
46039 typedef drwav_int32 drwav_result;
46040 #define DRWAV_SUCCESS 0
46041 #define DRWAV_ERROR -1
46042 #define DRWAV_INVALID_ARGS -2
46043 #define DRWAV_INVALID_OPERATION -3
46044 #define DRWAV_OUT_OF_MEMORY -4
46045 #define DRWAV_OUT_OF_RANGE -5
46046 #define DRWAV_ACCESS_DENIED -6
46047 #define DRWAV_DOES_NOT_EXIST -7
46048 #define DRWAV_ALREADY_EXISTS -8
46049 #define DRWAV_TOO_MANY_OPEN_FILES -9
46050 #define DRWAV_INVALID_FILE -10
46051 #define DRWAV_TOO_BIG -11
46052 #define DRWAV_PATH_TOO_LONG -12
46053 #define DRWAV_NAME_TOO_LONG -13
46054 #define DRWAV_NOT_DIRECTORY -14
46055 #define DRWAV_IS_DIRECTORY -15
46056 #define DRWAV_DIRECTORY_NOT_EMPTY -16
46057 #define DRWAV_END_OF_FILE -17
46058 #define DRWAV_NO_SPACE -18
46059 #define DRWAV_BUSY -19
46060 #define DRWAV_IO_ERROR -20
46061 #define DRWAV_INTERRUPT -21
46062 #define DRWAV_UNAVAILABLE -22
46063 #define DRWAV_ALREADY_IN_USE -23
46064 #define DRWAV_BAD_ADDRESS -24
46065 #define DRWAV_BAD_SEEK -25
46066 #define DRWAV_BAD_PIPE -26
46067 #define DRWAV_DEADLOCK -27
46068 #define DRWAV_TOO_MANY_LINKS -28
46069 #define DRWAV_NOT_IMPLEMENTED -29
46070 #define DRWAV_NO_MESSAGE -30
46071 #define DRWAV_BAD_MESSAGE -31
46072 #define DRWAV_NO_DATA_AVAILABLE -32
46073 #define DRWAV_INVALID_DATA -33
46074 #define DRWAV_TIMEOUT -34
46075 #define DRWAV_NO_NETWORK -35
46076 #define DRWAV_NOT_UNIQUE -36
46077 #define DRWAV_NOT_SOCKET -37
46078 #define DRWAV_NO_ADDRESS -38
46079 #define DRWAV_BAD_PROTOCOL -39
46080 #define DRWAV_PROTOCOL_UNAVAILABLE -40
46081 #define DRWAV_PROTOCOL_NOT_SUPPORTED -41
46082 #define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
46083 #define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED -43
46084 #define DRWAV_SOCKET_NOT_SUPPORTED -44
46085 #define DRWAV_CONNECTION_RESET -45
46086 #define DRWAV_ALREADY_CONNECTED -46
46087 #define DRWAV_NOT_CONNECTED -47
46088 #define DRWAV_CONNECTION_REFUSED -48
46089 #define DRWAV_NO_HOST -49
46090 #define DRWAV_IN_PROGRESS -50
46091 #define DRWAV_CANCELLED -51
46092 #define DRWAV_MEMORY_ALREADY_MAPPED -52
46093 #define DRWAV_AT_END -53
46094 #define DR_WAVE_FORMAT_PCM 0x1
46095 #define DR_WAVE_FORMAT_ADPCM 0x2
46096 #define DR_WAVE_FORMAT_IEEE_FLOAT 0x3
46097 #define DR_WAVE_FORMAT_ALAW 0x6
46098 #define DR_WAVE_FORMAT_MULAW 0x7
46099 #define DR_WAVE_FORMAT_DVI_ADPCM 0x11
46100 #define DR_WAVE_FORMAT_EXTENSIBLE 0xFFFE
46101 #define DRWAV_SEQUENTIAL 0x00000001
46102 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
46103 DRWAV_API const char* drwav_version_string(void);
46104 typedef enum
46105 {
46109 typedef enum
46110 {
46114 } drwav_container;
46115 typedef struct
46116 {
46117  union
46118  {
46119  drwav_uint8 fourcc[4];
46120  drwav_uint8 guid[16];
46121  } id;
46122  drwav_uint64 sizeInBytes;
46123  unsigned int paddingSize;
46125 typedef struct
46126 {
46127  drwav_uint16 formatTag;
46128  drwav_uint16 channels;
46129  drwav_uint32 sampleRate;
46130  drwav_uint32 avgBytesPerSec;
46131  drwav_uint16 blockAlign;
46132  drwav_uint16 bitsPerSample;
46133  drwav_uint16 extendedSize;
46134  drwav_uint16 validBitsPerSample;
46135  drwav_uint32 channelMask;
46136  drwav_uint8 subFormat[16];
46137 } drwav_fmt;
46139 typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
46140 typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
46141 typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
46142 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);
46143 typedef struct
46144 {
46145  void* pUserData;
46146  void* (* onMalloc)(size_t sz, void* pUserData);
46147  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
46148  void (* onFree)(void* p, void* pUserData);
46150 typedef struct
46151 {
46152  const drwav_uint8* data;
46153  size_t dataSize;
46154  size_t currentReadPos;
46156 typedef struct
46157 {
46158  void** ppData;
46159  size_t* pDataSize;
46160  size_t dataSize;
46161  size_t dataCapacity;
46162  size_t currentWritePos;
46164 typedef struct
46165 {
46166  drwav_container container;
46167  drwav_uint32 format;
46168  drwav_uint32 channels;
46169  drwav_uint32 sampleRate;
46170  drwav_uint32 bitsPerSample;
46172 typedef enum
46173 {
46175  drwav_metadata_type_unknown = 1 << 0,
46176  drwav_metadata_type_smpl = 1 << 1,
46177  drwav_metadata_type_inst = 1 << 2,
46178  drwav_metadata_type_cue = 1 << 3,
46179  drwav_metadata_type_acid = 1 << 4,
46180  drwav_metadata_type_bext = 1 << 5,
46208 typedef enum
46209 {
46214 typedef struct
46215 {
46216  drwav_uint32 cuePointId;
46217  drwav_uint32 type;
46218  drwav_uint32 firstSampleByteOffset;
46219  drwav_uint32 lastSampleByteOffset;
46220  drwav_uint32 sampleFraction;
46221  drwav_uint32 playCount;
46222 } drwav_smpl_loop;
46223 typedef struct
46224 {
46225  drwav_uint32 manufacturerId;
46226  drwav_uint32 productId;
46227  drwav_uint32 samplePeriodNanoseconds;
46228  drwav_uint32 midiUnityNote;
46229  drwav_uint32 midiPitchFraction;
46230  drwav_uint32 smpteFormat;
46231  drwav_uint32 smpteOffset;
46232  drwav_uint32 sampleLoopCount;
46233  drwav_uint32 samplerSpecificDataSizeInBytes;
46234  drwav_smpl_loop* pLoops;
46235  drwav_uint8* pSamplerSpecificData;
46236 } drwav_smpl;
46237 typedef struct
46238 {
46239  drwav_int8 midiUnityNote;
46240  drwav_int8 fineTuneCents;
46241  drwav_int8 gainDecibels;
46242  drwav_int8 lowNote;
46243  drwav_int8 highNote;
46244  drwav_int8 lowVelocity;
46245  drwav_int8 highVelocity;
46246 } drwav_inst;
46247 typedef struct
46248 {
46249  drwav_uint32 id;
46250  drwav_uint32 playOrderPosition;
46251  drwav_uint8 dataChunkId[4];
46252  drwav_uint32 chunkStart;
46253  drwav_uint32 blockStart;
46254  drwav_uint32 sampleByteOffset;
46255 } drwav_cue_point;
46256 typedef struct
46257 {
46258  drwav_uint32 cuePointCount;
46259  drwav_cue_point *pCuePoints;
46260 } drwav_cue;
46261 typedef enum
46262 {
46268 } drwav_acid_flag;
46269 typedef struct
46270 {
46271  drwav_uint32 flags;
46272  drwav_uint16 midiUnityNote;
46273  drwav_uint16 reserved1;
46274  float reserved2;
46275  drwav_uint32 numBeats;
46276  drwav_uint16 meterDenominator;
46277  drwav_uint16 meterNumerator;
46278  float tempo;
46279 } drwav_acid;
46280 typedef struct
46281 {
46282  drwav_uint32 cuePointId;
46283  drwav_uint32 stringLength;
46284  char* pString;
46286 typedef struct
46287 {
46288  char* pDescription;
46289  char* pOriginatorName;
46290  char* pOriginatorReference;
46291  char pOriginationDate[10];
46292  char pOriginationTime[8];
46293  drwav_uint64 timeReference;
46295  char* pCodingHistory;
46296  drwav_uint32 codingHistorySize;
46297  drwav_uint8* pUMID;
46298  drwav_uint16 loudnessValue;
46299  drwav_uint16 loudnessRange;
46300  drwav_uint16 maxTruePeakLevel;
46301  drwav_uint16 maxMomentaryLoudness;
46302  drwav_uint16 maxShortTermLoudness;
46303 } drwav_bext;
46304 typedef struct
46305 {
46306  drwav_uint32 stringLength;
46307  char* pString;
46309 typedef struct
46310 {
46311  drwav_uint32 cuePointId;
46312  drwav_uint32 sampleLength;
46313  drwav_uint8 purposeId[4];
46314  drwav_uint16 country;
46315  drwav_uint16 language;
46316  drwav_uint16 dialect;
46317  drwav_uint16 codePage;
46318  drwav_uint32 stringLength;
46319  char* pString;
46321 typedef enum
46322 {
46328 typedef struct
46329 {
46330  drwav_uint8 id[4];
46331  drwav_metadata_location chunkLocation;
46332  drwav_uint32 dataSizeInBytes;
46333  drwav_uint8* pData;
46335 typedef struct
46336 {
46337  drwav_metadata_type type;
46338  union
46339  {
46340  drwav_cue cue;
46341  drwav_smpl smpl;
46342  drwav_acid acid;
46343  drwav_inst inst;
46344  drwav_bext bext;
46345  drwav_list_label_or_note labelOrNote;
46346  drwav_list_labelled_cue_region labelledCueRegion;
46347  drwav_list_info_text infoText;
46348  drwav_unknown_metadata unknown;
46349  } data;
46350 } drwav_metadata;
46351 typedef struct
46352 {
46353  drwav_read_proc onRead;
46354  drwav_write_proc onWrite;
46355  drwav_seek_proc onSeek;
46356  void* pUserData;
46357  drwav_allocation_callbacks allocationCallbacks;
46358  drwav_container container;
46359  drwav_fmt fmt;
46360  drwav_uint32 sampleRate;
46361  drwav_uint16 channels;
46362  drwav_uint16 bitsPerSample;
46363  drwav_uint16 translatedFormatTag;
46364  drwav_uint64 totalPCMFrameCount;
46365  drwav_uint64 dataChunkDataSize;
46366  drwav_uint64 dataChunkDataPos;
46367  drwav_uint64 bytesRemaining;
46368  drwav_uint64 readCursorInPCMFrames;
46369  drwav_uint64 dataChunkDataSizeTargetWrite;
46370  drwav_bool32 isSequentialWrite;
46371  drwav_metadata_type allowedMetadataTypes;
46372  drwav_metadata* pMetadata;
46373  drwav_uint32 metadataCount;
46374  drwav__memory_stream memoryStream;
46375  drwav__memory_stream_write memoryStreamWrite;
46376  struct
46377  {
46378  drwav_uint32 bytesRemainingInBlock;
46379  drwav_uint16 predictor[2];
46380  drwav_int32 delta[2];
46381  drwav_int32 cachedFrames[4];
46382  drwav_uint32 cachedFrameCount;
46383  drwav_int32 prevFrames[2][2];
46384  } msadpcm;
46385  struct
46386  {
46387  drwav_uint32 bytesRemainingInBlock;
46388  drwav_int32 predictor[2];
46389  drwav_int32 stepIndex[2];
46390  drwav_int32 cachedFrames[16];
46391  drwav_uint32 cachedFrameCount;
46392  } ima;
46393 } drwav;
46394 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
46395 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);
46396 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);
46397 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);
46398 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);
46399 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);
46400 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);
46401 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
46404 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
46405 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
46406 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
46407 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
46411 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
46412 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
46413 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
46414 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
46415 #ifndef DR_WAV_NO_CONVERSION_API
46419 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
46420 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
46421 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
46422 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
46423 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
46424 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
46425 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
46426 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
46427 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
46428 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
46429 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
46430 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
46431 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
46432 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
46433 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
46434 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
46435 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
46439 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
46440 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
46441 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
46442 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
46443 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
46444 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
46445 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
46446 #endif
46447 #ifndef DR_WAV_NO_STDIO
46448 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
46449 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);
46450 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
46451 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);
46452 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
46453 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
46454 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
46455 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);
46456 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);
46457 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);
46458 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);
46459 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);
46460 #endif
46461 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
46462 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);
46463 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);
46464 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);
46465 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);
46466 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);
46467 #ifndef DR_WAV_NO_CONVERSION_API
46468 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);
46469 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);
46470 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);
46471 #ifndef DR_WAV_NO_STDIO
46472 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);
46473 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);
46474 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);
46475 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);
46476 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);
46477 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);
46478 #endif
46479 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);
46480 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);
46481 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);
46482 #endif
46483 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
46490 DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data);
46492 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
46493 #ifdef __cplusplus
46494 }
46495 #endif
46496 #endif
46497 /* dr_wav_h end */
46498 #endif /* MA_NO_WAV */
46499 
46500 #if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING)
46501 /* dr_flac_h begin */
46502 #ifndef dr_flac_h
46503 #define dr_flac_h
46504 #ifdef __cplusplus
46505 extern "C" {
46506 #endif
46507 #define DRFLAC_STRINGIFY(x) #x
46508 #define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
46509 #define DRFLAC_VERSION_MAJOR 0
46510 #define DRFLAC_VERSION_MINOR 12
46511 #define DRFLAC_VERSION_REVISION 30
46512 #define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
46513 #include <stddef.h>
46514 typedef signed char drflac_int8;
46515 typedef unsigned char drflac_uint8;
46516 typedef signed short drflac_int16;
46517 typedef unsigned short drflac_uint16;
46518 typedef signed int drflac_int32;
46519 typedef unsigned int drflac_uint32;
46520 #if defined(_MSC_VER)
46521  typedef signed __int64 drflac_int64;
46522  typedef unsigned __int64 drflac_uint64;
46523 #else
46524  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
46525  #pragma GCC diagnostic push
46526  #pragma GCC diagnostic ignored "-Wlong-long"
46527  #if defined(__clang__)
46528  #pragma GCC diagnostic ignored "-Wc++11-long-long"
46529  #endif
46530  #endif
46531  typedef signed long long drflac_int64;
46532  typedef unsigned long long drflac_uint64;
46533  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
46534  #pragma GCC diagnostic pop
46535  #endif
46536 #endif
46537 #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__)
46538  typedef drflac_uint64 drflac_uintptr;
46539 #else
46540  typedef drflac_uint32 drflac_uintptr;
46541 #endif
46542 typedef drflac_uint8 drflac_bool8;
46544 #define DRFLAC_TRUE 1
46545 #define DRFLAC_FALSE 0
46546 #if !defined(DRFLAC_API)
46547  #if defined(DRFLAC_DLL)
46548  #if defined(_WIN32)
46549  #define DRFLAC_DLL_IMPORT __declspec(dllimport)
46550  #define DRFLAC_DLL_EXPORT __declspec(dllexport)
46551  #define DRFLAC_DLL_PRIVATE static
46552  #else
46553  #if defined(__GNUC__) && __GNUC__ >= 4
46554  #define DRFLAC_DLL_IMPORT __attribute__((visibility("default")))
46555  #define DRFLAC_DLL_EXPORT __attribute__((visibility("default")))
46556  #define DRFLAC_DLL_PRIVATE __attribute__((visibility("hidden")))
46557  #else
46558  #define DRFLAC_DLL_IMPORT
46559  #define DRFLAC_DLL_EXPORT
46560  #define DRFLAC_DLL_PRIVATE static
46561  #endif
46562  #endif
46563  #if defined(DR_FLAC_IMPLEMENTATION) || defined(DRFLAC_IMPLEMENTATION)
46564  #define DRFLAC_API DRFLAC_DLL_EXPORT
46565  #else
46566  #define DRFLAC_API DRFLAC_DLL_IMPORT
46567  #endif
46568  #define DRFLAC_PRIVATE DRFLAC_DLL_PRIVATE
46569  #else
46570  #define DRFLAC_API extern
46571  #define DRFLAC_PRIVATE static
46572  #endif
46573 #endif
46574 #if defined(_MSC_VER) && _MSC_VER >= 1700
46575  #define DRFLAC_DEPRECATED __declspec(deprecated)
46576 #elif (defined(__GNUC__) && __GNUC__ >= 4)
46577  #define DRFLAC_DEPRECATED __attribute__((deprecated))
46578 #elif defined(__has_feature)
46579  #if __has_feature(attribute_deprecated)
46580  #define DRFLAC_DEPRECATED __attribute__((deprecated))
46581  #else
46582  #define DRFLAC_DEPRECATED
46583  #endif
46584 #else
46585  #define DRFLAC_DEPRECATED
46586 #endif
46587 DRFLAC_API void drflac_version(drflac_uint32* pMajor, drflac_uint32* pMinor, drflac_uint32* pRevision);
46588 DRFLAC_API const char* drflac_version_string(void);
46589 #ifndef DR_FLAC_BUFFER_SIZE
46590 #define DR_FLAC_BUFFER_SIZE 4096
46591 #endif
46592 #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
46593 #define DRFLAC_64BIT
46594 #endif
46595 #ifdef DRFLAC_64BIT
46597 #else
46599 #endif
46600 #define DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO 0
46601 #define DRFLAC_METADATA_BLOCK_TYPE_PADDING 1
46602 #define DRFLAC_METADATA_BLOCK_TYPE_APPLICATION 2
46603 #define DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE 3
46604 #define DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT 4
46605 #define DRFLAC_METADATA_BLOCK_TYPE_CUESHEET 5
46606 #define DRFLAC_METADATA_BLOCK_TYPE_PICTURE 6
46607 #define DRFLAC_METADATA_BLOCK_TYPE_INVALID 127
46608 #define DRFLAC_PICTURE_TYPE_OTHER 0
46609 #define DRFLAC_PICTURE_TYPE_FILE_ICON 1
46610 #define DRFLAC_PICTURE_TYPE_OTHER_FILE_ICON 2
46611 #define DRFLAC_PICTURE_TYPE_COVER_FRONT 3
46612 #define DRFLAC_PICTURE_TYPE_COVER_BACK 4
46613 #define DRFLAC_PICTURE_TYPE_LEAFLET_PAGE 5
46614 #define DRFLAC_PICTURE_TYPE_MEDIA 6
46615 #define DRFLAC_PICTURE_TYPE_LEAD_ARTIST 7
46616 #define DRFLAC_PICTURE_TYPE_ARTIST 8
46617 #define DRFLAC_PICTURE_TYPE_CONDUCTOR 9
46618 #define DRFLAC_PICTURE_TYPE_BAND 10
46619 #define DRFLAC_PICTURE_TYPE_COMPOSER 11
46620 #define DRFLAC_PICTURE_TYPE_LYRICIST 12
46621 #define DRFLAC_PICTURE_TYPE_RECORDING_LOCATION 13
46622 #define DRFLAC_PICTURE_TYPE_DURING_RECORDING 14
46623 #define DRFLAC_PICTURE_TYPE_DURING_PERFORMANCE 15
46624 #define DRFLAC_PICTURE_TYPE_SCREEN_CAPTURE 16
46625 #define DRFLAC_PICTURE_TYPE_BRIGHT_COLORED_FISH 17
46626 #define DRFLAC_PICTURE_TYPE_ILLUSTRATION 18
46627 #define DRFLAC_PICTURE_TYPE_BAND_LOGOTYPE 19
46628 #define DRFLAC_PICTURE_TYPE_PUBLISHER_LOGOTYPE 20
46629 typedef enum
46630 {
46635 typedef enum
46636 {
46640 #pragma pack(2)
46641 typedef struct
46642 {
46643  drflac_uint64 firstPCMFrame;
46644  drflac_uint64 flacFrameOffset;
46645  drflac_uint16 pcmFrameCount;
46647 #pragma pack()
46648 typedef struct
46649 {
46650  drflac_uint16 minBlockSizeInPCMFrames;
46651  drflac_uint16 maxBlockSizeInPCMFrames;
46652  drflac_uint32 minFrameSizeInPCMFrames;
46653  drflac_uint32 maxFrameSizeInPCMFrames;
46654  drflac_uint32 sampleRate;
46655  drflac_uint8 channels;
46656  drflac_uint8 bitsPerSample;
46657  drflac_uint64 totalPCMFrameCount;
46658  drflac_uint8 md5[16];
46660 typedef struct
46661 {
46662  drflac_uint32 type;
46663  const void* pRawData;
46664  drflac_uint32 rawDataSize;
46665  union
46666  {
46667  drflac_streaminfo streaminfo;
46668  struct
46669  {
46670  int unused;
46671  } padding;
46672  struct
46673  {
46674  drflac_uint32 id;
46675  const void* pData;
46676  drflac_uint32 dataSize;
46677  } application;
46678  struct
46679  {
46680  drflac_uint32 seekpointCount;
46681  const drflac_seekpoint* pSeekpoints;
46682  } seektable;
46683  struct
46684  {
46685  drflac_uint32 vendorLength;
46686  const char* vendor;
46687  drflac_uint32 commentCount;
46688  const void* pComments;
46689  } vorbis_comment;
46690  struct
46691  {
46692  char catalog[128];
46693  drflac_uint64 leadInSampleCount;
46694  drflac_bool32 isCD;
46695  drflac_uint8 trackCount;
46696  const void* pTrackData;
46697  } cuesheet;
46698  struct
46699  {
46700  drflac_uint32 type;
46701  drflac_uint32 mimeLength;
46702  const char* mime;
46703  drflac_uint32 descriptionLength;
46704  const char* description;
46705  drflac_uint32 width;
46706  drflac_uint32 height;
46707  drflac_uint32 colorDepth;
46708  drflac_uint32 indexColorCount;
46709  drflac_uint32 pictureDataSize;
46710  const drflac_uint8* pPictureData;
46711  } picture;
46712  } data;
46713 } drflac_metadata;
46714 typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
46715 typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
46716 typedef void (* drflac_meta_proc)(void* pUserData, drflac_metadata* pMetadata);
46717 typedef struct
46718 {
46719  void* pUserData;
46720  void* (* onMalloc)(size_t sz, void* pUserData);
46721  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
46722  void (* onFree)(void* p, void* pUserData);
46724 typedef struct
46725 {
46726  const drflac_uint8* data;
46727  size_t dataSize;
46728  size_t currentReadPos;
46730 typedef struct
46731 {
46732  drflac_read_proc onRead;
46733  drflac_seek_proc onSeek;
46734  void* pUserData;
46735  size_t unalignedByteCount;
46736  drflac_cache_t unalignedCache;
46737  drflac_uint32 nextL2Line;
46738  drflac_uint32 consumedBits;
46739  drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)];
46740  drflac_cache_t cache;
46741  drflac_uint16 crc16;
46742  drflac_cache_t crc16Cache;
46743  drflac_uint32 crc16CacheIgnoredBytes;
46744 } drflac_bs;
46745 typedef struct
46746 {
46747  drflac_uint8 subframeType;
46748  drflac_uint8 wastedBitsPerSample;
46749  drflac_uint8 lpcOrder;
46750  drflac_int32* pSamplesS32;
46751 } drflac_subframe;
46752 typedef struct
46753 {
46754  drflac_uint64 pcmFrameNumber;
46755  drflac_uint32 flacFrameNumber;
46756  drflac_uint32 sampleRate;
46757  drflac_uint16 blockSizeInPCMFrames;
46758  drflac_uint8 channelAssignment;
46759  drflac_uint8 bitsPerSample;
46760  drflac_uint8 crc8;
46762 typedef struct
46763 {
46765  drflac_uint32 pcmFramesRemaining;
46766  drflac_subframe subframes[8];
46767 } drflac_frame;
46768 typedef struct
46769 {
46770  drflac_meta_proc onMeta;
46771  void* pUserDataMD;
46772  drflac_allocation_callbacks allocationCallbacks;
46773  drflac_uint32 sampleRate;
46774  drflac_uint8 channels;
46775  drflac_uint8 bitsPerSample;
46776  drflac_uint16 maxBlockSizeInPCMFrames;
46777  drflac_uint64 totalPCMFrameCount;
46778  drflac_container container;
46779  drflac_uint32 seekpointCount;
46780  drflac_frame currentFLACFrame;
46781  drflac_uint64 currentPCMFrame;
46782  drflac_uint64 firstFLACFramePosInBytes;
46783  drflac__memory_stream memoryStream;
46784  drflac_int32* pDecodedSamples;
46785  drflac_seekpoint* pSeekpoints;
46786  void* _oggbs;
46787  drflac_bool32 _noSeekTableSeek : 1;
46788  drflac_bool32 _noBinarySearchSeek : 1;
46789  drflac_bool32 _noBruteForceSeek : 1;
46790  drflac_bs bs;
46791  drflac_uint8 pExtraData[1];
46792 } drflac;
46793 DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
46794 DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
46795 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);
46796 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);
46797 DRFLAC_API void drflac_close(drflac* pFlac);
46800 DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut);
46802 #ifndef DR_FLAC_NO_STDIO
46803 DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
46804 DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
46805 DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
46806 DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
46807 #endif
46808 DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks);
46809 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);
46810 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);
46811 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);
46812 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);
46813 #ifndef DR_FLAC_NO_STDIO
46814 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);
46815 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);
46816 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);
46817 #endif
46818 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);
46819 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);
46820 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);
46821 DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks);
46822 typedef struct
46823 {
46824  drflac_uint32 countRemaining;
46825  const char* pRunningData;
46827 DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments);
46829 typedef struct
46830 {
46831  drflac_uint32 countRemaining;
46832  const char* pRunningData;
46834 #pragma pack(4)
46835 typedef struct
46836 {
46837  drflac_uint64 offset;
46838  drflac_uint8 index;
46839  drflac_uint8 reserved[3];
46841 #pragma pack()
46842 typedef struct
46843 {
46844  drflac_uint64 offset;
46845  drflac_uint8 trackNumber;
46846  char ISRC[12];
46847  drflac_bool8 isAudio;
46848  drflac_bool8 preEmphasis;
46849  drflac_uint8 indexCount;
46850  const drflac_cuesheet_track_index* pIndexPoints;
46852 DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData);
46854 #ifdef __cplusplus
46855 }
46856 #endif
46857 #endif
46858 /* dr_flac_h end */
46859 #endif /* MA_NO_FLAC */
46860 
46861 #if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
46862 /* dr_mp3_h begin */
46863 #ifndef dr_mp3_h
46864 #define dr_mp3_h
46865 #ifdef __cplusplus
46866 extern "C" {
46867 #endif
46868 #define DRMP3_STRINGIFY(x) #x
46869 #define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
46870 #define DRMP3_VERSION_MAJOR 0
46871 #define DRMP3_VERSION_MINOR 6
46872 #define DRMP3_VERSION_REVISION 28
46873 #define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
46874 #include <stddef.h>
46875 typedef signed char drmp3_int8;
46876 typedef unsigned char drmp3_uint8;
46877 typedef signed short drmp3_int16;
46878 typedef unsigned short drmp3_uint16;
46879 typedef signed int drmp3_int32;
46880 typedef unsigned int drmp3_uint32;
46881 #if defined(_MSC_VER)
46882  typedef signed __int64 drmp3_int64;
46883  typedef unsigned __int64 drmp3_uint64;
46884 #else
46885  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
46886  #pragma GCC diagnostic push
46887  #pragma GCC diagnostic ignored "-Wlong-long"
46888  #if defined(__clang__)
46889  #pragma GCC diagnostic ignored "-Wc++11-long-long"
46890  #endif
46891  #endif
46892  typedef signed long long drmp3_int64;
46893  typedef unsigned long long drmp3_uint64;
46894  #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
46895  #pragma GCC diagnostic pop
46896  #endif
46897 #endif
46898 #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__)
46899  typedef drmp3_uint64 drmp3_uintptr;
46900 #else
46901  typedef drmp3_uint32 drmp3_uintptr;
46902 #endif
46903 typedef drmp3_uint8 drmp3_bool8;
46904 typedef drmp3_uint32 drmp3_bool32;
46905 #define DRMP3_TRUE 1
46906 #define DRMP3_FALSE 0
46907 #if !defined(DRMP3_API)
46908  #if defined(DRMP3_DLL)
46909  #if defined(_WIN32)
46910  #define DRMP3_DLL_IMPORT __declspec(dllimport)
46911  #define DRMP3_DLL_EXPORT __declspec(dllexport)
46912  #define DRMP3_DLL_PRIVATE static
46913  #else
46914  #if defined(__GNUC__) && __GNUC__ >= 4
46915  #define DRMP3_DLL_IMPORT __attribute__((visibility("default")))
46916  #define DRMP3_DLL_EXPORT __attribute__((visibility("default")))
46917  #define DRMP3_DLL_PRIVATE __attribute__((visibility("hidden")))
46918  #else
46919  #define DRMP3_DLL_IMPORT
46920  #define DRMP3_DLL_EXPORT
46921  #define DRMP3_DLL_PRIVATE static
46922  #endif
46923  #endif
46924  #if defined(DR_MP3_IMPLEMENTATION) || defined(DRMP3_IMPLEMENTATION)
46925  #define DRMP3_API DRMP3_DLL_EXPORT
46926  #else
46927  #define DRMP3_API DRMP3_DLL_IMPORT
46928  #endif
46929  #define DRMP3_PRIVATE DRMP3_DLL_PRIVATE
46930  #else
46931  #define DRMP3_API extern
46932  #define DRMP3_PRIVATE static
46933  #endif
46934 #endif
46935 typedef drmp3_int32 drmp3_result;
46936 #define DRMP3_SUCCESS 0
46937 #define DRMP3_ERROR -1
46938 #define DRMP3_INVALID_ARGS -2
46939 #define DRMP3_INVALID_OPERATION -3
46940 #define DRMP3_OUT_OF_MEMORY -4
46941 #define DRMP3_OUT_OF_RANGE -5
46942 #define DRMP3_ACCESS_DENIED -6
46943 #define DRMP3_DOES_NOT_EXIST -7
46944 #define DRMP3_ALREADY_EXISTS -8
46945 #define DRMP3_TOO_MANY_OPEN_FILES -9
46946 #define DRMP3_INVALID_FILE -10
46947 #define DRMP3_TOO_BIG -11
46948 #define DRMP3_PATH_TOO_LONG -12
46949 #define DRMP3_NAME_TOO_LONG -13
46950 #define DRMP3_NOT_DIRECTORY -14
46951 #define DRMP3_IS_DIRECTORY -15
46952 #define DRMP3_DIRECTORY_NOT_EMPTY -16
46953 #define DRMP3_END_OF_FILE -17
46954 #define DRMP3_NO_SPACE -18
46955 #define DRMP3_BUSY -19
46956 #define DRMP3_IO_ERROR -20
46957 #define DRMP3_INTERRUPT -21
46958 #define DRMP3_UNAVAILABLE -22
46959 #define DRMP3_ALREADY_IN_USE -23
46960 #define DRMP3_BAD_ADDRESS -24
46961 #define DRMP3_BAD_SEEK -25
46962 #define DRMP3_BAD_PIPE -26
46963 #define DRMP3_DEADLOCK -27
46964 #define DRMP3_TOO_MANY_LINKS -28
46965 #define DRMP3_NOT_IMPLEMENTED -29
46966 #define DRMP3_NO_MESSAGE -30
46967 #define DRMP3_BAD_MESSAGE -31
46968 #define DRMP3_NO_DATA_AVAILABLE -32
46969 #define DRMP3_INVALID_DATA -33
46970 #define DRMP3_TIMEOUT -34
46971 #define DRMP3_NO_NETWORK -35
46972 #define DRMP3_NOT_UNIQUE -36
46973 #define DRMP3_NOT_SOCKET -37
46974 #define DRMP3_NO_ADDRESS -38
46975 #define DRMP3_BAD_PROTOCOL -39
46976 #define DRMP3_PROTOCOL_UNAVAILABLE -40
46977 #define DRMP3_PROTOCOL_NOT_SUPPORTED -41
46978 #define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED -42
46979 #define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED -43
46980 #define DRMP3_SOCKET_NOT_SUPPORTED -44
46981 #define DRMP3_CONNECTION_RESET -45
46982 #define DRMP3_ALREADY_CONNECTED -46
46983 #define DRMP3_NOT_CONNECTED -47
46984 #define DRMP3_CONNECTION_REFUSED -48
46985 #define DRMP3_NO_HOST -49
46986 #define DRMP3_IN_PROGRESS -50
46987 #define DRMP3_CANCELLED -51
46988 #define DRMP3_MEMORY_ALREADY_MAPPED -52
46989 #define DRMP3_AT_END -53
46990 #define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
46991 #define DRMP3_MAX_SAMPLES_PER_FRAME (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2)
46992 #ifdef _MSC_VER
46993  #define DRMP3_INLINE __forceinline
46994 #elif defined(__GNUC__)
46995  #if defined(__STRICT_ANSI__)
46996  #define DRMP3_INLINE __inline__ __attribute__((always_inline))
46997  #else
46998  #define DRMP3_INLINE inline __attribute__((always_inline))
46999  #endif
47000 #elif defined(__WATCOMC__)
47001  #define DRMP3_INLINE __inline
47002 #else
47003  #define DRMP3_INLINE
47004 #endif
47005 DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision);
47006 DRMP3_API const char* drmp3_version_string(void);
47007 typedef struct
47008 {
47009  int frame_bytes, channels, hz, layer, bitrate_kbps;
47011 typedef struct
47012 {
47013  float mdct_overlap[2][9*32], qmf_state[15*2*32];
47014  int reserv, free_format_bytes;
47015  drmp3_uint8 header[4], reserv_buf[511];
47016 } drmp3dec;
47017 DRMP3_API void drmp3dec_init(drmp3dec *dec);
47018 DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info);
47019 DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples);
47020 typedef enum
47021 {
47025 typedef struct
47026 {
47027  drmp3_uint64 seekPosInBytes;
47028  drmp3_uint64 pcmFrameIndex;
47029  drmp3_uint16 mp3FramesToDiscard;
47030  drmp3_uint16 pcmFramesToDiscard;
47032 typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
47033 typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin);
47034 typedef struct
47035 {
47036  void* pUserData;
47037  void* (* onMalloc)(size_t sz, void* pUserData);
47038  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
47039  void (* onFree)(void* p, void* pUserData);
47041 typedef struct
47042 {
47043  drmp3_uint32 channels;
47044  drmp3_uint32 sampleRate;
47045 } drmp3_config;
47046 typedef struct
47047 {
47048  drmp3dec decoder;
47049  drmp3dec_frame_info frameInfo;
47050  drmp3_uint32 channels;
47051  drmp3_uint32 sampleRate;
47052  drmp3_read_proc onRead;
47053  drmp3_seek_proc onSeek;
47054  void* pUserData;
47055  drmp3_allocation_callbacks allocationCallbacks;
47056  drmp3_uint32 mp3FrameChannels;
47057  drmp3_uint32 mp3FrameSampleRate;
47058  drmp3_uint32 pcmFramesConsumedInMP3Frame;
47059  drmp3_uint32 pcmFramesRemainingInMP3Frame;
47060  drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME];
47061  drmp3_uint64 currentPCMFrame;
47062  drmp3_uint64 streamCursor;
47063  drmp3_seek_point* pSeekPoints;
47064  drmp3_uint32 seekPointCount;
47065  size_t dataSize;
47066  size_t dataCapacity;
47067  size_t dataConsumed;
47068  drmp3_uint8* pData;
47069  drmp3_bool32 atEnd : 1;
47070  struct
47071  {
47072  const drmp3_uint8* pData;
47073  size_t dataSize;
47074  size_t currentReadPos;
47075  } memory;
47076 } drmp3;
47077 DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks);
47078 DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks);
47079 #ifndef DR_MP3_NO_STDIO
47080 DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
47081 DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
47082 #endif
47083 DRMP3_API void drmp3_uninit(drmp3* pMP3);
47084 DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut);
47091 DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints);
47092 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);
47093 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);
47094 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);
47095 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);
47096 #ifndef DR_MP3_NO_STDIO
47097 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);
47098 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);
47099 #endif
47100 DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks);
47101 DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks);
47102 #ifdef __cplusplus
47103 }
47104 #endif
47105 #endif
47106 /* dr_mp3_h end */
47107 #endif /* MA_NO_MP3 */
47108 
47109 
47110 /**************************************************************************************************************************************************************
47111 
47112 Decoding
47113 
47114 **************************************************************************************************************************************************************/
47115 #ifndef MA_NO_DECODING
47116 
47117 static ma_result ma_decoder_read_bytes(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead)
47118 {
47119  size_t bytesRead;
47120 
47121  MA_ASSERT(pDecoder != NULL);
47122  MA_ASSERT(pBufferOut != NULL);
47123  MA_ASSERT(bytesToRead > 0); /* It's an error to call this with a byte count of zero. */
47124 
47125  bytesRead = pDecoder->onRead(pDecoder, pBufferOut, bytesToRead);
47126 
47127  if (pBytesRead != NULL) {
47128  *pBytesRead = bytesRead;
47129  }
47130 
47131  if (bytesRead == 0) {
47132  return MA_AT_END;
47133  }
47134 
47135  return MA_SUCCESS;
47136 }
47137 
47138 static ma_result ma_decoder_seek_bytes(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin)
47139 {
47140  ma_bool32 wasSuccessful;
47141 
47142  MA_ASSERT(pDecoder != NULL);
47143 
47144  wasSuccessful = pDecoder->onSeek(pDecoder, byteOffset, origin);
47145  if (wasSuccessful) {
47146  return MA_SUCCESS;
47147  } else {
47148  return MA_ERROR;
47149  }
47150 }
47151 
47152 static ma_result ma_decoder_tell_bytes(ma_decoder* pDecoder, ma_int64* pCursor)
47153 {
47154  MA_ASSERT(pDecoder != NULL);
47155 
47156  if (pDecoder->onTell == NULL) {
47157  return MA_NOT_IMPLEMENTED;
47158  }
47159 
47160  return pDecoder->onTell(pDecoder, pCursor);
47161 }
47162 
47163 
47165 {
47167 
47169  config.preferredFormat = preferredFormat;
47170 
47171  return config;
47172 }
47173 
47174 
47175 MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint32 outputChannels, ma_uint32 outputSampleRate)
47176 {
47179  config.format = outputFormat;
47180  config.channels = ma_min(outputChannels, ma_countof(config.channelMap));
47181  config.sampleRate = outputSampleRate;
47182  config.resampling.algorithm = ma_resample_algorithm_linear;
47183  config.resampling.linear.lpfOrder = ma_min(MA_DEFAULT_RESAMPLER_LPF_ORDER, MA_MAX_FILTER_ORDER);
47184  config.resampling.speex.quality = 3;
47185  config.encodingFormat = ma_encoding_format_unknown;
47186 
47187  /* Note that we are intentionally leaving the channel map empty here which will cause the default channel map to be used. */
47188 
47189  return config;
47190 }
47191 
47193 {
47195 }
47196 
47198 {
47200  if (pConfig != NULL) {
47201  config = *pConfig;
47202  } else {
47204  }
47205 
47206  return config;
47207 }
47208 
47210 {
47211  ma_result result;
47212  ma_data_converter_config converterConfig;
47213  ma_format internalFormat;
47214  ma_uint32 internalChannels;
47215  ma_uint32 internalSampleRate;
47216  ma_channel internalChannelMap[MA_MAX_CHANNELS];
47217 
47218  MA_ASSERT(pDecoder != NULL);
47219  MA_ASSERT(pConfig != NULL);
47220 
47221  result = ma_data_source_get_data_format(pDecoder->pBackend, &internalFormat, &internalChannels, &internalSampleRate);
47222  if (result != MA_SUCCESS) {
47223  return result; /* Failed to retrieve the internal data format. */
47224  }
47225 
47226  /* Channel map needs to be retrieved separately. */
47227  if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onGetChannelMap != NULL) {
47228  pDecoder->pBackendVTable->onGetChannelMap(pDecoder->pBackendUserData, pDecoder->pBackend, internalChannelMap, ma_countof(internalChannelMap));
47229  } else {
47230  ma_get_standard_channel_map(ma_standard_channel_map_default, ma_min(internalChannels, ma_countof(internalChannelMap)), internalChannelMap);
47231  }
47232 
47233 
47234 
47235  /* Make sure we're not asking for too many channels. */
47236  if (pConfig->channels > MA_MAX_CHANNELS) {
47237  return MA_INVALID_ARGS;
47238  }
47239 
47240  /* The internal channels should have already been validated at a higher level, but we'll do it again explicitly here for safety. */
47241  if (internalChannels > MA_MAX_CHANNELS) {
47242  return MA_INVALID_ARGS;
47243  }
47244 
47245 
47246  /* Output format. */
47247  if (pConfig->format == ma_format_unknown) {
47248  pDecoder->outputFormat = internalFormat;
47249  } else {
47250  pDecoder->outputFormat = pConfig->format;
47251  }
47252 
47253  if (pConfig->channels == 0) {
47254  pDecoder->outputChannels = internalChannels;
47255  } else {
47256  pDecoder->outputChannels = pConfig->channels;
47257  }
47258 
47259  if (pConfig->sampleRate == 0) {
47260  pDecoder->outputSampleRate = internalSampleRate;
47261  } else {
47262  pDecoder->outputSampleRate = pConfig->sampleRate;
47263  }
47264 
47265  if (ma_channel_map_blank(pDecoder->outputChannels, pConfig->channelMap)) {
47267  } else {
47268  MA_COPY_MEMORY(pDecoder->outputChannelMap, pConfig->channelMap, sizeof(pConfig->channelMap));
47269  }
47270 
47271 
47272  converterConfig = ma_data_converter_config_init(
47273  internalFormat, pDecoder->outputFormat,
47274  internalChannels, pDecoder->outputChannels,
47275  internalSampleRate, pDecoder->outputSampleRate
47276  );
47277  ma_channel_map_copy(converterConfig.channelMapIn, internalChannelMap, internalChannels);
47278  ma_channel_map_copy(converterConfig.channelMapOut, pDecoder->outputChannelMap, pDecoder->outputChannels);
47279  converterConfig.channelMixMode = pConfig->channelMixMode;
47280  converterConfig.ditherMode = pConfig->ditherMode;
47281  converterConfig.resampling.allowDynamicSampleRate = MA_FALSE; /* Never allow dynamic sample rate conversion. Setting this to true will disable passthrough optimizations. */
47282  converterConfig.resampling.algorithm = pConfig->resampling.algorithm;
47283  converterConfig.resampling.linear.lpfOrder = pConfig->resampling.linear.lpfOrder;
47284  converterConfig.resampling.speex.quality = pConfig->resampling.speex.quality;
47285 
47286  return ma_data_converter_init(&converterConfig, &pDecoder->converter);
47287 }
47288 
47289 
47290 
47291 static ma_result ma_decoder_internal_on_read__custom(void* pUserData, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead)
47292 {
47293  ma_decoder* pDecoder = (ma_decoder*)pUserData;
47294  MA_ASSERT(pDecoder != NULL);
47295 
47296  return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead, pBytesRead);
47297 }
47298 
47299 static ma_result ma_decoder_internal_on_seek__custom(void* pUserData, ma_int64 offset, ma_seek_origin origin)
47300 {
47301  ma_decoder* pDecoder = (ma_decoder*)pUserData;
47302  MA_ASSERT(pDecoder != NULL);
47303 
47304  return ma_decoder_seek_bytes(pDecoder, offset, origin);
47305 }
47306 
47307 static ma_result ma_decoder_internal_on_tell__custom(void* pUserData, ma_int64* pCursor)
47308 {
47309  ma_decoder* pDecoder = (ma_decoder*)pUserData;
47310  MA_ASSERT(pDecoder != NULL);
47311 
47312  return ma_decoder_tell_bytes(pDecoder, pCursor);
47313 }
47314 
47315 
47316 static ma_result ma_decoder_init_from_vtable(const ma_decoding_backend_vtable* pVTable, void* pVTableUserData, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
47317 {
47318  ma_result result;
47319  ma_decoding_backend_config backendConfig;
47320  ma_data_source* pBackend;
47321 
47322  MA_ASSERT(pVTable != NULL);
47323  MA_ASSERT(pConfig != NULL);
47324  MA_ASSERT(pDecoder != NULL);
47325 
47326  if (pVTable->onInit == NULL) {
47327  return MA_NOT_IMPLEMENTED;
47328  }
47329 
47330  backendConfig = ma_decoding_backend_config_init(pConfig->format);
47331 
47332  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);
47333  if (result != MA_SUCCESS) {
47334  return result; /* Failed to initialize the backend from this vtable. */
47335  }
47336 
47337  /* Getting here means we were able to initialize the backend so we can now initialize the decoder. */
47338  pDecoder->pBackend = pBackend;
47339  pDecoder->pBackendVTable = pVTable;
47340  pDecoder->pBackendUserData = pConfig->pCustomBackendUserData;
47341 
47342  return MA_SUCCESS;
47343 }
47344 
47345 
47346 
47348 {
47349  ma_result result = MA_NO_BACKEND;
47350  size_t ivtable;
47351 
47352  MA_ASSERT(pConfig != NULL);
47353  MA_ASSERT(pDecoder != NULL);
47354 
47355  if (pConfig->ppCustomBackendVTables == NULL) {
47356  return MA_NO_BACKEND;
47357  }
47358 
47359  /* The order each backend is listed is what defines the priority. */
47360  for (ivtable = 0; ivtable < pConfig->customBackendCount; ivtable += 1) {
47361  const ma_decoding_backend_vtable* pVTable = pConfig->ppCustomBackendVTables[ivtable];
47362  if (pVTable != NULL && pVTable->onInit != NULL) {
47363  result = ma_decoder_init_from_vtable(pVTable, pConfig->pCustomBackendUserData, pConfig, pDecoder);
47364  if (result == MA_SUCCESS) {
47365  return MA_SUCCESS;
47366  } else {
47367  /* 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. */
47368  result = ma_decoder_seek_bytes(pDecoder, 0, ma_seek_origin_start);
47369  if (result != MA_SUCCESS) {
47370  return result; /* Failed to seek back to the start. */
47371  }
47372  }
47373  } else {
47374  /* No vtable. */
47375  }
47376  }
47377 
47378  /* Getting here means we couldn't find a backend. */
47379  return MA_NO_BACKEND;
47380 }
47381 
47382 
47383 /* WAV */
47384 #ifdef dr_wav_h
47385 #define MA_HAS_WAV
47386 
47387 typedef struct
47388 {
47390  ma_read_proc onRead;
47391  ma_seek_proc onSeek;
47392  ma_tell_proc onTell;
47393  void* pReadSeekTellUserData;
47394  ma_format format; /* Can be f32, s16 or s32. */
47395 #if !defined(MA_NO_WAV)
47396  drwav dr;
47397 #endif
47398 } ma_wav;
47399 
47400 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);
47401 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);
47402 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);
47403 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);
47404 MA_API void ma_wav_uninit(ma_wav* pWav, const ma_allocation_callbacks* pAllocationCallbacks);
47405 MA_API ma_result ma_wav_read_pcm_frames(ma_wav* pWav, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
47407 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);
47410 
47411 
47412 static ma_result ma_wav_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
47413 {
47414  return ma_wav_read_pcm_frames((ma_wav*)pDataSource, pFramesOut, frameCount, pFramesRead);
47415 }
47416 
47417 static ma_result ma_wav_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
47418 {
47419  return ma_wav_seek_to_pcm_frame((ma_wav*)pDataSource, frameIndex);
47420 }
47421 
47422 static ma_result ma_wav_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
47423 {
47424  return ma_wav_get_data_format((ma_wav*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
47425 }
47426 
47427 static ma_result ma_wav_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
47428 {
47429  return ma_wav_get_cursor_in_pcm_frames((ma_wav*)pDataSource, pCursor);
47430 }
47431 
47432 static ma_result ma_wav_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
47433 {
47434  return ma_wav_get_length_in_pcm_frames((ma_wav*)pDataSource, pLength);
47435 }
47436 
47438 {
47441  NULL, /* onMap() */
47442  NULL, /* onUnmap() */
47446 };
47447 
47448 
47449 #if !defined(MA_NO_WAV)
47451 {
47452  drwav_allocation_callbacks callbacks;
47453 
47454  if (pAllocationCallbacks != NULL) {
47455  callbacks.onMalloc = pAllocationCallbacks->onMalloc;
47456  callbacks.onRealloc = pAllocationCallbacks->onRealloc;
47457  callbacks.onFree = pAllocationCallbacks->onFree;
47458  callbacks.pUserData = pAllocationCallbacks->pUserData;
47459  } else {
47460  callbacks.onMalloc = ma__malloc_default;
47461  callbacks.onRealloc = ma__realloc_default;
47462  callbacks.onFree = ma__free_default;
47463  callbacks.pUserData = NULL;
47464  }
47465 
47466  return callbacks;
47467 }
47468 
47469 static size_t ma_wav_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
47470 {
47471  ma_wav* pWav = (ma_wav*)pUserData;
47472  ma_result result;
47473  size_t bytesRead;
47474 
47475  MA_ASSERT(pWav != NULL);
47476 
47477  result = pWav->onRead(pWav->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
47478  (void)result;
47479 
47480  return bytesRead;
47481 }
47482 
47483 static drwav_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, drwav_seek_origin origin)
47484 {
47485  ma_wav* pWav = (ma_wav*)pUserData;
47486  ma_result result;
47487  ma_seek_origin maSeekOrigin;
47488 
47489  MA_ASSERT(pWav != NULL);
47490 
47491  maSeekOrigin = ma_seek_origin_start;
47492  if (origin == drwav_seek_origin_current) {
47493  maSeekOrigin = ma_seek_origin_current;
47494  }
47495 
47496  result = pWav->onSeek(pWav->pReadSeekTellUserData, offset, maSeekOrigin);
47497  if (result != MA_SUCCESS) {
47498  return MA_FALSE;
47499  }
47500 
47501  return MA_TRUE;
47502 }
47503 #endif
47504 
47506 {
47507  ma_result result;
47508  ma_data_source_config dataSourceConfig;
47509 
47510  if (pWav == NULL) {
47511  return MA_INVALID_ARGS;
47512  }
47513 
47514  MA_ZERO_OBJECT(pWav);
47515  pWav->format = ma_format_f32; /* f32 by default. */
47516 
47517  if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16 || pConfig->preferredFormat == ma_format_s32)) {
47518  pWav->format = pConfig->preferredFormat;
47519  } else {
47520  /* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
47521  }
47522 
47523  dataSourceConfig = ma_data_source_config_init();
47524  dataSourceConfig.vtable = &g_ma_wav_ds_vtable;
47525 
47526  result = ma_data_source_init(&dataSourceConfig, &pWav->ds);
47527  if (result != MA_SUCCESS) {
47528  return result; /* Failed to initialize the base data source. */
47529  }
47530 
47531  return MA_SUCCESS;
47532 }
47533 
47534 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)
47535 {
47536  ma_result result;
47537 
47538  result = ma_wav_init_internal(pConfig, pWav);
47539  if (result != MA_SUCCESS) {
47540  return result;
47541  }
47542 
47543  if (onRead == NULL || onSeek == NULL) {
47544  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
47545  }
47546 
47547  pWav->onRead = onRead;
47548  pWav->onSeek = onSeek;
47549  pWav->onTell = onTell;
47550  pWav->pReadSeekTellUserData = pReadSeekTellUserData;
47551 
47552  #if !defined(MA_NO_WAV)
47553  {
47554  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
47555  drwav_bool32 wavResult;
47556 
47557  wavResult = drwav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, pWav, &wavAllocationCallbacks);
47558  if (wavResult != MA_TRUE) {
47559  return MA_INVALID_FILE;
47560  }
47561 
47562  return MA_SUCCESS;
47563  }
47564  #else
47565  {
47566  /* wav is disabled. */
47567  (void)pAllocationCallbacks;
47568  return MA_NOT_IMPLEMENTED;
47569  }
47570  #endif
47571 }
47572 
47573 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)
47574 {
47575  ma_result result;
47576 
47577  result = ma_wav_init_internal(pConfig, pWav);
47578  if (result != MA_SUCCESS) {
47579  return result;
47580  }
47581 
47582  #if !defined(MA_NO_WAV)
47583  {
47584  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
47585  drwav_bool32 wavResult;
47586 
47587  wavResult = drwav_init_file(&pWav->dr, pFilePath, &wavAllocationCallbacks);
47588  if (wavResult != MA_TRUE) {
47589  return MA_INVALID_FILE;
47590  }
47591 
47592  return MA_SUCCESS;
47593  }
47594  #else
47595  {
47596  /* wav is disabled. */
47597  (void)pFilePath;
47598  (void)pAllocationCallbacks;
47599  return MA_NOT_IMPLEMENTED;
47600  }
47601  #endif
47602 }
47603 
47604 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)
47605 {
47606  ma_result result;
47607 
47608  result = ma_wav_init_internal(pConfig, pWav);
47609  if (result != MA_SUCCESS) {
47610  return result;
47611  }
47612 
47613  #if !defined(MA_NO_WAV)
47614  {
47615  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
47616  drwav_bool32 wavResult;
47617 
47618  wavResult = drwav_init_file_w(&pWav->dr, pFilePath, &wavAllocationCallbacks);
47619  if (wavResult != MA_TRUE) {
47620  return MA_INVALID_FILE;
47621  }
47622 
47623  return MA_SUCCESS;
47624  }
47625  #else
47626  {
47627  /* wav is disabled. */
47628  (void)pFilePath;
47629  (void)pAllocationCallbacks;
47630  return MA_NOT_IMPLEMENTED;
47631  }
47632  #endif
47633 }
47634 
47635 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)
47636 {
47637  ma_result result;
47638 
47639  result = ma_wav_init_internal(pConfig, pWav);
47640  if (result != MA_SUCCESS) {
47641  return result;
47642  }
47643 
47644  #if !defined(MA_NO_WAV)
47645  {
47646  drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
47647  drwav_bool32 wavResult;
47648 
47649  wavResult = drwav_init_memory(&pWav->dr, pData, dataSize, &wavAllocationCallbacks);
47650  if (wavResult != MA_TRUE) {
47651  return MA_INVALID_FILE;
47652  }
47653 
47654  return MA_SUCCESS;
47655  }
47656  #else
47657  {
47658  /* wav is disabled. */
47659  (void)pData;
47660  (void)dataSize;
47661  (void)pAllocationCallbacks;
47662  return MA_NOT_IMPLEMENTED;
47663  }
47664  #endif
47665 }
47666 
47667 MA_API void ma_wav_uninit(ma_wav* pWav, const ma_allocation_callbacks* pAllocationCallbacks)
47668 {
47669  if (pWav == NULL) {
47670  return;
47671  }
47672 
47673  (void)pAllocationCallbacks;
47674 
47675  #if !defined(MA_NO_WAV)
47676  {
47677  drwav_uninit(&pWav->dr);
47678  }
47679  #else
47680  {
47681  /* wav is disabled. Should never hit this since initialization would have failed. */
47683  }
47684  #endif
47685 
47686  ma_data_source_uninit(&pWav->ds);
47687 }
47688 
47689 MA_API ma_result ma_wav_read_pcm_frames(ma_wav* pWav, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
47690 {
47691  if (pWav == NULL) {
47692  return MA_INVALID_ARGS;
47693  }
47694 
47695  #if !defined(MA_NO_WAV)
47696  {
47697  /* We always use floating point format. */
47698  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
47699  ma_uint64 totalFramesRead = 0;
47700  ma_format format;
47701 
47702  ma_wav_get_data_format(pWav, &format, NULL, NULL, NULL, 0);
47703 
47704  switch (format)
47705  {
47706  case ma_format_f32:
47707  {
47708  totalFramesRead = drwav_read_pcm_frames_f32(&pWav->dr, frameCount, (float*)pFramesOut);
47709  } break;
47710 
47711  case ma_format_s16:
47712  {
47713  totalFramesRead = drwav_read_pcm_frames_s16(&pWav->dr, frameCount, (drwav_int16*)pFramesOut);
47714  } break;
47715 
47716  case ma_format_s32:
47717  {
47718  totalFramesRead = drwav_read_pcm_frames_s32(&pWav->dr, frameCount, (drwav_int32*)pFramesOut);
47719  } break;
47720 
47721  /* Fallback to a raw read. */
47722  case ma_format_unknown: return MA_INVALID_OPERATION; /* <-- this should never be hit because initialization would just fall back to supported format. */
47723  default:
47724  {
47725  totalFramesRead = drwav_read_pcm_frames(&pWav->dr, frameCount, pFramesOut);
47726  } break;
47727  }
47728 
47729  /* In the future we'll update dr_wav to return MA_AT_END for us. */
47730  if (totalFramesRead == 0) {
47731  result = MA_AT_END;
47732  }
47733 
47734  if (pFramesRead != NULL) {
47735  *pFramesRead = totalFramesRead;
47736  }
47737 
47738  return result;
47739  }
47740  #else
47741  {
47742  /* wav is disabled. Should never hit this since initialization would have failed. */
47744 
47745  (void)pFramesOut;
47746  (void)frameCount;
47747  (void)pFramesRead;
47748 
47749  return MA_NOT_IMPLEMENTED;
47750  }
47751  #endif
47752 }
47753 
47755 {
47756  if (pWav == NULL) {
47757  return MA_INVALID_ARGS;
47758  }
47759 
47760  #if !defined(MA_NO_WAV)
47761  {
47762  drwav_bool32 wavResult;
47763 
47764  wavResult = drwav_seek_to_pcm_frame(&pWav->dr, frameIndex);
47765  if (wavResult != DRWAV_TRUE) {
47766  return MA_ERROR;
47767  }
47768 
47769  return MA_SUCCESS;
47770  }
47771  #else
47772  {
47773  /* wav is disabled. Should never hit this since initialization would have failed. */
47775 
47776  (void)frameIndex;
47777 
47778  return MA_NOT_IMPLEMENTED;
47779  }
47780  #endif
47781 }
47782 
47783 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)
47784 {
47785  /* Defaults for safety. */
47786  if (pFormat != NULL) {
47787  *pFormat = ma_format_unknown;
47788  }
47789  if (pChannels != NULL) {
47790  *pChannels = 0;
47791  }
47792  if (pSampleRate != NULL) {
47793  *pSampleRate = 0;
47794  }
47795  if (pChannelMap != NULL) {
47796  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
47797  }
47798 
47799  if (pWav == NULL) {
47800  return MA_INVALID_OPERATION;
47801  }
47802 
47803  if (pFormat != NULL) {
47804  *pFormat = pWav->format;
47805  }
47806 
47807  #if !defined(MA_NO_WAV)
47808  {
47809  if (pChannels != NULL) {
47810  *pChannels = pWav->dr.channels;
47811  }
47812 
47813  if (pSampleRate != NULL) {
47814  *pSampleRate = pWav->dr.sampleRate;
47815  }
47816 
47817  if (pChannelMap != NULL) {
47819  }
47820 
47821  return MA_SUCCESS;
47822  }
47823  #else
47824  {
47825  /* wav is disabled. Should never hit this since initialization would have failed. */
47827  return MA_NOT_IMPLEMENTED;
47828  }
47829  #endif
47830 }
47831 
47833 {
47834  if (pCursor == NULL) {
47835  return MA_INVALID_ARGS;
47836  }
47837 
47838  *pCursor = 0; /* Safety. */
47839 
47840  if (pWav == NULL) {
47841  return MA_INVALID_ARGS;
47842  }
47843 
47844  #if !defined(MA_NO_WAV)
47845  {
47846  drwav_result wavResult = drwav_get_cursor_in_pcm_frames(&pWav->dr, pCursor);
47847  if (wavResult != DRWAV_SUCCESS) {
47848  return (ma_result)wavResult; /* dr_wav result codes map to miniaudio's. */
47849  }
47850 
47851  return MA_SUCCESS;
47852  }
47853  #else
47854  {
47855  /* wav is disabled. Should never hit this since initialization would have failed. */
47857  return MA_NOT_IMPLEMENTED;
47858  }
47859  #endif
47860 }
47861 
47863 {
47864  if (pLength == NULL) {
47865  return MA_INVALID_ARGS;
47866  }
47867 
47868  *pLength = 0; /* Safety. */
47869 
47870  if (pWav == NULL) {
47871  return MA_INVALID_ARGS;
47872  }
47873 
47874  #if !defined(MA_NO_WAV)
47875  {
47876  drwav_result wavResult = drwav_get_length_in_pcm_frames(&pWav->dr, pLength);
47877  if (wavResult != DRWAV_SUCCESS) {
47878  return (ma_result)wavResult; /* dr_wav result codes map to miniaudio's. */
47879  }
47880 
47881  return MA_SUCCESS;
47882  }
47883  #else
47884  {
47885  /* wav is disabled. Should never hit this since initialization would have failed. */
47887  return MA_NOT_IMPLEMENTED;
47888  }
47889  #endif
47890 }
47891 
47892 
47893 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)
47894 {
47895  ma_result result;
47896  ma_wav* pWav;
47897 
47898  (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. */
47899 
47900  /* For now we're just allocating the decoder backend on the heap. */
47901  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
47902  if (pWav == NULL) {
47903  return MA_OUT_OF_MEMORY;
47904  }
47905 
47906  result = ma_wav_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pWav);
47907  if (result != MA_SUCCESS) {
47908  ma_free(pWav, pAllocationCallbacks);
47909  return result;
47910  }
47911 
47912  *ppBackend = pWav;
47913 
47914  return MA_SUCCESS;
47915 }
47916 
47917 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)
47918 {
47919  ma_result result;
47920  ma_wav* pWav;
47921 
47922  (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. */
47923 
47924  /* For now we're just allocating the decoder backend on the heap. */
47925  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
47926  if (pWav == NULL) {
47927  return MA_OUT_OF_MEMORY;
47928  }
47929 
47930  result = ma_wav_init_file(pFilePath, pConfig, pAllocationCallbacks, pWav);
47931  if (result != MA_SUCCESS) {
47932  ma_free(pWav, pAllocationCallbacks);
47933  return result;
47934  }
47935 
47936  *ppBackend = pWav;
47937 
47938  return MA_SUCCESS;
47939 }
47940 
47941 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)
47942 {
47943  ma_result result;
47944  ma_wav* pWav;
47945 
47946  (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. */
47947 
47948  /* For now we're just allocating the decoder backend on the heap. */
47949  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
47950  if (pWav == NULL) {
47951  return MA_OUT_OF_MEMORY;
47952  }
47953 
47954  result = ma_wav_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pWav);
47955  if (result != MA_SUCCESS) {
47956  ma_free(pWav, pAllocationCallbacks);
47957  return result;
47958  }
47959 
47960  *ppBackend = pWav;
47961 
47962  return MA_SUCCESS;
47963 }
47964 
47965 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)
47966 {
47967  ma_result result;
47968  ma_wav* pWav;
47969 
47970  (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. */
47971 
47972  /* For now we're just allocating the decoder backend on the heap. */
47973  pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
47974  if (pWav == NULL) {
47975  return MA_OUT_OF_MEMORY;
47976  }
47977 
47978  result = ma_wav_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pWav);
47979  if (result != MA_SUCCESS) {
47980  ma_free(pWav, pAllocationCallbacks);
47981  return result;
47982  }
47983 
47984  *ppBackend = pWav;
47985 
47986  return MA_SUCCESS;
47987 }
47988 
47989 static void ma_decoding_backend_uninit__wav(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
47990 {
47991  ma_wav* pWav = (ma_wav*)pBackend;
47992 
47993  (void)pUserData;
47994 
47995  ma_wav_uninit(pWav, pAllocationCallbacks);
47996  ma_free(pWav, pAllocationCallbacks);
47997 }
47998 
47999 static ma_result ma_decoding_backend_get_channel_map__wav(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
48000 {
48001  ma_wav* pWav = (ma_wav*)pBackend;
48002 
48003  (void)pUserData;
48004 
48005  return ma_wav_get_data_format(pWav, NULL, NULL, NULL, pChannelMap, channelMapCap);
48006 }
48007 
48009 {
48016 };
48017 
48018 static ma_result ma_decoder_init_wav__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
48019 {
48021 }
48022 #endif /* dr_wav_h */
48023 
48024 /* FLAC */
48025 #ifdef dr_flac_h
48026 #define MA_HAS_FLAC
48027 
48028 typedef struct
48029 {
48031  ma_read_proc onRead;
48032  ma_seek_proc onSeek;
48033  ma_tell_proc onTell;
48034  void* pReadSeekTellUserData;
48035  ma_format format; /* Can be f32, s16 or s32. */
48036 #if !defined(MA_NO_FLAC)
48037  drflac* dr;
48038 #endif
48039 } ma_flac;
48040 
48041 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);
48042 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);
48043 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);
48044 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);
48045 MA_API void ma_flac_uninit(ma_flac* pFlac, const ma_allocation_callbacks* pAllocationCallbacks);
48046 MA_API ma_result ma_flac_read_pcm_frames(ma_flac* pFlac, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
48048 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);
48051 
48052 
48053 static ma_result ma_flac_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
48054 {
48055  return ma_flac_read_pcm_frames((ma_flac*)pDataSource, pFramesOut, frameCount, pFramesRead);
48056 }
48057 
48058 static ma_result ma_flac_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
48059 {
48060  return ma_flac_seek_to_pcm_frame((ma_flac*)pDataSource, frameIndex);
48061 }
48062 
48063 static ma_result ma_flac_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
48064 {
48065  return ma_flac_get_data_format((ma_flac*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
48066 }
48067 
48068 static ma_result ma_flac_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
48069 {
48070  return ma_flac_get_cursor_in_pcm_frames((ma_flac*)pDataSource, pCursor);
48071 }
48072 
48073 static ma_result ma_flac_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
48074 {
48075  return ma_flac_get_length_in_pcm_frames((ma_flac*)pDataSource, pLength);
48076 }
48077 
48079 {
48082  NULL, /* onMap() */
48083  NULL, /* onUnmap() */
48087 };
48088 
48089 
48090 #if !defined(MA_NO_FLAC)
48092 {
48093  drflac_allocation_callbacks callbacks;
48094 
48095  if (pAllocationCallbacks != NULL) {
48096  callbacks.onMalloc = pAllocationCallbacks->onMalloc;
48097  callbacks.onRealloc = pAllocationCallbacks->onRealloc;
48098  callbacks.onFree = pAllocationCallbacks->onFree;
48099  callbacks.pUserData = pAllocationCallbacks->pUserData;
48100  } else {
48101  callbacks.onMalloc = ma__malloc_default;
48102  callbacks.onRealloc = ma__realloc_default;
48103  callbacks.onFree = ma__free_default;
48104  callbacks.pUserData = NULL;
48105  }
48106 
48107  return callbacks;
48108 }
48109 
48110 static size_t ma_flac_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
48111 {
48112  ma_flac* pFlac = (ma_flac*)pUserData;
48113  ma_result result;
48114  size_t bytesRead;
48115 
48116  MA_ASSERT(pFlac != NULL);
48117 
48118  result = pFlac->onRead(pFlac->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
48119  (void)result;
48120 
48121  return bytesRead;
48122 }
48123 
48124 static drflac_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, drflac_seek_origin origin)
48125 {
48126  ma_flac* pFlac = (ma_flac*)pUserData;
48127  ma_result result;
48128  ma_seek_origin maSeekOrigin;
48129 
48130  MA_ASSERT(pFlac != NULL);
48131 
48132  maSeekOrigin = ma_seek_origin_start;
48133  if (origin == drflac_seek_origin_current) {
48134  maSeekOrigin = ma_seek_origin_current;
48135  }
48136 
48137  result = pFlac->onSeek(pFlac->pReadSeekTellUserData, offset, maSeekOrigin);
48138  if (result != MA_SUCCESS) {
48139  return MA_FALSE;
48140  }
48141 
48142  return MA_TRUE;
48143 }
48144 #endif
48145 
48147 {
48148  ma_result result;
48149  ma_data_source_config dataSourceConfig;
48150 
48151  if (pFlac == NULL) {
48152  return MA_INVALID_ARGS;
48153  }
48154 
48155  MA_ZERO_OBJECT(pFlac);
48156  pFlac->format = ma_format_f32; /* f32 by default. */
48157 
48158  if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16 || pConfig->preferredFormat == ma_format_s32)) {
48159  pFlac->format = pConfig->preferredFormat;
48160  } else {
48161  /* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
48162  }
48163 
48164  dataSourceConfig = ma_data_source_config_init();
48165  dataSourceConfig.vtable = &g_ma_flac_ds_vtable;
48166 
48167  result = ma_data_source_init(&dataSourceConfig, &pFlac->ds);
48168  if (result != MA_SUCCESS) {
48169  return result; /* Failed to initialize the base data source. */
48170  }
48171 
48172  return MA_SUCCESS;
48173 }
48174 
48175 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)
48176 {
48177  ma_result result;
48178 
48179  result = ma_flac_init_internal(pConfig, pFlac);
48180  if (result != MA_SUCCESS) {
48181  return result;
48182  }
48183 
48184  if (onRead == NULL || onSeek == NULL) {
48185  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
48186  }
48187 
48188  pFlac->onRead = onRead;
48189  pFlac->onSeek = onSeek;
48190  pFlac->onTell = onTell;
48191  pFlac->pReadSeekTellUserData = pReadSeekTellUserData;
48192 
48193  #if !defined(MA_NO_FLAC)
48194  {
48195  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48196 
48197  pFlac->dr = drflac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, pFlac, &flacAllocationCallbacks);
48198  if (pFlac->dr == NULL) {
48199  return MA_INVALID_FILE;
48200  }
48201 
48202  return MA_SUCCESS;
48203  }
48204  #else
48205  {
48206  /* flac is disabled. */
48207  (void)pAllocationCallbacks;
48208  return MA_NOT_IMPLEMENTED;
48209  }
48210  #endif
48211 }
48212 
48213 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)
48214 {
48215  ma_result result;
48216 
48217  result = ma_flac_init_internal(pConfig, pFlac);
48218  if (result != MA_SUCCESS) {
48219  return result;
48220  }
48221 
48222  #if !defined(MA_NO_FLAC)
48223  {
48224  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48225 
48226  pFlac->dr = drflac_open_file(pFilePath, &flacAllocationCallbacks);
48227  if (pFlac->dr == NULL) {
48228  return MA_INVALID_FILE;
48229  }
48230 
48231  return MA_SUCCESS;
48232  }
48233  #else
48234  {
48235  /* flac is disabled. */
48236  (void)pFilePath;
48237  (void)pAllocationCallbacks;
48238  return MA_NOT_IMPLEMENTED;
48239  }
48240  #endif
48241 }
48242 
48243 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)
48244 {
48245  ma_result result;
48246 
48247  result = ma_flac_init_internal(pConfig, pFlac);
48248  if (result != MA_SUCCESS) {
48249  return result;
48250  }
48251 
48252  #if !defined(MA_NO_FLAC)
48253  {
48254  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48255 
48256  pFlac->dr = drflac_open_file_w(pFilePath, &flacAllocationCallbacks);
48257  if (pFlac->dr == NULL) {
48258  return MA_INVALID_FILE;
48259  }
48260 
48261  return MA_SUCCESS;
48262  }
48263  #else
48264  {
48265  /* flac is disabled. */
48266  (void)pFilePath;
48267  (void)pAllocationCallbacks;
48268  return MA_NOT_IMPLEMENTED;
48269  }
48270  #endif
48271 }
48272 
48273 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)
48274 {
48275  ma_result result;
48276 
48277  result = ma_flac_init_internal(pConfig, pFlac);
48278  if (result != MA_SUCCESS) {
48279  return result;
48280  }
48281 
48282  #if !defined(MA_NO_FLAC)
48283  {
48284  drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48285 
48286  pFlac->dr = drflac_open_memory(pData, dataSize, &flacAllocationCallbacks);
48287  if (pFlac->dr == NULL) {
48288  return MA_INVALID_FILE;
48289  }
48290 
48291  return MA_SUCCESS;
48292  }
48293  #else
48294  {
48295  /* flac is disabled. */
48296  (void)pData;
48297  (void)dataSize;
48298  (void)pAllocationCallbacks;
48299  return MA_NOT_IMPLEMENTED;
48300  }
48301  #endif
48302 }
48303 
48304 MA_API void ma_flac_uninit(ma_flac* pFlac, const ma_allocation_callbacks* pAllocationCallbacks)
48305 {
48306  if (pFlac == NULL) {
48307  return;
48308  }
48309 
48310  (void)pAllocationCallbacks;
48311 
48312  #if !defined(MA_NO_FLAC)
48313  {
48314  drflac_close(pFlac->dr);
48315  }
48316  #else
48317  {
48318  /* flac is disabled. Should never hit this since initialization would have failed. */
48320  }
48321  #endif
48322 
48323  ma_data_source_uninit(&pFlac->ds);
48324 }
48325 
48326 MA_API ma_result ma_flac_read_pcm_frames(ma_flac* pFlac, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
48327 {
48328  if (pFlac == NULL) {
48329  return MA_INVALID_ARGS;
48330  }
48331 
48332  #if !defined(MA_NO_FLAC)
48333  {
48334  /* We always use floating point format. */
48335  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
48336  ma_uint64 totalFramesRead = 0;
48337  ma_format format;
48338 
48339  ma_flac_get_data_format(pFlac, &format, NULL, NULL, NULL, 0);
48340 
48341  switch (format)
48342  {
48343  case ma_format_f32:
48344  {
48345  totalFramesRead = drflac_read_pcm_frames_f32(pFlac->dr, frameCount, (float*)pFramesOut);
48346  } break;
48347 
48348  case ma_format_s16:
48349  {
48350  totalFramesRead = drflac_read_pcm_frames_s16(pFlac->dr, frameCount, (drflac_int16*)pFramesOut);
48351  } break;
48352 
48353  case ma_format_s32:
48354  {
48355  totalFramesRead = drflac_read_pcm_frames_s32(pFlac->dr, frameCount, (drflac_int32*)pFramesOut);
48356  } break;
48357 
48358  case ma_format_u8:
48359  case ma_format_s24:
48360  case ma_format_unknown:
48361  default:
48362  {
48363  return MA_INVALID_OPERATION;
48364  };
48365  }
48366 
48367  /* In the future we'll update dr_flac to return MA_AT_END for us. */
48368  if (totalFramesRead == 0) {
48369  result = MA_AT_END;
48370  }
48371 
48372  if (pFramesRead != NULL) {
48373  *pFramesRead = totalFramesRead;
48374  }
48375 
48376  return result;
48377  }
48378  #else
48379  {
48380  /* flac is disabled. Should never hit this since initialization would have failed. */
48382 
48383  (void)pFramesOut;
48384  (void)frameCount;
48385  (void)pFramesRead;
48386 
48387  return MA_NOT_IMPLEMENTED;
48388  }
48389  #endif
48390 }
48391 
48393 {
48394  if (pFlac == NULL) {
48395  return MA_INVALID_ARGS;
48396  }
48397 
48398  #if !defined(MA_NO_FLAC)
48399  {
48400  drflac_bool32 flacResult;
48401 
48402  flacResult = drflac_seek_to_pcm_frame(pFlac->dr, frameIndex);
48403  if (flacResult != DRFLAC_TRUE) {
48404  return MA_ERROR;
48405  }
48406 
48407  return MA_SUCCESS;
48408  }
48409  #else
48410  {
48411  /* flac is disabled. Should never hit this since initialization would have failed. */
48413 
48414  (void)frameIndex;
48415 
48416  return MA_NOT_IMPLEMENTED;
48417  }
48418  #endif
48419 }
48420 
48421 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)
48422 {
48423  /* Defaults for safety. */
48424  if (pFormat != NULL) {
48425  *pFormat = ma_format_unknown;
48426  }
48427  if (pChannels != NULL) {
48428  *pChannels = 0;
48429  }
48430  if (pSampleRate != NULL) {
48431  *pSampleRate = 0;
48432  }
48433  if (pChannelMap != NULL) {
48434  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
48435  }
48436 
48437  if (pFlac == NULL) {
48438  return MA_INVALID_OPERATION;
48439  }
48440 
48441  if (pFormat != NULL) {
48442  *pFormat = pFlac->format;
48443  }
48444 
48445  #if !defined(MA_NO_FLAC)
48446  {
48447  if (pChannels != NULL) {
48448  *pChannels = pFlac->dr->channels;
48449  }
48450 
48451  if (pSampleRate != NULL) {
48452  *pSampleRate = pFlac->dr->sampleRate;
48453  }
48454 
48455  if (pChannelMap != NULL) {
48457  }
48458 
48459  return MA_SUCCESS;
48460  }
48461  #else
48462  {
48463  /* flac is disabled. Should never hit this since initialization would have failed. */
48465  return MA_NOT_IMPLEMENTED;
48466  }
48467  #endif
48468 }
48469 
48471 {
48472  if (pCursor == NULL) {
48473  return MA_INVALID_ARGS;
48474  }
48475 
48476  *pCursor = 0; /* Safety. */
48477 
48478  if (pFlac == NULL) {
48479  return MA_INVALID_ARGS;
48480  }
48481 
48482  #if !defined(MA_NO_FLAC)
48483  {
48484  *pCursor = pFlac->dr->currentPCMFrame;
48485 
48486  return MA_SUCCESS;
48487  }
48488  #else
48489  {
48490  /* flac is disabled. Should never hit this since initialization would have failed. */
48492  return MA_NOT_IMPLEMENTED;
48493  }
48494  #endif
48495 }
48496 
48498 {
48499  if (pLength == NULL) {
48500  return MA_INVALID_ARGS;
48501  }
48502 
48503  *pLength = 0; /* Safety. */
48504 
48505  if (pFlac == NULL) {
48506  return MA_INVALID_ARGS;
48507  }
48508 
48509  #if !defined(MA_NO_FLAC)
48510  {
48511  *pLength = pFlac->dr->totalPCMFrameCount;
48512 
48513  return MA_SUCCESS;
48514  }
48515  #else
48516  {
48517  /* flac is disabled. Should never hit this since initialization would have failed. */
48519  return MA_NOT_IMPLEMENTED;
48520  }
48521  #endif
48522 }
48523 
48524 
48525 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)
48526 {
48527  ma_result result;
48528  ma_flac* pFlac;
48529 
48530  (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. */
48531 
48532  /* For now we're just allocating the decoder backend on the heap. */
48533  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
48534  if (pFlac == NULL) {
48535  return MA_OUT_OF_MEMORY;
48536  }
48537 
48538  result = ma_flac_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pFlac);
48539  if (result != MA_SUCCESS) {
48540  ma_free(pFlac, pAllocationCallbacks);
48541  return result;
48542  }
48543 
48544  *ppBackend = pFlac;
48545 
48546  return MA_SUCCESS;
48547 }
48548 
48549 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)
48550 {
48551  ma_result result;
48552  ma_flac* pFlac;
48553 
48554  (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. */
48555 
48556  /* For now we're just allocating the decoder backend on the heap. */
48557  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
48558  if (pFlac == NULL) {
48559  return MA_OUT_OF_MEMORY;
48560  }
48561 
48562  result = ma_flac_init_file(pFilePath, pConfig, pAllocationCallbacks, pFlac);
48563  if (result != MA_SUCCESS) {
48564  ma_free(pFlac, pAllocationCallbacks);
48565  return result;
48566  }
48567 
48568  *ppBackend = pFlac;
48569 
48570  return MA_SUCCESS;
48571 }
48572 
48573 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)
48574 {
48575  ma_result result;
48576  ma_flac* pFlac;
48577 
48578  (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. */
48579 
48580  /* For now we're just allocating the decoder backend on the heap. */
48581  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
48582  if (pFlac == NULL) {
48583  return MA_OUT_OF_MEMORY;
48584  }
48585 
48586  result = ma_flac_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pFlac);
48587  if (result != MA_SUCCESS) {
48588  ma_free(pFlac, pAllocationCallbacks);
48589  return result;
48590  }
48591 
48592  *ppBackend = pFlac;
48593 
48594  return MA_SUCCESS;
48595 }
48596 
48597 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)
48598 {
48599  ma_result result;
48600  ma_flac* pFlac;
48601 
48602  (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. */
48603 
48604  /* For now we're just allocating the decoder backend on the heap. */
48605  pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
48606  if (pFlac == NULL) {
48607  return MA_OUT_OF_MEMORY;
48608  }
48609 
48610  result = ma_flac_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pFlac);
48611  if (result != MA_SUCCESS) {
48612  ma_free(pFlac, pAllocationCallbacks);
48613  return result;
48614  }
48615 
48616  *ppBackend = pFlac;
48617 
48618  return MA_SUCCESS;
48619 }
48620 
48621 static void ma_decoding_backend_uninit__flac(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
48622 {
48623  ma_flac* pFlac = (ma_flac*)pBackend;
48624 
48625  (void)pUserData;
48626 
48627  ma_flac_uninit(pFlac, pAllocationCallbacks);
48628  ma_free(pFlac, pAllocationCallbacks);
48629 }
48630 
48631 static ma_result ma_decoding_backend_get_channel_map__flac(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
48632 {
48633  ma_flac* pFlac = (ma_flac*)pBackend;
48634 
48635  (void)pUserData;
48636 
48637  return ma_flac_get_data_format(pFlac, NULL, NULL, NULL, pChannelMap, channelMapCap);
48638 }
48639 
48641 {
48648 };
48649 
48650 static ma_result ma_decoder_init_flac__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
48651 {
48653 }
48654 #endif /* dr_flac_h */
48655 
48656 /* MP3 */
48657 #ifdef dr_mp3_h
48658 #define MA_HAS_MP3
48659 
48660 typedef struct
48661 {
48663  ma_read_proc onRead;
48664  ma_seek_proc onSeek;
48665  ma_tell_proc onTell;
48666  void* pReadSeekTellUserData;
48667  ma_format format; /* Can be f32 or s16. */
48668 #if !defined(MA_NO_MP3)
48669  drmp3 dr;
48670 #endif
48671 } ma_mp3;
48672 
48673 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);
48674 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);
48675 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);
48676 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);
48677 MA_API void ma_mp3_uninit(ma_mp3* pMP3, const ma_allocation_callbacks* pAllocationCallbacks);
48678 MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3* pMP3, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
48680 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);
48683 
48684 
48685 static ma_result ma_mp3_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
48686 {
48687  return ma_mp3_read_pcm_frames((ma_mp3*)pDataSource, pFramesOut, frameCount, pFramesRead);
48688 }
48689 
48690 static ma_result ma_mp3_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
48691 {
48692  return ma_mp3_seek_to_pcm_frame((ma_mp3*)pDataSource, frameIndex);
48693 }
48694 
48695 static ma_result ma_mp3_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
48696 {
48697  return ma_mp3_get_data_format((ma_mp3*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
48698 }
48699 
48700 static ma_result ma_mp3_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
48701 {
48702  return ma_mp3_get_cursor_in_pcm_frames((ma_mp3*)pDataSource, pCursor);
48703 }
48704 
48705 static ma_result ma_mp3_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
48706 {
48707  return ma_mp3_get_length_in_pcm_frames((ma_mp3*)pDataSource, pLength);
48708 }
48709 
48711 {
48714  NULL, /* onMap() */
48715  NULL, /* onUnmap() */
48719 };
48720 
48721 
48722 #if !defined(MA_NO_MP3)
48724 {
48725  drmp3_allocation_callbacks callbacks;
48726 
48727  if (pAllocationCallbacks != NULL) {
48728  callbacks.onMalloc = pAllocationCallbacks->onMalloc;
48729  callbacks.onRealloc = pAllocationCallbacks->onRealloc;
48730  callbacks.onFree = pAllocationCallbacks->onFree;
48731  callbacks.pUserData = pAllocationCallbacks->pUserData;
48732  } else {
48733  callbacks.onMalloc = ma__malloc_default;
48734  callbacks.onRealloc = ma__realloc_default;
48735  callbacks.onFree = ma__free_default;
48736  callbacks.pUserData = NULL;
48737  }
48738 
48739  return callbacks;
48740 }
48741 
48742 static size_t ma_mp3_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
48743 {
48744  ma_mp3* pMP3 = (ma_mp3*)pUserData;
48745  ma_result result;
48746  size_t bytesRead;
48747 
48748  MA_ASSERT(pMP3 != NULL);
48749 
48750  result = pMP3->onRead(pMP3->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
48751  (void)result;
48752 
48753  return bytesRead;
48754 }
48755 
48756 static drmp3_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, drmp3_seek_origin origin)
48757 {
48758  ma_mp3* pMP3 = (ma_mp3*)pUserData;
48759  ma_result result;
48760  ma_seek_origin maSeekOrigin;
48761 
48762  MA_ASSERT(pMP3 != NULL);
48763 
48764  maSeekOrigin = ma_seek_origin_start;
48765  if (origin == drmp3_seek_origin_current) {
48766  maSeekOrigin = ma_seek_origin_current;
48767  }
48768 
48769  result = pMP3->onSeek(pMP3->pReadSeekTellUserData, offset, maSeekOrigin);
48770  if (result != MA_SUCCESS) {
48771  return MA_FALSE;
48772  }
48773 
48774  return MA_TRUE;
48775 }
48776 #endif
48777 
48779 {
48780  ma_result result;
48781  ma_data_source_config dataSourceConfig;
48782 
48783  if (pMP3 == NULL) {
48784  return MA_INVALID_ARGS;
48785  }
48786 
48787  MA_ZERO_OBJECT(pMP3);
48788  pMP3->format = ma_format_f32; /* f32 by default. */
48789 
48790  if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16)) {
48791  pMP3->format = pConfig->preferredFormat;
48792  } else {
48793  /* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
48794  }
48795 
48796  dataSourceConfig = ma_data_source_config_init();
48797  dataSourceConfig.vtable = &g_ma_mp3_ds_vtable;
48798 
48799  result = ma_data_source_init(&dataSourceConfig, &pMP3->ds);
48800  if (result != MA_SUCCESS) {
48801  return result; /* Failed to initialize the base data source. */
48802  }
48803 
48804  return MA_SUCCESS;
48805 }
48806 
48807 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)
48808 {
48809  ma_result result;
48810 
48811  result = ma_mp3_init_internal(pConfig, pMP3);
48812  if (result != MA_SUCCESS) {
48813  return result;
48814  }
48815 
48816  if (onRead == NULL || onSeek == NULL) {
48817  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
48818  }
48819 
48820  pMP3->onRead = onRead;
48821  pMP3->onSeek = onSeek;
48822  pMP3->onTell = onTell;
48823  pMP3->pReadSeekTellUserData = pReadSeekTellUserData;
48824 
48825  #if !defined(MA_NO_MP3)
48826  {
48827  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48828  drmp3_bool32 mp3Result;
48829 
48830  mp3Result = drmp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, pMP3, &mp3AllocationCallbacks);
48831  if (mp3Result != MA_TRUE) {
48832  return MA_INVALID_FILE;
48833  }
48834 
48835  return MA_SUCCESS;
48836  }
48837  #else
48838  {
48839  /* mp3 is disabled. */
48840  (void)pAllocationCallbacks;
48841  return MA_NOT_IMPLEMENTED;
48842  }
48843  #endif
48844 }
48845 
48846 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)
48847 {
48848  ma_result result;
48849 
48850  result = ma_mp3_init_internal(pConfig, pMP3);
48851  if (result != MA_SUCCESS) {
48852  return result;
48853  }
48854 
48855  #if !defined(MA_NO_MP3)
48856  {
48857  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48858  drmp3_bool32 mp3Result;
48859 
48860  mp3Result = drmp3_init_file(&pMP3->dr, pFilePath, &mp3AllocationCallbacks);
48861  if (mp3Result != MA_TRUE) {
48862  return MA_INVALID_FILE;
48863  }
48864 
48865  return MA_SUCCESS;
48866  }
48867  #else
48868  {
48869  /* mp3 is disabled. */
48870  (void)pFilePath;
48871  (void)pAllocationCallbacks;
48872  return MA_NOT_IMPLEMENTED;
48873  }
48874  #endif
48875 }
48876 
48877 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)
48878 {
48879  ma_result result;
48880 
48881  result = ma_mp3_init_internal(pConfig, pMP3);
48882  if (result != MA_SUCCESS) {
48883  return result;
48884  }
48885 
48886  #if !defined(MA_NO_MP3)
48887  {
48888  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48889  drmp3_bool32 mp3Result;
48890 
48891  mp3Result = drmp3_init_file_w(&pMP3->dr, pFilePath, &mp3AllocationCallbacks);
48892  if (mp3Result != MA_TRUE) {
48893  return MA_INVALID_FILE;
48894  }
48895 
48896  return MA_SUCCESS;
48897  }
48898  #else
48899  {
48900  /* mp3 is disabled. */
48901  (void)pFilePath;
48902  (void)pAllocationCallbacks;
48903  return MA_NOT_IMPLEMENTED;
48904  }
48905  #endif
48906 }
48907 
48908 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)
48909 {
48910  ma_result result;
48911 
48912  result = ma_mp3_init_internal(pConfig, pMP3);
48913  if (result != MA_SUCCESS) {
48914  return result;
48915  }
48916 
48917  #if !defined(MA_NO_MP3)
48918  {
48919  drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
48920  drmp3_bool32 mp3Result;
48921 
48922  mp3Result = drmp3_init_memory(&pMP3->dr, pData, dataSize, &mp3AllocationCallbacks);
48923  if (mp3Result != MA_TRUE) {
48924  return MA_INVALID_FILE;
48925  }
48926 
48927  return MA_SUCCESS;
48928  }
48929  #else
48930  {
48931  /* mp3 is disabled. */
48932  (void)pData;
48933  (void)dataSize;
48934  (void)pAllocationCallbacks;
48935  return MA_NOT_IMPLEMENTED;
48936  }
48937  #endif
48938 }
48939 
48940 MA_API void ma_mp3_uninit(ma_mp3* pMP3, const ma_allocation_callbacks* pAllocationCallbacks)
48941 {
48942  if (pMP3 == NULL) {
48943  return;
48944  }
48945 
48946  (void)pAllocationCallbacks;
48947 
48948  #if !defined(MA_NO_MP3)
48949  {
48950  drmp3_uninit(&pMP3->dr);
48951  }
48952  #else
48953  {
48954  /* mp3 is disabled. Should never hit this since initialization would have failed. */
48956  }
48957  #endif
48958 
48959  ma_data_source_uninit(&pMP3->ds);
48960 }
48961 
48962 MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3* pMP3, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
48963 {
48964  if (pMP3 == NULL) {
48965  return MA_INVALID_ARGS;
48966  }
48967 
48968  #if !defined(MA_NO_MP3)
48969  {
48970  /* We always use floating point format. */
48971  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
48972  ma_uint64 totalFramesRead = 0;
48973  ma_format format;
48974 
48975  ma_mp3_get_data_format(pMP3, &format, NULL, NULL, NULL, 0);
48976 
48977  switch (format)
48978  {
48979  case ma_format_f32:
48980  {
48981  totalFramesRead = drmp3_read_pcm_frames_f32(&pMP3->dr, frameCount, (float*)pFramesOut);
48982  } break;
48983 
48984  case ma_format_s16:
48985  {
48986  totalFramesRead = drmp3_read_pcm_frames_s16(&pMP3->dr, frameCount, (drmp3_int16*)pFramesOut);
48987  } break;
48988 
48989  case ma_format_u8:
48990  case ma_format_s24:
48991  case ma_format_s32:
48992  case ma_format_unknown:
48993  default:
48994  {
48995  return MA_INVALID_OPERATION;
48996  };
48997  }
48998 
48999  /* In the future we'll update dr_mp3 to return MA_AT_END for us. */
49000  if (totalFramesRead == 0) {
49001  result = MA_AT_END;
49002  }
49003 
49004  if (pFramesRead != NULL) {
49005  *pFramesRead = totalFramesRead;
49006  }
49007 
49008  return result;
49009  }
49010  #else
49011  {
49012  /* mp3 is disabled. Should never hit this since initialization would have failed. */
49014 
49015  (void)pFramesOut;
49016  (void)frameCount;
49017  (void)pFramesRead;
49018 
49019  return MA_NOT_IMPLEMENTED;
49020  }
49021  #endif
49022 }
49023 
49025 {
49026  if (pMP3 == NULL) {
49027  return MA_INVALID_ARGS;
49028  }
49029 
49030  #if !defined(MA_NO_MP3)
49031  {
49032  drmp3_bool32 mp3Result;
49033 
49034  mp3Result = drmp3_seek_to_pcm_frame(&pMP3->dr, frameIndex);
49035  if (mp3Result != DRMP3_TRUE) {
49036  return MA_ERROR;
49037  }
49038 
49039  return MA_SUCCESS;
49040  }
49041  #else
49042  {
49043  /* mp3 is disabled. Should never hit this since initialization would have failed. */
49045 
49046  (void)frameIndex;
49047 
49048  return MA_NOT_IMPLEMENTED;
49049  }
49050  #endif
49051 }
49052 
49053 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)
49054 {
49055  /* Defaults for safety. */
49056  if (pFormat != NULL) {
49057  *pFormat = ma_format_unknown;
49058  }
49059  if (pChannels != NULL) {
49060  *pChannels = 0;
49061  }
49062  if (pSampleRate != NULL) {
49063  *pSampleRate = 0;
49064  }
49065  if (pChannelMap != NULL) {
49066  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
49067  }
49068 
49069  if (pMP3 == NULL) {
49070  return MA_INVALID_OPERATION;
49071  }
49072 
49073  if (pFormat != NULL) {
49074  *pFormat = pMP3->format;
49075  }
49076 
49077  #if !defined(MA_NO_MP3)
49078  {
49079  if (pChannels != NULL) {
49080  *pChannels = pMP3->dr.channels;
49081  }
49082 
49083  if (pSampleRate != NULL) {
49084  *pSampleRate = pMP3->dr.sampleRate;
49085  }
49086 
49087  if (pChannelMap != NULL) {
49089  }
49090 
49091  return MA_SUCCESS;
49092  }
49093  #else
49094  {
49095  /* mp3 is disabled. Should never hit this since initialization would have failed. */
49097  return MA_NOT_IMPLEMENTED;
49098  }
49099  #endif
49100 }
49101 
49103 {
49104  if (pCursor == NULL) {
49105  return MA_INVALID_ARGS;
49106  }
49107 
49108  *pCursor = 0; /* Safety. */
49109 
49110  if (pMP3 == NULL) {
49111  return MA_INVALID_ARGS;
49112  }
49113 
49114  #if !defined(MA_NO_MP3)
49115  {
49116  *pCursor = pMP3->dr.currentPCMFrame;
49117 
49118  return MA_SUCCESS;
49119  }
49120  #else
49121  {
49122  /* mp3 is disabled. Should never hit this since initialization would have failed. */
49124  return MA_NOT_IMPLEMENTED;
49125  }
49126  #endif
49127 }
49128 
49130 {
49131  if (pLength == NULL) {
49132  return MA_INVALID_ARGS;
49133  }
49134 
49135  *pLength = 0; /* Safety. */
49136 
49137  if (pMP3 == NULL) {
49138  return MA_INVALID_ARGS;
49139  }
49140 
49141  #if !defined(MA_NO_MP3)
49142  {
49143  *pLength = drmp3_get_pcm_frame_count(&pMP3->dr);
49144 
49145  return MA_SUCCESS;
49146  }
49147  #else
49148  {
49149  /* mp3 is disabled. Should never hit this since initialization would have failed. */
49151  return MA_NOT_IMPLEMENTED;
49152  }
49153  #endif
49154 }
49155 
49156 
49157 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)
49158 {
49159  ma_result result;
49160  ma_mp3* pMP3;
49161 
49162  (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. */
49163 
49164  /* For now we're just allocating the decoder backend on the heap. */
49165  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
49166  if (pMP3 == NULL) {
49167  return MA_OUT_OF_MEMORY;
49168  }
49169 
49170  result = ma_mp3_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pMP3);
49171  if (result != MA_SUCCESS) {
49172  ma_free(pMP3, pAllocationCallbacks);
49173  return result;
49174  }
49175 
49176  *ppBackend = pMP3;
49177 
49178  return MA_SUCCESS;
49179 }
49180 
49181 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)
49182 {
49183  ma_result result;
49184  ma_mp3* pMP3;
49185 
49186  (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. */
49187 
49188  /* For now we're just allocating the decoder backend on the heap. */
49189  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
49190  if (pMP3 == NULL) {
49191  return MA_OUT_OF_MEMORY;
49192  }
49193 
49194  result = ma_mp3_init_file(pFilePath, pConfig, pAllocationCallbacks, pMP3);
49195  if (result != MA_SUCCESS) {
49196  ma_free(pMP3, pAllocationCallbacks);
49197  return result;
49198  }
49199 
49200  *ppBackend = pMP3;
49201 
49202  return MA_SUCCESS;
49203 }
49204 
49205 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)
49206 {
49207  ma_result result;
49208  ma_mp3* pMP3;
49209 
49210  (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. */
49211 
49212  /* For now we're just allocating the decoder backend on the heap. */
49213  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
49214  if (pMP3 == NULL) {
49215  return MA_OUT_OF_MEMORY;
49216  }
49217 
49218  result = ma_mp3_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pMP3);
49219  if (result != MA_SUCCESS) {
49220  ma_free(pMP3, pAllocationCallbacks);
49221  return result;
49222  }
49223 
49224  *ppBackend = pMP3;
49225 
49226  return MA_SUCCESS;
49227 }
49228 
49229 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)
49230 {
49231  ma_result result;
49232  ma_mp3* pMP3;
49233 
49234  (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. */
49235 
49236  /* For now we're just allocating the decoder backend on the heap. */
49237  pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
49238  if (pMP3 == NULL) {
49239  return MA_OUT_OF_MEMORY;
49240  }
49241 
49242  result = ma_mp3_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pMP3);
49243  if (result != MA_SUCCESS) {
49244  ma_free(pMP3, pAllocationCallbacks);
49245  return result;
49246  }
49247 
49248  *ppBackend = pMP3;
49249 
49250  return MA_SUCCESS;
49251 }
49252 
49253 static void ma_decoding_backend_uninit__mp3(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
49254 {
49255  ma_mp3* pMP3 = (ma_mp3*)pBackend;
49256 
49257  (void)pUserData;
49258 
49259  ma_mp3_uninit(pMP3, pAllocationCallbacks);
49260  ma_free(pMP3, pAllocationCallbacks);
49261 }
49262 
49263 static ma_result ma_decoding_backend_get_channel_map__mp3(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
49264 {
49265  ma_mp3* pMP3 = (ma_mp3*)pBackend;
49266 
49267  (void)pUserData;
49268 
49269  return ma_mp3_get_data_format(pMP3, NULL, NULL, NULL, pChannelMap, channelMapCap);
49270 }
49271 
49273 {
49280 };
49281 
49282 static ma_result ma_decoder_init_mp3__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
49283 {
49285 }
49286 #endif /* dr_mp3_h */
49287 
49288 /* Vorbis */
49289 #ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
49290 #define MA_HAS_VORBIS
49291 
49292 /* The size in bytes of each chunk of data to read from the Vorbis stream. */
49293 #define MA_VORBIS_DATA_CHUNK_SIZE 4096
49294 
49295 typedef struct
49296 {
49298  ma_read_proc onRead;
49299  ma_seek_proc onSeek;
49300  ma_tell_proc onTell;
49301  void* pReadSeekTellUserData;
49302  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. */
49303  ma_format format; /* Only f32 is allowed with stb_vorbis. */
49304  ma_uint32 channels;
49305  ma_uint32 sampleRate;
49306  ma_uint64 cursor;
49307 #if !defined(MA_NO_VORBIS)
49308  stb_vorbis* stb;
49309  ma_bool32 usingPushMode;
49310  struct
49311  {
49312  ma_uint8* pData;
49313  size_t dataSize;
49314  size_t dataCapacity;
49315  ma_uint32 framesConsumed; /* The number of frames consumed in ppPacketData. */
49316  ma_uint32 framesRemaining; /* The number of frames remaining in ppPacketData. */
49317  float** ppPacketData;
49318  } push;
49319 #endif
49320 } ma_stbvorbis;
49321 
49322 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);
49323 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);
49324 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);
49325 MA_API void ma_stbvorbis_uninit(ma_stbvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks);
49326 MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
49327 MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64 frameIndex);
49328 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);
49329 MA_API ma_result ma_stbvorbis_get_cursor_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pCursor);
49330 MA_API ma_result ma_stbvorbis_get_length_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pLength);
49331 
49332 
49333 static ma_result ma_stbvorbis_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
49334 {
49335  return ma_stbvorbis_read_pcm_frames((ma_stbvorbis*)pDataSource, pFramesOut, frameCount, pFramesRead);
49336 }
49337 
49338 static ma_result ma_stbvorbis_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
49339 {
49340  return ma_stbvorbis_seek_to_pcm_frame((ma_stbvorbis*)pDataSource, frameIndex);
49341 }
49342 
49343 static ma_result ma_stbvorbis_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
49344 {
49345  return ma_stbvorbis_get_data_format((ma_stbvorbis*)pDataSource, pFormat, pChannels, pSampleRate, NULL, 0);
49346 }
49347 
49348 static ma_result ma_stbvorbis_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
49349 {
49350  return ma_stbvorbis_get_cursor_in_pcm_frames((ma_stbvorbis*)pDataSource, pCursor);
49351 }
49352 
49353 static ma_result ma_stbvorbis_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
49354 {
49355  return ma_stbvorbis_get_length_in_pcm_frames((ma_stbvorbis*)pDataSource, pLength);
49356 }
49357 
49358 static ma_data_source_vtable g_ma_stbvorbis_ds_vtable =
49359 {
49360  ma_stbvorbis_ds_read,
49361  ma_stbvorbis_ds_seek,
49362  NULL, /* onMap() */
49363  NULL, /* onUnmap() */
49364  ma_stbvorbis_ds_get_data_format,
49365  ma_stbvorbis_ds_get_cursor,
49366  ma_stbvorbis_ds_get_length
49367 };
49368 
49369 
49370 static ma_result ma_stbvorbis_init_internal(const ma_decoding_backend_config* pConfig, ma_stbvorbis* pVorbis)
49371 {
49372  ma_result result;
49373  ma_data_source_config dataSourceConfig;
49374 
49375  (void)pConfig;
49376 
49377  if (pVorbis == NULL) {
49378  return MA_INVALID_ARGS;
49379  }
49380 
49381  MA_ZERO_OBJECT(pVorbis);
49382  pVorbis->format = ma_format_f32; /* Only supporting f32. */
49383 
49384  dataSourceConfig = ma_data_source_config_init();
49385  dataSourceConfig.vtable = &g_ma_stbvorbis_ds_vtable;
49386 
49387  result = ma_data_source_init(&dataSourceConfig, &pVorbis->ds);
49388  if (result != MA_SUCCESS) {
49389  return result; /* Failed to initialize the base data source. */
49390  }
49391 
49392  return MA_SUCCESS;
49393 }
49394 
49395 #if !defined(MA_NO_VORBIS)
49396 static ma_result ma_stbvorbis_post_init(ma_stbvorbis* pVorbis)
49397 {
49398  stb_vorbis_info info;
49399 
49400  MA_ASSERT(pVorbis != NULL);
49401 
49402  info = stb_vorbis_get_info(pVorbis->stb);
49403 
49404  pVorbis->channels = info.channels;
49405  pVorbis->sampleRate = info.sample_rate;
49406 
49407  return MA_SUCCESS;
49408 }
49409 #endif
49410 
49411 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)
49412 {
49413  ma_result result;
49414 
49415  result = ma_stbvorbis_init_internal(pConfig, pVorbis);
49416  if (result != MA_SUCCESS) {
49417  return result;
49418  }
49419 
49420  if (onRead == NULL || onSeek == NULL) {
49421  return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
49422  }
49423 
49424  pVorbis->onRead = onRead;
49425  pVorbis->onSeek = onSeek;
49426  pVorbis->onTell = onTell;
49427  pVorbis->pReadSeekTellUserData = pReadSeekTellUserData;
49428  ma_allocation_callbacks_init_copy(&pVorbis->allocationCallbacks, pAllocationCallbacks);
49429 
49430  #if !defined(MA_NO_VORBIS)
49431  {
49432  /*
49433  stb_vorbis lacks a callback based API for it's pulling API which means we're stuck with the
49434  pushing API. In order for us to be able to successfully initialize the decoder we need to
49435  supply it with enough data. We need to keep loading data until we have enough.
49436  */
49437  stb_vorbis* stb;
49438  size_t dataSize = 0;
49439  size_t dataCapacity = 0;
49440  ma_uint8* pData = NULL; /* <-- Must be initialized to NULL. */
49441 
49442  for (;;) {
49443  int vorbisError;
49444  int consumedDataSize; /* <-- Fill by stb_vorbis_open_pushdata(). */
49445  size_t bytesRead;
49446  ma_uint8* pNewData;
49447 
49448  /* Allocate memory for the new chunk. */
49449  dataCapacity += MA_VORBIS_DATA_CHUNK_SIZE;
49450  pNewData = (ma_uint8*)ma_realloc(pData, dataCapacity, pAllocationCallbacks);
49451  if (pNewData == NULL) {
49452  ma_free(pData, pAllocationCallbacks);
49453  return MA_OUT_OF_MEMORY;
49454  }
49455 
49456  pData = pNewData;
49457 
49458  /* Read in the next chunk. */
49459  result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, ma_offset_ptr(pData, dataSize), (dataCapacity - dataSize), &bytesRead);
49460  dataSize += bytesRead;
49461 
49462  if (result != MA_SUCCESS) {
49463  ma_free(pData, pAllocationCallbacks);
49464  return result;
49465  }
49466 
49467  /* We have a maximum of 31 bits with stb_vorbis. */
49468  if (dataSize > INT_MAX) {
49469  ma_free(pData, pAllocationCallbacks);
49470  return MA_TOO_BIG;
49471  }
49472 
49473  stb = stb_vorbis_open_pushdata(pData, (int)dataSize, &consumedDataSize, &vorbisError, NULL);
49474  if (stb != NULL) {
49475  /*
49476  Successfully opened the Vorbis decoder. We might have some leftover unprocessed
49477  data so we'll need to move that down to the front.
49478  */
49479  dataSize -= (size_t)consumedDataSize; /* Consume the data. */
49480  MA_MOVE_MEMORY(pData, ma_offset_ptr(pData, consumedDataSize), dataSize);
49481  break;
49482  } else {
49483  /* Failed to open the decoder. */
49484  if (vorbisError == VORBIS_need_more_data) {
49485  continue;
49486  } else {
49487  ma_free(pData, pAllocationCallbacks);
49488  return MA_ERROR; /* Failed to open the stb_vorbis decoder. */
49489  }
49490  }
49491  }
49492 
49493  MA_ASSERT(stb != NULL);
49494  pVorbis->stb = stb;
49495  pVorbis->push.pData = pData;
49496  pVorbis->push.dataSize = dataSize;
49497  pVorbis->push.dataCapacity = dataCapacity;
49498 
49499  pVorbis->usingPushMode = MA_TRUE;
49500 
49501  result = ma_stbvorbis_post_init(pVorbis);
49502  if (result != MA_SUCCESS) {
49503  stb_vorbis_close(pVorbis->stb);
49504  ma_free(pData, pAllocationCallbacks);
49505  return result;
49506  }
49507 
49508  return MA_SUCCESS;
49509  }
49510  #else
49511  {
49512  /* vorbis is disabled. */
49513  (void)pAllocationCallbacks;
49514  return MA_NOT_IMPLEMENTED;
49515  }
49516  #endif
49517 }
49518 
49519 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)
49520 {
49521  ma_result result;
49522 
49523  result = ma_stbvorbis_init_internal(pConfig, pVorbis);
49524  if (result != MA_SUCCESS) {
49525  return result;
49526  }
49527 
49528  #if !defined(MA_NO_VORBIS)
49529  {
49530  (void)pAllocationCallbacks; /* Don't know how to make use of this with stb_vorbis. */
49531 
49532  /* We can use stb_vorbis' pull mode for file based streams. */
49533  pVorbis->stb = stb_vorbis_open_filename(pFilePath, NULL, NULL);
49534  if (pVorbis->stb == NULL) {
49535  return MA_INVALID_FILE;
49536  }
49537 
49538  pVorbis->usingPushMode = MA_FALSE;
49539 
49540  result = ma_stbvorbis_post_init(pVorbis);
49541  if (result != MA_SUCCESS) {
49542  stb_vorbis_close(pVorbis->stb);
49543  return result;
49544  }
49545 
49546  return MA_SUCCESS;
49547  }
49548  #else
49549  {
49550  /* vorbis is disabled. */
49551  (void)pFilePath;
49552  (void)pAllocationCallbacks;
49553  return MA_NOT_IMPLEMENTED;
49554  }
49555  #endif
49556 }
49557 
49558 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)
49559 {
49560  ma_result result;
49561 
49562  result = ma_stbvorbis_init_internal(pConfig, pVorbis);
49563  if (result != MA_SUCCESS) {
49564  return result;
49565  }
49566 
49567  #if !defined(MA_NO_VORBIS)
49568  {
49569  (void)pAllocationCallbacks;
49570 
49571  /* stb_vorbis uses an int as it's size specifier, restricting it to 32-bit even on 64-bit systems. *sigh*. */
49572  if (dataSize > INT_MAX) {
49573  return MA_TOO_BIG;
49574  }
49575 
49576  pVorbis->stb = stb_vorbis_open_memory((const unsigned char*)pData, (int)dataSize, NULL, NULL);
49577  if (pVorbis->stb == NULL) {
49578  return MA_INVALID_FILE;
49579  }
49580 
49581  pVorbis->usingPushMode = MA_FALSE;
49582 
49583  result = ma_stbvorbis_post_init(pVorbis);
49584  if (result != MA_SUCCESS) {
49585  stb_vorbis_close(pVorbis->stb);
49586  return result;
49587  }
49588 
49589  return MA_SUCCESS;
49590  }
49591  #else
49592  {
49593  /* vorbis is disabled. */
49594  (void)pData;
49595  (void)dataSize;
49596  (void)pAllocationCallbacks;
49597  return MA_NOT_IMPLEMENTED;
49598  }
49599  #endif
49600 }
49601 
49602 MA_API void ma_stbvorbis_uninit(ma_stbvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks)
49603 {
49604  if (pVorbis == NULL) {
49605  return;
49606  }
49607 
49608  #if !defined(MA_NO_VORBIS)
49609  {
49610  stb_vorbis_close(pVorbis->stb);
49611 
49612  /* We'll have to clear some memory if we're using push mode. */
49613  if (pVorbis->usingPushMode) {
49614  ma_free(pVorbis->push.pData, pAllocationCallbacks);
49615  }
49616  }
49617  #else
49618  {
49619  /* vorbis is disabled. Should never hit this since initialization would have failed. */
49621  }
49622  #endif
49623 
49624  ma_data_source_uninit(&pVorbis->ds);
49625 }
49626 
49627 MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
49628 {
49629  if (pVorbis == NULL) {
49630  return MA_INVALID_ARGS;
49631  }
49632 
49633  #if !defined(MA_NO_VORBIS)
49634  {
49635  /* We always use floating point format. */
49636  ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
49637  ma_uint64 totalFramesRead = 0;
49638  ma_format format;
49639  ma_uint32 channels;
49640 
49641  ma_stbvorbis_get_data_format(pVorbis, &format, &channels, NULL, NULL, 0);
49642 
49643  if (format == ma_format_f32) {
49644  /* We read differently depending on whether or not we're using push mode. */
49645  if (pVorbis->usingPushMode) {
49646  /* Push mode. This is the complex case. */
49647  float* pFramesOutF32 = (float*)pFramesOut;
49648 
49649  while (totalFramesRead < frameCount) {
49650  /* The first thing to do is read from any already-cached frames. */
49651  ma_uint32 framesToReadFromCache = (ma_uint32)ma_min(pVorbis->push.framesRemaining, (frameCount - totalFramesRead)); /* Safe cast because pVorbis->framesRemaining is 32-bit. */
49652 
49653  /* The output pointer can be null in which case we just treate it as a seek. */
49654  if (pFramesOut != NULL) {
49655  ma_uint64 iFrame;
49656  for (iFrame = 0; iFrame < framesToReadFromCache; iFrame += 1) {
49657  ma_uint32 iChannel;
49658  for (iChannel = 0; iChannel < pVorbis->channels; iChannel += 1) {
49659  pFramesOutF32[iChannel] = pVorbis->push.ppPacketData[iChannel][pVorbis->push.framesConsumed + iFrame];
49660  }
49661 
49662  pFramesOutF32 += pVorbis->channels;
49663  }
49664  }
49665 
49666  /* Update pointers and counters. */
49667  pVorbis->push.framesConsumed += framesToReadFromCache;
49668  pVorbis->push.framesRemaining -= framesToReadFromCache;
49669  totalFramesRead += framesToReadFromCache;
49670 
49671  /* Don't bother reading any more frames right now if we've just finished loading. */
49672  if (totalFramesRead == frameCount) {
49673  break;
49674  }
49675 
49676  MA_ASSERT(pVorbis->push.framesRemaining == 0);
49677 
49678  /* Getting here means we've run out of cached frames. We'll need to load some more. */
49679  for (;;) {
49680  int samplesRead = 0;
49681  int consumedDataSize;
49682 
49683  /* We need to case dataSize to an int, so make sure we can do it safely. */
49684  if (pVorbis->push.dataSize > INT_MAX) {
49685  break; /* Too big. */
49686  }
49687 
49688  consumedDataSize = stb_vorbis_decode_frame_pushdata(pVorbis->stb, pVorbis->push.pData, (int)pVorbis->push.dataSize, NULL, &pVorbis->push.ppPacketData, &samplesRead);
49689  if (consumedDataSize != 0) {
49690  /* Successfully decoded a Vorbis frame. Consume the data. */
49691  pVorbis->push.dataSize -= (size_t)consumedDataSize;
49692  MA_MOVE_MEMORY(pVorbis->push.pData, ma_offset_ptr(pVorbis->push.pData, consumedDataSize), pVorbis->push.dataSize);
49693 
49694  pVorbis->push.framesConsumed = 0;
49695  pVorbis->push.framesRemaining = samplesRead;
49696 
49697  break;
49698  } else {
49699  /* Not enough data. Read more. */
49700  size_t bytesRead;
49701 
49702  /* Expand the data buffer if necessary. */
49703  if (pVorbis->push.dataCapacity == pVorbis->push.dataSize) {
49704  size_t newCap = pVorbis->push.dataCapacity + MA_VORBIS_DATA_CHUNK_SIZE;
49705  ma_uint8* pNewData;
49706 
49707  pNewData = (ma_uint8*)ma_realloc(pVorbis->push.pData, newCap, &pVorbis->allocationCallbacks);
49708  if (pNewData == NULL) {
49709  result = MA_OUT_OF_MEMORY;
49710  break;
49711  }
49712 
49713  pVorbis->push.pData = pNewData;
49714  pVorbis->push.dataCapacity = newCap;
49715  }
49716 
49717  /* We should have enough room to load some data. */
49718  result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, ma_offset_ptr(pVorbis->push.pData, pVorbis->push.dataSize), (pVorbis->push.dataCapacity - pVorbis->push.dataSize), &bytesRead);
49719  pVorbis->push.dataSize += bytesRead;
49720 
49721  if (result != MA_SUCCESS) {
49722  break; /* Failed to read any data. Get out. */
49723  }
49724  }
49725  }
49726 
49727  /* 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). */
49728  if (result != MA_SUCCESS) {
49729  break;
49730  }
49731  }
49732  } else {
49733  /* 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. */
49734  while (totalFramesRead < frameCount) {
49735  ma_uint64 framesRemaining = (frameCount - totalFramesRead);
49736  int framesRead;
49737 
49738  if (framesRemaining > INT_MAX) {
49739  framesRemaining = INT_MAX;
49740  }
49741 
49742  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. */
49743  totalFramesRead += framesRead;
49744 
49745  if (framesRead < framesRemaining) {
49746  break; /* Nothing left to read. Get out. */
49747  }
49748  }
49749  }
49750  } else {
49751  result = MA_INVALID_ARGS;
49752  }
49753 
49754  pVorbis->cursor += totalFramesRead;
49755 
49756  if (totalFramesRead == 0) {
49757  result = MA_AT_END;
49758  }
49759 
49760  if (pFramesRead != NULL) {
49761  *pFramesRead = totalFramesRead;
49762  }
49763 
49764  return result;
49765  }
49766  #else
49767  {
49768  /* vorbis is disabled. Should never hit this since initialization would have failed. */
49770 
49771  (void)pFramesOut;
49772  (void)frameCount;
49773  (void)pFramesRead;
49774 
49775  return MA_NOT_IMPLEMENTED;
49776  }
49777  #endif
49778 }
49779 
49780 MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64 frameIndex)
49781 {
49782  if (pVorbis == NULL) {
49783  return MA_INVALID_ARGS;
49784  }
49785 
49786  #if !defined(MA_NO_VORBIS)
49787  {
49788  /* Different seeking methods depending on whether or not we're using push mode. */
49789  if (pVorbis->usingPushMode) {
49790  /* Push mode. This is the complex case. */
49791  ma_result result;
49792  float buffer[4096];
49793 
49794  /*
49795  This is terribly inefficient because stb_vorbis does not have a good seeking solution with it's push API. Currently this just performs
49796  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
49797  find the one containing the sample we need. Then we know exactly where to seek for stb_vorbis.
49798 
49799  TODO: Use seeking logic documented for stb_vorbis_flush_pushdata().
49800  */
49801 
49802  /* Seek to the start of the file to begin with. */
49803  result = pVorbis->onSeek(pVorbis->pReadSeekTellUserData, 0, ma_seek_origin_start);
49804  if (result != MA_SUCCESS) {
49805  return result;
49806  }
49807 
49808  stb_vorbis_flush_pushdata(pVorbis->stb);
49809  pVorbis->push.framesRemaining = 0;
49810  pVorbis->push.dataSize = 0;
49811 
49812  /* Move the cursor back to the start. We'll increment this in the loop below. */
49813  pVorbis->cursor = 0;
49814 
49815  while (pVorbis->cursor < frameIndex) {
49816  ma_uint64 framesRead;
49817  ma_uint64 framesToRead = ma_countof(buffer)/pVorbis->channels;
49818  if (framesToRead > (frameIndex - pVorbis->cursor)) {
49819  framesToRead = (frameIndex - pVorbis->cursor);
49820  }
49821 
49822  result = ma_stbvorbis_read_pcm_frames(pVorbis, buffer, framesToRead, &framesRead);
49823  pVorbis->cursor += framesRead;
49824 
49825  if (result != MA_SUCCESS) {
49826  return result;
49827  }
49828  }
49829  } else {
49830  /* Pull mode. This is the simple case. */
49831  int vorbisResult;
49832 
49833  if (frameIndex > UINT_MAX) {
49834  return MA_INVALID_ARGS; /* Trying to seek beyond the 32-bit maximum of stb_vorbis. */
49835  }
49836 
49837  vorbisResult = stb_vorbis_seek(pVorbis->stb, (unsigned int)frameIndex); /* Safe cast. */
49838  if (vorbisResult == 0) {
49839  return MA_ERROR; /* See failed. */
49840  }
49841 
49842  pVorbis->cursor = frameIndex;
49843  }
49844 
49845  return MA_SUCCESS;
49846  }
49847  #else
49848  {
49849  /* vorbis is disabled. Should never hit this since initialization would have failed. */
49851 
49852  (void)frameIndex;
49853 
49854  return MA_NOT_IMPLEMENTED;
49855  }
49856  #endif
49857 }
49858 
49859 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)
49860 {
49861  /* Defaults for safety. */
49862  if (pFormat != NULL) {
49863  *pFormat = ma_format_unknown;
49864  }
49865  if (pChannels != NULL) {
49866  *pChannels = 0;
49867  }
49868  if (pSampleRate != NULL) {
49869  *pSampleRate = 0;
49870  }
49871  if (pChannelMap != NULL) {
49872  MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
49873  }
49874 
49875  if (pVorbis == NULL) {
49876  return MA_INVALID_OPERATION;
49877  }
49878 
49879  if (pFormat != NULL) {
49880  *pFormat = pVorbis->format;
49881  }
49882 
49883  #if !defined(MA_NO_VORBIS)
49884  {
49885  if (pChannels != NULL) {
49886  *pChannels = pVorbis->channels;
49887  }
49888 
49889  if (pSampleRate != NULL) {
49890  *pSampleRate = pVorbis->sampleRate;
49891  }
49892 
49893  if (pChannelMap != NULL) {
49894  ma_get_standard_channel_map(ma_standard_channel_map_vorbis, (ma_uint32)ma_min(pVorbis->channels, channelMapCap), pChannelMap);
49895  }
49896 
49897  return MA_SUCCESS;
49898  }
49899  #else
49900  {
49901  /* vorbis is disabled. Should never hit this since initialization would have failed. */
49903  return MA_NOT_IMPLEMENTED;
49904  }
49905  #endif
49906 }
49907 
49908 MA_API ma_result ma_stbvorbis_get_cursor_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pCursor)
49909 {
49910  if (pCursor == NULL) {
49911  return MA_INVALID_ARGS;
49912  }
49913 
49914  *pCursor = 0; /* Safety. */
49915 
49916  if (pVorbis == NULL) {
49917  return MA_INVALID_ARGS;
49918  }
49919 
49920  #if !defined(MA_NO_VORBIS)
49921  {
49922  *pCursor = pVorbis->cursor;
49923 
49924  return MA_SUCCESS;
49925  }
49926  #else
49927  {
49928  /* vorbis is disabled. Should never hit this since initialization would have failed. */
49930  return MA_NOT_IMPLEMENTED;
49931  }
49932  #endif
49933 }
49934 
49935 MA_API ma_result ma_stbvorbis_get_length_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pLength)
49936 {
49937  if (pLength == NULL) {
49938  return MA_INVALID_ARGS;
49939  }
49940 
49941  *pLength = 0; /* Safety. */
49942 
49943  if (pVorbis == NULL) {
49944  return MA_INVALID_ARGS;
49945  }
49946 
49947  #if !defined(MA_NO_VORBIS)
49948  {
49949  if (pVorbis->usingPushMode) {
49950  *pLength = 0; /* I don't know of a good way to determine this reliably with stb_vorbis and push mode. */
49951  } else {
49952  *pLength = stb_vorbis_stream_length_in_samples(pVorbis->stb);
49953  }
49954 
49955  return MA_SUCCESS;
49956  }
49957  #else
49958  {
49959  /* vorbis is disabled. Should never hit this since initialization would have failed. */
49961  return MA_NOT_IMPLEMENTED;
49962  }
49963  #endif
49964 }
49965 
49966 
49967 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)
49968 {
49969  ma_result result;
49970  ma_stbvorbis* pVorbis;
49971 
49972  (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. */
49973 
49974  /* For now we're just allocating the decoder backend on the heap. */
49975  pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
49976  if (pVorbis == NULL) {
49977  return MA_OUT_OF_MEMORY;
49978  }
49979 
49980  result = ma_stbvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
49981  if (result != MA_SUCCESS) {
49982  ma_free(pVorbis, pAllocationCallbacks);
49983  return result;
49984  }
49985 
49986  *ppBackend = pVorbis;
49987 
49988  return MA_SUCCESS;
49989 }
49990 
49991 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)
49992 {
49993  ma_result result;
49994  ma_stbvorbis* pVorbis;
49995 
49996  (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. */
49997 
49998  /* For now we're just allocating the decoder backend on the heap. */
49999  pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
50000  if (pVorbis == NULL) {
50001  return MA_OUT_OF_MEMORY;
50002  }
50003 
50004  result = ma_stbvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
50005  if (result != MA_SUCCESS) {
50006  ma_free(pVorbis, pAllocationCallbacks);
50007  return result;
50008  }
50009 
50010  *ppBackend = pVorbis;
50011 
50012  return MA_SUCCESS;
50013 }
50014 
50015 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)
50016 {
50017  ma_result result;
50018  ma_stbvorbis* pVorbis;
50019 
50020  (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. */
50021 
50022  /* For now we're just allocating the decoder backend on the heap. */
50023  pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
50024  if (pVorbis == NULL) {
50025  return MA_OUT_OF_MEMORY;
50026  }
50027 
50028  result = ma_stbvorbis_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pVorbis);
50029  if (result != MA_SUCCESS) {
50030  ma_free(pVorbis, pAllocationCallbacks);
50031  return result;
50032  }
50033 
50034  *ppBackend = pVorbis;
50035 
50036  return MA_SUCCESS;
50037 }
50038 
50039 static void ma_decoding_backend_uninit__stbvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
50040 {
50041  ma_stbvorbis* pVorbis = (ma_stbvorbis*)pBackend;
50042 
50043  (void)pUserData;
50044 
50045  ma_stbvorbis_uninit(pVorbis, pAllocationCallbacks);
50046  ma_free(pVorbis, pAllocationCallbacks);
50047 }
50048 
50049 static ma_result ma_decoding_backend_get_channel_map__stbvorbis(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
50050 {
50051  ma_stbvorbis* pVorbis = (ma_stbvorbis*)pBackend;
50052 
50053  (void)pUserData;
50054 
50055  return ma_stbvorbis_get_data_format(pVorbis, NULL, NULL, NULL, pChannelMap, channelMapCap);
50056 }
50057 
50058 static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_stbvorbis =
50059 {
50060  ma_decoding_backend_init__stbvorbis,
50061  ma_decoding_backend_init_file__stbvorbis,
50062  NULL, /* onInitFileW() */
50063  ma_decoding_backend_init_memory__stbvorbis,
50064  ma_decoding_backend_uninit__stbvorbis,
50065  ma_decoding_backend_get_channel_map__stbvorbis
50066 };
50067 
50068 static ma_result ma_decoder_init_vorbis__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50069 {
50070  return ma_decoder_init_from_vtable(&g_ma_decoding_backend_vtable_stbvorbis, NULL, pConfig, pDecoder);
50071 }
50072 #endif /* STB_VORBIS_INCLUDE_STB_VORBIS_H */
50073 
50074 
50075 
50077 {
50078  MA_ASSERT(pDecoder != NULL);
50079 
50080  if (pConfig != NULL) {
50082  } else {
50084  return MA_SUCCESS;
50085  }
50086 }
50087 
50088 static ma_result ma_decoder__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
50089 {
50090  ma_uint64 framesRead = ma_decoder_read_pcm_frames((ma_decoder*)pDataSource, pFramesOut, frameCount);
50091 
50092  if (pFramesRead != NULL) {
50093  *pFramesRead = framesRead;
50094  }
50095 
50096  if (framesRead == 0) {
50097  return MA_AT_END;
50098  }
50099 
50100  return MA_SUCCESS;
50101 }
50102 
50103 static ma_result ma_decoder__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
50104 {
50105  return ma_decoder_seek_to_pcm_frame((ma_decoder*)pDataSource, frameIndex);
50106 }
50107 
50108 static ma_result ma_decoder__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
50109 {
50110  ma_decoder* pDecoder = (ma_decoder*)pDataSource;
50111 
50112  *pFormat = pDecoder->outputFormat;
50113  *pChannels = pDecoder->outputChannels;
50114  *pSampleRate = pDecoder->outputSampleRate;
50115 
50116  return MA_SUCCESS;
50117 }
50118 
50120 {
50121  ma_decoder* pDecoder = (ma_decoder*)pDataSource;
50122 
50123  return ma_decoder_get_cursor_in_pcm_frames(pDecoder, pCursor);
50124 }
50125 
50127 {
50128  ma_decoder* pDecoder = (ma_decoder*)pDataSource;
50129 
50130  *pLength = ma_decoder_get_length_in_pcm_frames(pDecoder);
50131  if (*pLength == 0) {
50132  return MA_NOT_IMPLEMENTED;
50133  }
50134 
50135  return MA_SUCCESS;
50136 }
50137 
50139 {
50142  NULL, /* onMap */
50143  NULL, /* onUnmap */
50147 };
50148 
50149 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)
50150 {
50151  ma_result result;
50152  ma_data_source_config dataSourceConfig;
50153 
50154  MA_ASSERT(pConfig != NULL);
50155 
50156  if (pDecoder == NULL) {
50157  return MA_INVALID_ARGS;
50158  }
50159 
50160  MA_ZERO_OBJECT(pDecoder);
50161 
50162  if (onRead == NULL || onSeek == NULL) {
50163  return MA_INVALID_ARGS;
50164  }
50165 
50166  dataSourceConfig = ma_data_source_config_init();
50167  dataSourceConfig.vtable = &g_ma_decoder_data_source_vtable;
50168 
50169  result = ma_data_source_init(&dataSourceConfig, &pDecoder->ds);
50170  if (result != MA_SUCCESS) {
50171  return result;
50172  }
50173 
50174  pDecoder->onRead = onRead;
50175  pDecoder->onSeek = onSeek;
50176  pDecoder->onTell = onTell;
50177  pDecoder->pUserData = pUserData;
50178 
50179  result = ma_decoder__init_allocation_callbacks(pConfig, pDecoder);
50180  if (result != MA_SUCCESS) {
50181  ma_data_source_uninit(&pDecoder->ds);
50182  return result;
50183  }
50184 
50185  return MA_SUCCESS;
50186 }
50187 
50188 static ma_result ma_decoder__postinit(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50189 {
50190  ma_result result = MA_SUCCESS;
50191 
50192  /* Basic validation in case the internal decoder supports different limits to miniaudio. */
50193  {
50194  /* TODO: Remove this block once we remove MA_MIN_CHANNELS and MA_MAX_CHANNELS. */
50195  ma_uint32 internalChannels;
50196  ma_data_source_get_data_format(pDecoder->pBackend, NULL, &internalChannels, NULL);
50197 
50198  if (internalChannels < MA_MIN_CHANNELS || internalChannels > MA_MAX_CHANNELS) {
50199  result = MA_INVALID_DATA;
50200  }
50201  }
50202 
50203  if (result == MA_SUCCESS) {
50204  result = ma_decoder__init_data_converter(pDecoder, pConfig);
50205  }
50206 
50207  /* If we failed post initialization we need to uninitialize the decoder before returning to prevent a memory leak. */
50208  if (result != MA_SUCCESS) {
50209  ma_decoder_uninit(pDecoder);
50210  return result;
50211  }
50212 
50213  return result;
50214 }
50215 
50216 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)
50217 {
50218 #ifdef MA_HAS_WAV
50220 
50222  config.encodingFormat = ma_encoding_format_wav;
50223 
50224  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
50225 #else
50226  (void)onRead;
50227  (void)onSeek;
50228  (void)pUserData;
50229  (void)pConfig;
50230  (void)pDecoder;
50231  return MA_NO_BACKEND;
50232 #endif
50233 }
50234 
50235 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)
50236 {
50237 #ifdef MA_HAS_FLAC
50239 
50241  config.encodingFormat = ma_encoding_format_flac;
50242 
50243  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
50244 #else
50245  (void)onRead;
50246  (void)onSeek;
50247  (void)pUserData;
50248  (void)pConfig;
50249  (void)pDecoder;
50250  return MA_NO_BACKEND;
50251 #endif
50252 }
50253 
50254 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)
50255 {
50256 #ifdef MA_HAS_MP3
50258 
50260  config.encodingFormat = ma_encoding_format_mp3;
50261 
50262  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
50263 #else
50264  (void)onRead;
50265  (void)onSeek;
50266  (void)pUserData;
50267  (void)pConfig;
50268  (void)pDecoder;
50269  return MA_NO_BACKEND;
50270 #endif
50271 }
50272 
50273 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)
50274 {
50275 #ifdef MA_HAS_VORBIS
50277 
50279  config.encodingFormat = ma_encoding_format_vorbis;
50280 
50281  return ma_decoder_init(onRead, onSeek, pUserData, &config, pDecoder);
50282 #else
50283  (void)onRead;
50284  (void)onSeek;
50285  (void)pUserData;
50286  (void)pConfig;
50287  (void)pDecoder;
50288  return MA_NO_BACKEND;
50289 #endif
50290 }
50291 
50292 
50293 
50294 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)
50295 {
50296  ma_result result = MA_NO_BACKEND;
50297 
50298  MA_ASSERT(pConfig != NULL);
50299  MA_ASSERT(pDecoder != NULL);
50300 
50301  /* Silence some warnings in the case that we don't have any decoder backends enabled. */
50302  (void)onRead;
50303  (void)onSeek;
50304  (void)pUserData;
50305 
50306 
50307  /* If we've specified a specific encoding type, try that first. */
50308  if (pConfig->encodingFormat != ma_encoding_format_unknown) {
50309  #ifdef MA_HAS_WAV
50310  if (pConfig->encodingFormat == ma_encoding_format_wav) {
50311  result = ma_decoder_init_wav__internal(pConfig, pDecoder);
50312  }
50313  #endif
50314  #ifdef MA_HAS_FLAC
50315  if (pConfig->encodingFormat == ma_encoding_format_flac) {
50316  result = ma_decoder_init_flac__internal(pConfig, pDecoder);
50317  }
50318  #endif
50319  #ifdef MA_HAS_MP3
50320  if (pConfig->encodingFormat == ma_encoding_format_mp3) {
50321  result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
50322  }
50323  #endif
50324  #ifdef MA_HAS_VORBIS
50325  if (pConfig->encodingFormat == ma_encoding_format_vorbis) {
50326  result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
50327  }
50328  #endif
50329 
50330  /* If we weren't able to initialize the decoder, seek back to the start to give the next attempts a clean start. */
50331  if (result != MA_SUCCESS) {
50332  onSeek(pDecoder, 0, ma_seek_origin_start);
50333  }
50334  }
50335 
50336  if (result != MA_SUCCESS) {
50337  /* Getting here means we couldn't load a specific decoding backend based on the encoding format. */
50338 
50339  /*
50340  We use trial and error to open a decoder. We prioritize custom decoders so that if they
50341  implement the same encoding format they take priority over the built-in decoders.
50342  */
50343  if (result != MA_SUCCESS) {
50344  result = ma_decoder_init_custom__internal(pConfig, pDecoder);
50345  if (result != MA_SUCCESS) {
50346  onSeek(pDecoder, 0, ma_seek_origin_start);
50347  }
50348  }
50349 
50350  /*
50351  If we get to this point and we still haven't found a decoder, and the caller has requested a
50352  specific encoding format, there's no hope for it. Abort.
50353  */
50354  if (pConfig->encodingFormat != ma_encoding_format_unknown) {
50355  return MA_NO_BACKEND;
50356  }
50357 
50358  #ifdef MA_HAS_WAV
50359  if (result != MA_SUCCESS) {
50360  result = ma_decoder_init_wav__internal(pConfig, pDecoder);
50361  if (result != MA_SUCCESS) {
50362  onSeek(pDecoder, 0, ma_seek_origin_start);
50363  }
50364  }
50365  #endif
50366  #ifdef MA_HAS_FLAC
50367  if (result != MA_SUCCESS) {
50368  result = ma_decoder_init_flac__internal(pConfig, pDecoder);
50369  if (result != MA_SUCCESS) {
50370  onSeek(pDecoder, 0, ma_seek_origin_start);
50371  }
50372  }
50373  #endif
50374  #ifdef MA_HAS_MP3
50375  if (result != MA_SUCCESS) {
50376  result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
50377  if (result != MA_SUCCESS) {
50378  onSeek(pDecoder, 0, ma_seek_origin_start);
50379  }
50380  }
50381  #endif
50382  #ifdef MA_HAS_VORBIS
50383  if (result != MA_SUCCESS) {
50384  result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
50385  if (result != MA_SUCCESS) {
50386  onSeek(pDecoder, 0, ma_seek_origin_start);
50387  }
50388  }
50389  #endif
50390  }
50391 
50392  if (result != MA_SUCCESS) {
50393  return result;
50394  }
50395 
50396  return ma_decoder__postinit(pConfig, pDecoder);
50397 }
50398 
50399 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)
50400 {
50402  ma_result result;
50403 
50405 
50406  result = ma_decoder__preinit(onRead, onSeek, NULL, pUserData, &config, pDecoder);
50407  if (result != MA_SUCCESS) {
50408  return result;
50409  }
50410 
50411  return ma_decoder_init__internal(onRead, onSeek, pUserData, &config, pDecoder);
50412 }
50413 
50414 
50415 static size_t ma_decoder__on_read_memory(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead)
50416 {
50417  size_t bytesRemaining;
50418 
50419  MA_ASSERT(pDecoder->data.memory.dataSize >= pDecoder->data.memory.currentReadPos);
50420 
50421  bytesRemaining = pDecoder->data.memory.dataSize - pDecoder->data.memory.currentReadPos;
50422  if (bytesToRead > bytesRemaining) {
50423  bytesToRead = bytesRemaining;
50424  }
50425 
50426  if (bytesToRead > 0) {
50427  MA_COPY_MEMORY(pBufferOut, pDecoder->data.memory.pData + pDecoder->data.memory.currentReadPos, bytesToRead);
50428  pDecoder->data.memory.currentReadPos += bytesToRead;
50429  }
50430 
50431  return bytesToRead;
50432 }
50433 
50434 static ma_bool32 ma_decoder__on_seek_memory(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin)
50435 {
50436  if (byteOffset > 0 && (ma_uint64)byteOffset > MA_SIZE_MAX) {
50437  return MA_FALSE; /* Too far. */
50438  }
50439 
50440  if (origin == ma_seek_origin_current) {
50441  if (byteOffset > 0) {
50442  if (pDecoder->data.memory.currentReadPos + byteOffset > pDecoder->data.memory.dataSize) {
50443  byteOffset = (ma_int64)(pDecoder->data.memory.dataSize - pDecoder->data.memory.currentReadPos); /* Trying to seek too far forward. */
50444  }
50445 
50446  pDecoder->data.memory.currentReadPos += (size_t)byteOffset;
50447  } else {
50448  if (pDecoder->data.memory.currentReadPos < (size_t)-byteOffset) {
50449  byteOffset = -(ma_int64)pDecoder->data.memory.currentReadPos; /* Trying to seek too far backwards. */
50450  }
50451 
50452  pDecoder->data.memory.currentReadPos -= (size_t)-byteOffset;
50453  }
50454  } else {
50455  if (origin == ma_seek_origin_end) {
50456  if (byteOffset < 0) {
50457  byteOffset = -byteOffset;
50458  }
50459 
50460  if (byteOffset > (ma_int64)pDecoder->data.memory.dataSize) {
50461  pDecoder->data.memory.currentReadPos = 0; /* Trying to seek too far back. */
50462  } else {
50463  pDecoder->data.memory.currentReadPos = pDecoder->data.memory.dataSize - (size_t)byteOffset;
50464  }
50465  } else {
50466  if ((size_t)byteOffset <= pDecoder->data.memory.dataSize) {
50467  pDecoder->data.memory.currentReadPos = (size_t)byteOffset;
50468  } else {
50469  pDecoder->data.memory.currentReadPos = pDecoder->data.memory.dataSize; /* Trying to seek too far forward. */
50470  }
50471  }
50472  }
50473 
50474  return MA_TRUE;
50475 }
50476 
50477 static ma_result ma_decoder__on_tell_memory(ma_decoder* pDecoder, ma_int64* pCursor)
50478 {
50479  MA_ASSERT(pDecoder != NULL);
50480  MA_ASSERT(pCursor != NULL);
50481 
50482  *pCursor = (ma_int64)pDecoder->data.memory.currentReadPos;
50483 
50484  return MA_SUCCESS;
50485 }
50486 
50487 static ma_result ma_decoder__preinit_memory(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50488 {
50490  if (result != MA_SUCCESS) {
50491  return result;
50492  }
50493 
50494  if (pData == NULL || dataSize == 0) {
50495  return MA_INVALID_ARGS;
50496  }
50497 
50498  pDecoder->data.memory.pData = (const ma_uint8*)pData;
50499  pDecoder->data.memory.dataSize = dataSize;
50500  pDecoder->data.memory.currentReadPos = 0;
50501 
50502  (void)pConfig;
50503  return MA_SUCCESS;
50504 }
50505 
50506 MA_API ma_result ma_decoder_init_memory(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50507 {
50509  ma_result result;
50510 
50511  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
50512 
50513  result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
50514  if (result != MA_SUCCESS) {
50515  return result;
50516  }
50517 
50519 }
50520 
50521 MA_API ma_result ma_decoder_init_memory_wav(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50522 {
50523 #ifdef MA_HAS_WAV
50525 
50526  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
50527  config.encodingFormat = ma_encoding_format_wav;
50528 
50529  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
50530 #else
50531  (void)pData;
50532  (void)dataSize;
50533  (void)pConfig;
50534  (void)pDecoder;
50535  return MA_NO_BACKEND;
50536 #endif
50537 }
50538 
50539 MA_API ma_result ma_decoder_init_memory_flac(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50540 {
50541 #ifdef MA_HAS_FLAC
50543 
50544  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
50545  config.encodingFormat = ma_encoding_format_flac;
50546 
50547  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
50548 #else
50549  (void)pData;
50550  (void)dataSize;
50551  (void)pConfig;
50552  (void)pDecoder;
50553  return MA_NO_BACKEND;
50554 #endif
50555 }
50556 
50557 MA_API ma_result ma_decoder_init_memory_mp3(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50558 {
50559 #ifdef MA_HAS_MP3
50561 
50562  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
50563  config.encodingFormat = ma_encoding_format_mp3;
50564 
50565  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
50566 #else
50567  (void)pData;
50568  (void)dataSize;
50569  (void)pConfig;
50570  (void)pDecoder;
50571  return MA_NO_BACKEND;
50572 #endif
50573 }
50574 
50575 MA_API ma_result ma_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50576 {
50577 #ifdef MA_HAS_VORBIS
50579 
50580  config = ma_decoder_config_init_copy(pConfig); /* Make sure the config is not NULL. */
50581  config.encodingFormat = ma_encoding_format_vorbis;
50582 
50583  return ma_decoder_init_memory(pData, dataSize, &config, pDecoder);
50584 #else
50585  (void)pData;
50586  (void)dataSize;
50587  (void)pConfig;
50588  (void)pDecoder;
50589  return MA_NO_BACKEND;
50590 #endif
50591 }
50592 
50593 
50594 
50595 #if defined(MA_HAS_WAV) || \
50596  defined(MA_HAS_MP3) || \
50597  defined(MA_HAS_FLAC) || \
50598  defined(MA_HAS_VORBIS) || \
50599  defined(MA_HAS_OPUS)
50600 #define MA_HAS_PATH_API
50601 #endif
50602 
50603 #if defined(MA_HAS_PATH_API)
50604 static const char* ma_path_file_name(const char* path)
50605 {
50606  const char* fileName;
50607 
50608  if (path == NULL) {
50609  return NULL;
50610  }
50611 
50612  fileName = path;
50613 
50614  /* We just loop through the path until we find the last slash. */
50615  while (path[0] != '\0') {
50616  if (path[0] == '/' || path[0] == '\\') {
50617  fileName = path;
50618  }
50619 
50620  path += 1;
50621  }
50622 
50623  /* At this point the file name is sitting on a slash, so just move forward. */
50624  while (fileName[0] != '\0' && (fileName[0] == '/' || fileName[0] == '\\')) {
50625  fileName += 1;
50626  }
50627 
50628  return fileName;
50629 }
50630 
50631 static const wchar_t* ma_path_file_name_w(const wchar_t* path)
50632 {
50633  const wchar_t* fileName;
50634 
50635  if (path == NULL) {
50636  return NULL;
50637  }
50638 
50639  fileName = path;
50640 
50641  /* We just loop through the path until we find the last slash. */
50642  while (path[0] != '\0') {
50643  if (path[0] == '/' || path[0] == '\\') {
50644  fileName = path;
50645  }
50646 
50647  path += 1;
50648  }
50649 
50650  /* At this point the file name is sitting on a slash, so just move forward. */
50651  while (fileName[0] != '\0' && (fileName[0] == '/' || fileName[0] == '\\')) {
50652  fileName += 1;
50653  }
50654 
50655  return fileName;
50656 }
50657 
50658 
50659 static const char* ma_path_extension(const char* path)
50660 {
50661  const char* extension;
50662  const char* lastOccurance;
50663 
50664  if (path == NULL) {
50665  path = "";
50666  }
50667 
50668  extension = ma_path_file_name(path);
50669  lastOccurance = NULL;
50670 
50671  /* Just find the last '.' and return. */
50672  while (extension[0] != '\0') {
50673  if (extension[0] == '.') {
50674  extension += 1;
50675  lastOccurance = extension;
50676  }
50677 
50678  extension += 1;
50679  }
50680 
50681  return (lastOccurance != NULL) ? lastOccurance : extension;
50682 }
50683 
50684 static const wchar_t* ma_path_extension_w(const wchar_t* path)
50685 {
50686  const wchar_t* extension;
50687  const wchar_t* lastOccurance;
50688 
50689  if (path == NULL) {
50690  path = L"";
50691  }
50692 
50693  extension = ma_path_file_name_w(path);
50694  lastOccurance = NULL;
50695 
50696  /* Just find the last '.' and return. */
50697  while (extension[0] != '\0') {
50698  if (extension[0] == '.') {
50699  extension += 1;
50700  lastOccurance = extension;
50701  }
50702 
50703  extension += 1;
50704  }
50705 
50706  return (lastOccurance != NULL) ? lastOccurance : extension;
50707 }
50708 
50709 
50710 static ma_bool32 ma_path_extension_equal(const char* path, const char* extension)
50711 {
50712  const char* ext1;
50713  const char* ext2;
50714 
50715  if (path == NULL || extension == NULL) {
50716  return MA_FALSE;
50717  }
50718 
50719  ext1 = extension;
50720  ext2 = ma_path_extension(path);
50721 
50722 #if defined(_MSC_VER) || defined(__DMC__)
50723  return _stricmp(ext1, ext2) == 0;
50724 #else
50725  return strcasecmp(ext1, ext2) == 0;
50726 #endif
50727 }
50728 
50729 static ma_bool32 ma_path_extension_equal_w(const wchar_t* path, const wchar_t* extension)
50730 {
50731  const wchar_t* ext1;
50732  const wchar_t* ext2;
50733 
50734  if (path == NULL || extension == NULL) {
50735  return MA_FALSE;
50736  }
50737 
50738  ext1 = extension;
50739  ext2 = ma_path_extension_w(path);
50740 
50741 #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)
50742  return _wcsicmp(ext1, ext2) == 0;
50743 #else
50744  /*
50745  I'm not aware of a wide character version of strcasecmp(). I'm therefore converting the extensions to multibyte strings and comparing those. This
50746  isn't the most efficient way to do it, but it should work OK.
50747  */
50748  {
50749  char ext1MB[4096];
50750  char ext2MB[4096];
50751  const wchar_t* pext1 = ext1;
50752  const wchar_t* pext2 = ext2;
50753  mbstate_t mbs1;
50754  mbstate_t mbs2;
50755 
50756  MA_ZERO_OBJECT(&mbs1);
50757  MA_ZERO_OBJECT(&mbs2);
50758 
50759  if (wcsrtombs(ext1MB, &pext1, sizeof(ext1MB), &mbs1) == (size_t)-1) {
50760  return MA_FALSE;
50761  }
50762  if (wcsrtombs(ext2MB, &pext2, sizeof(ext2MB), &mbs2) == (size_t)-1) {
50763  return MA_FALSE;
50764  }
50765 
50766  return strcasecmp(ext1MB, ext2MB) == 0;
50767  }
50768 #endif
50769 }
50770 #endif /* MA_HAS_PATH_API */
50771 
50772 
50773 
50774 static size_t ma_decoder__on_read_vfs(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead)
50775 {
50776  size_t bytesRead;
50777 
50778  MA_ASSERT(pDecoder != NULL);
50779  MA_ASSERT(pBufferOut != NULL);
50780 
50781  ma_vfs_or_default_read(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file, pBufferOut, bytesToRead, &bytesRead);
50782 
50783  return bytesRead;
50784 }
50785 
50786 static ma_bool32 ma_decoder__on_seek_vfs(ma_decoder* pDecoder, ma_int64 offset, ma_seek_origin origin)
50787 {
50788  ma_result result;
50789 
50790  MA_ASSERT(pDecoder != NULL);
50791 
50792  result = ma_vfs_or_default_seek(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file, offset, origin);
50793  if (result != MA_SUCCESS) {
50794  return MA_FALSE;
50795  }
50796 
50797  return MA_TRUE;
50798 }
50799 
50800 static ma_result ma_decoder__on_tell_vfs(ma_decoder* pDecoder, ma_int64* pCursor)
50801 {
50802  MA_ASSERT(pDecoder != NULL);
50803 
50804  return ma_vfs_or_default_tell(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file, pCursor);
50805 }
50806 
50807 static ma_result ma_decoder__preinit_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50808 {
50809  ma_result result;
50810  ma_vfs_file file;
50811 
50813  if (result != MA_SUCCESS) {
50814  return result;
50815  }
50816 
50817  if (pFilePath == NULL || pFilePath[0] == '\0') {
50818  return MA_INVALID_ARGS;
50819  }
50820 
50821  result = ma_vfs_or_default_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
50822  if (result != MA_SUCCESS) {
50823  return result;
50824  }
50825 
50826  pDecoder->data.vfs.pVFS = pVFS;
50827  pDecoder->data.vfs.file = file;
50828 
50829  return MA_SUCCESS;
50830 }
50831 
50832 MA_API ma_result ma_decoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50833 {
50834  ma_result result;
50836 
50838  result = ma_decoder__preinit_vfs(pVFS, pFilePath, &config, pDecoder);
50839  if (result != MA_SUCCESS) {
50840  return result;
50841  }
50842 
50843  result = MA_NO_BACKEND;
50844 
50845  if (config.encodingFormat != ma_encoding_format_unknown) {
50846  #ifdef MA_HAS_WAV
50847  if (config.encodingFormat == ma_encoding_format_wav) {
50848  result = ma_decoder_init_wav__internal(&config, pDecoder);
50849  }
50850  #endif
50851  #ifdef MA_HAS_FLAC
50852  if (config.encodingFormat == ma_encoding_format_flac) {
50853  result = ma_decoder_init_flac__internal(&config, pDecoder);
50854  }
50855  #endif
50856  #ifdef MA_HAS_MP3
50857  if (config.encodingFormat == ma_encoding_format_mp3) {
50858  result = ma_decoder_init_mp3__internal(&config, pDecoder);
50859  }
50860  #endif
50861  #ifdef MA_HAS_VORBIS
50862  if (config.encodingFormat == ma_encoding_format_vorbis) {
50863  result = ma_decoder_init_vorbis__internal(&config, pDecoder);
50864  }
50865  #endif
50866 
50867  /* Make sure we seek back to the start if we didn't initialize a decoder successfully so the next attempts have a fresh start. */
50868  if (result != MA_SUCCESS) {
50870  }
50871  }
50872 
50873  if (result != MA_SUCCESS) {
50874  /* Getting here means we weren't able to initialize a decoder of a specific encoding format. */
50875 
50876  /*
50877  We use trial and error to open a decoder. We prioritize custom decoders so that if they
50878  implement the same encoding format they take priority over the built-in decoders.
50879  */
50880  if (result != MA_SUCCESS) {
50881  result = ma_decoder_init_custom__internal(&config, pDecoder);
50882  if (result != MA_SUCCESS) {
50884  }
50885  }
50886 
50887  /*
50888  If we get to this point and we still haven't found a decoder, and the caller has requested a
50889  specific encoding format, there's no hope for it. Abort.
50890  */
50891  if (config.encodingFormat != ma_encoding_format_unknown) {
50892  return MA_NO_BACKEND;
50893  }
50894 
50895  #ifdef MA_HAS_WAV
50896  if (result != MA_SUCCESS && ma_path_extension_equal(pFilePath, "wav")) {
50897  result = ma_decoder_init_wav__internal(&config, pDecoder);
50898  if (result != MA_SUCCESS) {
50900  }
50901  }
50902  #endif
50903  #ifdef MA_HAS_FLAC
50904  if (result != MA_SUCCESS && ma_path_extension_equal(pFilePath, "flac")) {
50905  result = ma_decoder_init_flac__internal(&config, pDecoder);
50906  if (result != MA_SUCCESS) {
50908  }
50909  }
50910  #endif
50911  #ifdef MA_HAS_MP3
50912  if (result != MA_SUCCESS && ma_path_extension_equal(pFilePath, "mp3")) {
50913  result = ma_decoder_init_mp3__internal(&config, pDecoder);
50914  if (result != MA_SUCCESS) {
50916  }
50917  }
50918  #endif
50919  }
50920 
50921  /* If we still haven't got a result just use trial and error. Otherwise we can finish up. */
50922  if (result != MA_SUCCESS) {
50924  } else {
50925  result = ma_decoder__postinit(&config, pDecoder);
50926  }
50927 
50928  if (result != MA_SUCCESS) {
50929  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. */
50930  ma_vfs_or_default_close(pVFS, pDecoder->data.vfs.file);
50931  }
50932 
50933  return result;
50934  }
50935 
50936  return MA_SUCCESS;
50937 }
50938 
50939 MA_API ma_result ma_decoder_init_vfs_wav(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50940 {
50941 #ifdef MA_HAS_WAV
50943 
50945  config.encodingFormat = ma_encoding_format_wav;
50946 
50947  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
50948 #else
50949  (void)pVFS;
50950  (void)pFilePath;
50951  (void)pConfig;
50952  (void)pDecoder;
50953  return MA_NO_BACKEND;
50954 #endif
50955 }
50956 
50957 MA_API ma_result ma_decoder_init_vfs_flac(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50958 {
50959 #ifdef MA_HAS_FLAC
50961 
50963  config.encodingFormat = ma_encoding_format_flac;
50964 
50965  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
50966 #else
50967  (void)pVFS;
50968  (void)pFilePath;
50969  (void)pConfig;
50970  (void)pDecoder;
50971  return MA_NO_BACKEND;
50972 #endif
50973 }
50974 
50975 MA_API ma_result ma_decoder_init_vfs_mp3(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50976 {
50977 #ifdef MA_HAS_MP3
50979 
50981  config.encodingFormat = ma_encoding_format_mp3;
50982 
50983  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
50984 #else
50985  (void)pVFS;
50986  (void)pFilePath;
50987  (void)pConfig;
50988  (void)pDecoder;
50989  return MA_NO_BACKEND;
50990 #endif
50991 }
50992 
50993 MA_API ma_result ma_decoder_init_vfs_vorbis(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
50994 {
50995 #ifdef MA_HAS_VORBIS
50997 
50999  config.encodingFormat = ma_encoding_format_vorbis;
51000 
51001  return ma_decoder_init_vfs(pVFS, pFilePath, &config, pDecoder);
51002 #else
51003  (void)pVFS;
51004  (void)pFilePath;
51005  (void)pConfig;
51006  (void)pDecoder;
51007  return MA_NO_BACKEND;
51008 #endif
51009 }
51010 
51011 
51012 
51013 static ma_result ma_decoder__preinit_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51014 {
51015  ma_result result;
51016  ma_vfs_file file;
51017 
51019  if (result != MA_SUCCESS) {
51020  return result;
51021  }
51022 
51023  if (pFilePath == NULL || pFilePath[0] == '\0') {
51024  return MA_INVALID_ARGS;
51025  }
51026 
51027  result = ma_vfs_or_default_open_w(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
51028  if (result != MA_SUCCESS) {
51029  return result;
51030  }
51031 
51032  pDecoder->data.vfs.pVFS = pVFS;
51033  pDecoder->data.vfs.file = file;
51034 
51035  return MA_SUCCESS;
51036 }
51037 
51038 MA_API ma_result ma_decoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51039 {
51040  ma_result result;
51042 
51044  result = ma_decoder__preinit_vfs_w(pVFS, pFilePath, &config, pDecoder);
51045  if (result != MA_SUCCESS) {
51046  return result;
51047  }
51048 
51049  result = MA_NO_BACKEND;
51050 
51051  if (config.encodingFormat != ma_encoding_format_unknown) {
51052  #ifdef MA_HAS_WAV
51053  if (config.encodingFormat == ma_encoding_format_wav) {
51054  result = ma_decoder_init_wav__internal(&config, pDecoder);
51055  }
51056  #endif
51057  #ifdef MA_HAS_FLAC
51058  if (config.encodingFormat == ma_encoding_format_flac) {
51059  result = ma_decoder_init_flac__internal(&config, pDecoder);
51060  }
51061  #endif
51062  #ifdef MA_HAS_MP3
51063  if (config.encodingFormat == ma_encoding_format_mp3) {
51064  result = ma_decoder_init_mp3__internal(&config, pDecoder);
51065  }
51066  #endif
51067  #ifdef MA_HAS_VORBIS
51068  if (config.encodingFormat == ma_encoding_format_vorbis) {
51069  result = ma_decoder_init_vorbis__internal(&config, pDecoder);
51070  }
51071  #endif
51072 
51073  /* Make sure we seek back to the start if we didn't initialize a decoder successfully so the next attempts have a fresh start. */
51074  if (result != MA_SUCCESS) {
51076  }
51077  }
51078 
51079  if (result != MA_SUCCESS) {
51080  /* Getting here means we weren't able to initialize a decoder of a specific encoding format. */
51081 
51082  /*
51083  We use trial and error to open a decoder. We prioritize custom decoders so that if they
51084  implement the same encoding format they take priority over the built-in decoders.
51085  */
51086  if (result != MA_SUCCESS) {
51087  result = ma_decoder_init_custom__internal(&config, pDecoder);
51088  if (result != MA_SUCCESS) {
51090  }
51091  }
51092 
51093  /*
51094  If we get to this point and we still haven't found a decoder, and the caller has requested a
51095  specific encoding format, there's no hope for it. Abort.
51096  */
51097  if (config.encodingFormat != ma_encoding_format_unknown) {
51098  return MA_NO_BACKEND;
51099  }
51100 
51101  #ifdef MA_HAS_WAV
51102  if (result != MA_SUCCESS && ma_path_extension_equal_w(pFilePath, L"wav")) {
51103  result = ma_decoder_init_wav__internal(&config, pDecoder);
51104  if (result != MA_SUCCESS) {
51106  }
51107  }
51108  #endif
51109  #ifdef MA_HAS_FLAC
51110  if (result != MA_SUCCESS && ma_path_extension_equal_w(pFilePath, L"flac")) {
51111  result = ma_decoder_init_flac__internal(&config, pDecoder);
51112  if (result != MA_SUCCESS) {
51114  }
51115  }
51116  #endif
51117  #ifdef MA_HAS_MP3
51118  if (result != MA_SUCCESS && ma_path_extension_equal_w(pFilePath, L"mp3")) {
51119  result = ma_decoder_init_mp3__internal(&config, pDecoder);
51120  if (result != MA_SUCCESS) {
51122  }
51123  }
51124  #endif
51125  }
51126 
51127  /* If we still haven't got a result just use trial and error. Otherwise we can finish up. */
51128  if (result != MA_SUCCESS) {
51130  } else {
51131  result = ma_decoder__postinit(&config, pDecoder);
51132  }
51133 
51134  if (result != MA_SUCCESS) {
51135  ma_vfs_or_default_close(pVFS, pDecoder->data.vfs.file);
51136  return result;
51137  }
51138 
51139  return MA_SUCCESS;
51140 }
51141 
51142 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)
51143 {
51144 #ifdef MA_HAS_WAV
51146 
51148  config.encodingFormat = ma_encoding_format_wav;
51149 
51150  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
51151 #else
51152  (void)pVFS;
51153  (void)pFilePath;
51154  (void)pConfig;
51155  (void)pDecoder;
51156  return MA_NO_BACKEND;
51157 #endif
51158 }
51159 
51160 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)
51161 {
51162 #ifdef MA_HAS_FLAC
51164 
51166  config.encodingFormat = ma_encoding_format_flac;
51167 
51168  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
51169 #else
51170  (void)pVFS;
51171  (void)pFilePath;
51172  (void)pConfig;
51173  (void)pDecoder;
51174  return MA_NO_BACKEND;
51175 #endif
51176 }
51177 
51178 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)
51179 {
51180 #ifdef MA_HAS_MP3
51182 
51184  config.encodingFormat = ma_encoding_format_mp3;
51185 
51186  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
51187 #else
51188  (void)pVFS;
51189  (void)pFilePath;
51190  (void)pConfig;
51191  (void)pDecoder;
51192  return MA_NO_BACKEND;
51193 #endif
51194 }
51195 
51196 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)
51197 {
51198 #ifdef MA_HAS_VORBIS
51200 
51202  config.encodingFormat = ma_encoding_format_vorbis;
51203 
51204  return ma_decoder_init_vfs_w(pVFS, pFilePath, &config, pDecoder);
51205 #else
51206  (void)pVFS;
51207  (void)pFilePath;
51208  (void)pConfig;
51209  (void)pDecoder;
51210  return MA_NO_BACKEND;
51211 #endif
51212 }
51213 
51214 
51215 
51216 MA_API ma_result ma_decoder_init_file(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51217 {
51218  return ma_decoder_init_vfs(NULL, pFilePath, pConfig, pDecoder);
51219 }
51220 
51221 MA_API ma_result ma_decoder_init_file_wav(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51222 {
51223  return ma_decoder_init_vfs_wav(NULL, pFilePath, pConfig, pDecoder);
51224 }
51225 
51226 MA_API ma_result ma_decoder_init_file_flac(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51227 {
51228  return ma_decoder_init_vfs_flac(NULL, pFilePath, pConfig, pDecoder);
51229 }
51230 
51231 MA_API ma_result ma_decoder_init_file_mp3(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51232 {
51233  return ma_decoder_init_vfs_mp3(NULL, pFilePath, pConfig, pDecoder);
51234 }
51235 
51236 MA_API ma_result ma_decoder_init_file_vorbis(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51237 {
51238  return ma_decoder_init_vfs_vorbis(NULL, pFilePath, pConfig, pDecoder);
51239 }
51240 
51241 
51242 
51243 MA_API ma_result ma_decoder_init_file_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51244 {
51245  return ma_decoder_init_vfs_w(NULL, pFilePath, pConfig, pDecoder);
51246 }
51247 
51248 MA_API ma_result ma_decoder_init_file_wav_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51249 {
51250  return ma_decoder_init_vfs_wav_w(NULL, pFilePath, pConfig, pDecoder);
51251 }
51252 
51253 MA_API ma_result ma_decoder_init_file_flac_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51254 {
51255  return ma_decoder_init_vfs_flac_w(NULL, pFilePath, pConfig, pDecoder);
51256 }
51257 
51258 MA_API ma_result ma_decoder_init_file_mp3_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51259 {
51260  return ma_decoder_init_vfs_mp3_w(NULL, pFilePath, pConfig, pDecoder);
51261 }
51262 
51263 MA_API ma_result ma_decoder_init_file_vorbis_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder)
51264 {
51265  return ma_decoder_init_vfs_vorbis_w(NULL, pFilePath, pConfig, pDecoder);
51266 }
51267 
51269 {
51270  if (pDecoder == NULL) {
51271  return MA_INVALID_ARGS;
51272  }
51273 
51274  if (pDecoder->pBackend != NULL) {
51275  if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onUninit != NULL) {
51276  pDecoder->pBackendVTable->onUninit(pDecoder->pBackendUserData, pDecoder->pBackend, &pDecoder->allocationCallbacks);
51277  }
51278  }
51279 
51280  /* Legacy. */
51281  if (pDecoder->onRead == ma_decoder__on_read_vfs) {
51282  ma_vfs_or_default_close(pDecoder->data.vfs.pVFS, pDecoder->data.vfs.file);
51283  pDecoder->data.vfs.file = NULL;
51284  }
51285 
51286  ma_data_converter_uninit(&pDecoder->converter);
51287  ma_data_source_uninit(&pDecoder->ds);
51288 
51289  return MA_SUCCESS;
51290 }
51291 
51293 {
51294  if (pCursor == NULL) {
51295  return MA_INVALID_ARGS;
51296  }
51297 
51298  *pCursor = 0;
51299 
51300  if (pDecoder == NULL) {
51301  return MA_INVALID_ARGS;
51302  }
51303 
51304  *pCursor = pDecoder->readPointerInPCMFrames;
51305 
51306  return MA_SUCCESS;
51307 }
51308 
51310 {
51311  if (pDecoder == NULL) {
51312  return 0;
51313  }
51314 
51315  if (pDecoder->pBackend != NULL) {
51316  ma_result result;
51317  ma_uint64 nativeLengthInPCMFrames;
51318  ma_uint32 internalSampleRate;
51319 
51320  ma_data_source_get_length_in_pcm_frames(pDecoder->pBackend, &nativeLengthInPCMFrames);
51321 
51322  result = ma_data_source_get_data_format(pDecoder->pBackend, NULL, NULL, &internalSampleRate);
51323  if (result != MA_SUCCESS) {
51324  return 0; /* Failed to retrieve the internal sample rate. */
51325  }
51326 
51327  if (internalSampleRate == pDecoder->outputSampleRate) {
51328  return nativeLengthInPCMFrames;
51329  } else {
51330  return ma_calculate_frame_count_after_resampling(pDecoder->outputSampleRate, internalSampleRate, nativeLengthInPCMFrames);
51331  }
51332  }
51333 
51334  return 0;
51335 }
51336 
51337 MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount)
51338 {
51339  ma_result result;
51340  ma_uint64 totalFramesReadOut;
51341  ma_uint64 totalFramesReadIn;
51342  void* pRunningFramesOut;
51343 
51344  if (pDecoder == NULL) {
51345  return 0;
51346  }
51347 
51348  if (pDecoder->pBackend == NULL) {
51349  return 0;
51350  }
51351 
51352  /* Fast path. */
51353  if (pDecoder->converter.isPassthrough) {
51354  result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pFramesOut, frameCount, &totalFramesReadOut, MA_FALSE);
51355  } else {
51356  /*
51357  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
51358  need to run through each sample because we need to ensure it's internal cache is updated.
51359  */
51360  if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) {
51361  result = ma_data_source_read_pcm_frames(pDecoder->pBackend, NULL, frameCount, &totalFramesReadOut, MA_FALSE);
51362  } else {
51363  /* Slow path. Need to run everything through the data converter. */
51364  ma_format internalFormat;
51365  ma_uint32 internalChannels;
51366 
51367  totalFramesReadOut = 0;
51368  totalFramesReadIn = 0;
51369  pRunningFramesOut = pFramesOut;
51370 
51371  result = ma_data_source_get_data_format(pDecoder->pBackend, &internalFormat, &internalChannels, NULL);
51372  if (result != MA_SUCCESS) {
51373  return 0; /* Failed to retrieve the internal format and channel count. */
51374  }
51375 
51376  while (totalFramesReadOut < frameCount) {
51377  ma_uint8 pIntermediaryBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* In internal format. */
51378  ma_uint64 intermediaryBufferCap = sizeof(pIntermediaryBuffer) / ma_get_bytes_per_frame(internalFormat, internalChannels);
51379  ma_uint64 framesToReadThisIterationIn;
51380  ma_uint64 framesReadThisIterationIn;
51381  ma_uint64 framesToReadThisIterationOut;
51382  ma_uint64 framesReadThisIterationOut;
51383  ma_uint64 requiredInputFrameCount;
51384 
51385  framesToReadThisIterationOut = (frameCount - totalFramesReadOut);
51386  framesToReadThisIterationIn = framesToReadThisIterationOut;
51387  if (framesToReadThisIterationIn > intermediaryBufferCap) {
51388  framesToReadThisIterationIn = intermediaryBufferCap;
51389  }
51390 
51391  requiredInputFrameCount = ma_data_converter_get_required_input_frame_count(&pDecoder->converter, framesToReadThisIterationOut);
51392  if (framesToReadThisIterationIn > requiredInputFrameCount) {
51393  framesToReadThisIterationIn = requiredInputFrameCount;
51394  }
51395 
51396  if (requiredInputFrameCount > 0) {
51397  result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn, MA_FALSE);
51398  totalFramesReadIn += framesReadThisIterationIn;
51399  } else {
51400  framesReadThisIterationIn = 0;
51401  }
51402 
51403  /*
51404  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
51405  input frames, we still want to try processing frames because there may some output frames generated from cached input data.
51406  */
51407  framesReadThisIterationOut = framesToReadThisIterationOut;
51408  result = ma_data_converter_process_pcm_frames(&pDecoder->converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
51409  if (result != MA_SUCCESS) {
51410  break;
51411  }
51412 
51413  totalFramesReadOut += framesReadThisIterationOut;
51414 
51415  if (pRunningFramesOut != NULL) {
51416  pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels));
51417  }
51418 
51419  if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
51420  break; /* We're done. */
51421  }
51422  }
51423  }
51424  }
51425 
51426  pDecoder->readPointerInPCMFrames += totalFramesReadOut;
51427 
51428  return totalFramesReadOut;
51429 }
51430 
51432 {
51433  if (pDecoder == NULL) {
51434  return MA_INVALID_ARGS;
51435  }
51436 
51437  if (pDecoder->pBackend != NULL) {
51438  ma_result result;
51439  ma_uint64 internalFrameIndex;
51440  ma_uint32 internalSampleRate;
51441 
51442  result = ma_data_source_get_data_format(pDecoder->pBackend, NULL, NULL, &internalSampleRate);
51443  if (result != MA_SUCCESS) {
51444  return result; /* Failed to retrieve the internal sample rate. */
51445  }
51446 
51447  if (internalSampleRate == pDecoder->outputSampleRate) {
51448  internalFrameIndex = frameIndex;
51449  } else {
51450  internalFrameIndex = ma_calculate_frame_count_after_resampling(internalSampleRate, pDecoder->outputSampleRate, frameIndex);
51451  }
51452 
51453  result = ma_data_source_seek_to_pcm_frame(pDecoder->pBackend, internalFrameIndex);
51454  if (result == MA_SUCCESS) {
51455  pDecoder->readPointerInPCMFrames = frameIndex;
51456  }
51457 
51458  return result;
51459  }
51460 
51461  /* Should never get here, but if we do it means onSeekToPCMFrame was not set by the backend. */
51462  return MA_INVALID_ARGS;
51463 }
51464 
51466 {
51467  ma_uint64 totalFrameCount;
51468 
51469  if (pAvailableFrames == NULL) {
51470  return MA_INVALID_ARGS;
51471  }
51472 
51473  *pAvailableFrames = 0;
51474 
51475  if (pDecoder == NULL) {
51476  return MA_INVALID_ARGS;
51477  }
51478 
51479  totalFrameCount = ma_decoder_get_length_in_pcm_frames(pDecoder);
51480  if (totalFrameCount == 0) {
51481  return MA_NOT_IMPLEMENTED;
51482  }
51483 
51484  if (totalFrameCount <= pDecoder->readPointerInPCMFrames) {
51485  *pAvailableFrames = 0;
51486  } else {
51487  *pAvailableFrames = totalFrameCount - pDecoder->readPointerInPCMFrames;
51488  }
51489 
51490  return MA_SUCCESS; /* No frames available. */
51491 }
51492 
51493 
51494 static ma_result ma_decoder__full_decode_and_uninit(ma_decoder* pDecoder, ma_decoder_config* pConfigOut, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
51495 {
51496  ma_uint64 totalFrameCount;
51497  ma_uint64 bpf;
51498  ma_uint64 dataCapInFrames;
51499  void* pPCMFramesOut;
51500 
51501  MA_ASSERT(pDecoder != NULL);
51502 
51503  totalFrameCount = 0;
51504  bpf = ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels);
51505 
51506  /* The frame count is unknown until we try reading. Thus, we just run in a loop. */
51507  dataCapInFrames = 0;
51508  pPCMFramesOut = NULL;
51509  for (;;) {
51510  ma_uint64 frameCountToTryReading;
51511  ma_uint64 framesJustRead;
51512 
51513  /* Make room if there's not enough. */
51514  if (totalFrameCount == dataCapInFrames) {
51515  void* pNewPCMFramesOut;
51516  ma_uint64 oldDataCapInFrames = dataCapInFrames;
51517  ma_uint64 newDataCapInFrames = dataCapInFrames*2;
51518  if (newDataCapInFrames == 0) {
51519  newDataCapInFrames = 4096;
51520  }
51521 
51522  if ((newDataCapInFrames * bpf) > MA_SIZE_MAX) {
51523  ma__free_from_callbacks(pPCMFramesOut, &pDecoder->allocationCallbacks);
51524  return MA_TOO_BIG;
51525  }
51526 
51527 
51528  pNewPCMFramesOut = (void*)ma__realloc_from_callbacks(pPCMFramesOut, (size_t)(newDataCapInFrames * bpf), (size_t)(oldDataCapInFrames * bpf), &pDecoder->allocationCallbacks);
51529  if (pNewPCMFramesOut == NULL) {
51530  ma__free_from_callbacks(pPCMFramesOut, &pDecoder->allocationCallbacks);
51531  return MA_OUT_OF_MEMORY;
51532  }
51533 
51534  dataCapInFrames = newDataCapInFrames;
51535  pPCMFramesOut = pNewPCMFramesOut;
51536  }
51537 
51538  frameCountToTryReading = dataCapInFrames - totalFrameCount;
51539  MA_ASSERT(frameCountToTryReading > 0);
51540 
51541  framesJustRead = ma_decoder_read_pcm_frames(pDecoder, (ma_uint8*)pPCMFramesOut + (totalFrameCount * bpf), frameCountToTryReading);
51542  totalFrameCount += framesJustRead;
51543 
51544  if (framesJustRead < frameCountToTryReading) {
51545  break;
51546  }
51547  }
51548 
51549 
51550  if (pConfigOut != NULL) {
51551  pConfigOut->format = pDecoder->outputFormat;
51552  pConfigOut->channels = pDecoder->outputChannels;
51553  pConfigOut->sampleRate = pDecoder->outputSampleRate;
51554  ma_channel_map_copy(pConfigOut->channelMap, pDecoder->outputChannelMap, pDecoder->outputChannels);
51555  }
51556 
51557  if (ppPCMFramesOut != NULL) {
51558  *ppPCMFramesOut = pPCMFramesOut;
51559  } else {
51560  ma__free_from_callbacks(pPCMFramesOut, &pDecoder->allocationCallbacks);
51561  }
51562 
51563  if (pFrameCountOut != NULL) {
51564  *pFrameCountOut = totalFrameCount;
51565  }
51566 
51567  ma_decoder_uninit(pDecoder);
51568  return MA_SUCCESS;
51569 }
51570 
51571 MA_API ma_result ma_decode_from_vfs(ma_vfs* pVFS, const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
51572 {
51573  ma_result result;
51576 
51577  if (pFrameCountOut != NULL) {
51578  *pFrameCountOut = 0;
51579  }
51580  if (ppPCMFramesOut != NULL) {
51581  *ppPCMFramesOut = NULL;
51582  }
51583 
51585 
51586  result = ma_decoder_init_vfs(pVFS, pFilePath, &config, &decoder);
51587  if (result != MA_SUCCESS) {
51588  return result;
51589  }
51590 
51591  result = ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
51592 
51593  return result;
51594 }
51595 
51596 MA_API ma_result ma_decode_file(const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
51597 {
51598  return ma_decode_from_vfs(NULL, pFilePath, pConfig, pFrameCountOut, ppPCMFramesOut);
51599 }
51600 
51601 MA_API ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut)
51602 {
51605  ma_result result;
51606 
51607  if (pFrameCountOut != NULL) {
51608  *pFrameCountOut = 0;
51609  }
51610  if (ppPCMFramesOut != NULL) {
51611  *ppPCMFramesOut = NULL;
51612  }
51613 
51614  if (pData == NULL || dataSize == 0) {
51615  return MA_INVALID_ARGS;
51616  }
51617 
51619 
51620  result = ma_decoder_init_memory(pData, dataSize, &config, &decoder);
51621  if (result != MA_SUCCESS) {
51622  return result;
51623  }
51624 
51625  return ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
51626 }
51627 #endif /* MA_NO_DECODING */
51628 
51629 
51630 #ifndef MA_NO_ENCODING
51631 
51632 #if defined(MA_HAS_WAV)
51633 static size_t ma_encoder__internal_on_write_wav(void* pUserData, const void* pData, size_t bytesToWrite)
51634 {
51635  ma_encoder* pEncoder = (ma_encoder*)pUserData;
51636  MA_ASSERT(pEncoder != NULL);
51637 
51638  return pEncoder->onWrite(pEncoder, pData, bytesToWrite);
51639 }
51640 
51641 static drwav_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, drwav_seek_origin origin)
51642 {
51643  ma_encoder* pEncoder = (ma_encoder*)pUserData;
51644  MA_ASSERT(pEncoder != NULL);
51645 
51646  return pEncoder->onSeek(pEncoder, offset, (origin == drwav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current);
51647 }
51648 
51650 {
51651  drwav_data_format wavFormat;
51652  drwav_allocation_callbacks allocationCallbacks;
51653  drwav* pWav;
51654 
51655  MA_ASSERT(pEncoder != NULL);
51656 
51657  pWav = (drwav*)ma__malloc_from_callbacks(sizeof(*pWav), &pEncoder->config.allocationCallbacks);
51658  if (pWav == NULL) {
51659  return MA_OUT_OF_MEMORY;
51660  }
51661 
51662  wavFormat.container = drwav_container_riff;
51663  wavFormat.channels = pEncoder->config.channels;
51664  wavFormat.sampleRate = pEncoder->config.sampleRate;
51665  wavFormat.bitsPerSample = ma_get_bytes_per_sample(pEncoder->config.format) * 8;
51666  if (pEncoder->config.format == ma_format_f32) {
51667  wavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT;
51668  } else {
51669  wavFormat.format = DR_WAVE_FORMAT_PCM;
51670  }
51671 
51672  allocationCallbacks.pUserData = pEncoder->config.allocationCallbacks.pUserData;
51673  allocationCallbacks.onMalloc = pEncoder->config.allocationCallbacks.onMalloc;
51674  allocationCallbacks.onRealloc = pEncoder->config.allocationCallbacks.onRealloc;
51675  allocationCallbacks.onFree = pEncoder->config.allocationCallbacks.onFree;
51676 
51677  if (!drwav_init_write(pWav, &wavFormat, ma_encoder__internal_on_write_wav, ma_encoder__internal_on_seek_wav, pEncoder, &allocationCallbacks)) {
51678  return MA_ERROR;
51679  }
51680 
51681  pEncoder->pInternalEncoder = pWav;
51682 
51683  return MA_SUCCESS;
51684 }
51685 
51686 static void ma_encoder__on_uninit_wav(ma_encoder* pEncoder)
51687 {
51688  drwav* pWav;
51689 
51690  MA_ASSERT(pEncoder != NULL);
51691 
51692  pWav = (drwav*)pEncoder->pInternalEncoder;
51693  MA_ASSERT(pWav != NULL);
51694 
51695  drwav_uninit(pWav);
51697 }
51698 
51699 static ma_uint64 ma_encoder__on_write_pcm_frames_wav(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount)
51700 {
51701  drwav* pWav;
51702 
51703  MA_ASSERT(pEncoder != NULL);
51704 
51705  pWav = (drwav*)pEncoder->pInternalEncoder;
51706  MA_ASSERT(pWav != NULL);
51707 
51708  return drwav_write_pcm_frames(pWav, frameCount, pFramesIn);
51709 }
51710 #endif
51711 
51713 {
51715 
51717  config.resourceFormat = resourceFormat;
51718  config.format = format;
51719  config.channels = channels;
51720  config.sampleRate = sampleRate;
51721 
51722  return config;
51723 }
51724 
51726 {
51727  ma_result result;
51728 
51729  if (pEncoder == NULL) {
51730  return MA_INVALID_ARGS;
51731  }
51732 
51733  MA_ZERO_OBJECT(pEncoder);
51734 
51735  if (pConfig == NULL) {
51736  return MA_INVALID_ARGS;
51737  }
51738 
51739  if (pConfig->format == ma_format_unknown || pConfig->channels == 0 || pConfig->sampleRate == 0) {
51740  return MA_INVALID_ARGS;
51741  }
51742 
51743  pEncoder->config = *pConfig;
51744 
51746  if (result != MA_SUCCESS) {
51747  return result;
51748  }
51749 
51750  return MA_SUCCESS;
51751 }
51752 
51754 {
51755  ma_result result = MA_SUCCESS;
51756 
51757  /* This assumes ma_encoder_preinit() has been called prior. */
51758  MA_ASSERT(pEncoder != NULL);
51759 
51760  if (onWrite == NULL || onSeek == NULL) {
51761  return MA_INVALID_ARGS;
51762  }
51763 
51764  pEncoder->onWrite = onWrite;
51765  pEncoder->onSeek = onSeek;
51766  pEncoder->pUserData = pUserData;
51767 
51768  switch (pEncoder->config.resourceFormat)
51769  {
51771  {
51772  #if defined(MA_HAS_WAV)
51773  pEncoder->onInit = ma_encoder__on_init_wav;
51774  pEncoder->onUninit = ma_encoder__on_uninit_wav;
51776  #else
51777  result = MA_NO_BACKEND;
51778  #endif
51779  } break;
51780 
51781  default:
51782  {
51783  result = MA_INVALID_ARGS;
51784  } break;
51785  }
51786 
51787  /* Getting here means we should have our backend callbacks set up. */
51788  if (result == MA_SUCCESS) {
51789  result = pEncoder->onInit(pEncoder);
51790  if (result != MA_SUCCESS) {
51791  return result;
51792  }
51793  }
51794 
51795  return MA_SUCCESS;
51796 }
51797 
51798 MA_API size_t ma_encoder__on_write_stdio(ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite)
51799 {
51800  return fwrite(pBufferIn, 1, bytesToWrite, (FILE*)pEncoder->pFile);
51801 }
51802 
51803 MA_API ma_bool32 ma_encoder__on_seek_stdio(ma_encoder* pEncoder, int byteOffset, ma_seek_origin origin)
51804 {
51805  return fseek((FILE*)pEncoder->pFile, byteOffset, (origin == ma_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
51806 }
51807 
51808 MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
51809 {
51810  ma_result result;
51811  FILE* pFile;
51812 
51813  result = ma_encoder_preinit(pConfig, pEncoder);
51814  if (result != MA_SUCCESS) {
51815  return result;
51816  }
51817 
51818  /* Now open the file. If this fails we don't need to uninitialize the encoder. */
51819  result = ma_fopen(&pFile, pFilePath, "wb");
51820  if (pFile == NULL) {
51821  return result;
51822  }
51823 
51824  pEncoder->pFile = pFile;
51825 
51827 }
51828 
51829 MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
51830 {
51831  ma_result result;
51832  FILE* pFile;
51833 
51834  result = ma_encoder_preinit(pConfig, pEncoder);
51835  if (result != MA_SUCCESS) {
51836  return result;
51837  }
51838 
51839  /* Now open the file. If this fails we don't need to uninitialize the encoder. */
51840  result = ma_wfopen(&pFile, pFilePath, L"wb", &pEncoder->config.allocationCallbacks);
51841  if (pFile == NULL) {
51842  return result;
51843  }
51844 
51845  pEncoder->pFile = pFile;
51846 
51848 }
51849 
51850 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)
51851 {
51852  ma_result result;
51853 
51854  result = ma_encoder_preinit(pConfig, pEncoder);
51855  if (result != MA_SUCCESS) {
51856  return result;
51857  }
51858 
51859  return ma_encoder_init__internal(onWrite, onSeek, pUserData, pEncoder);
51860 }
51861 
51862 
51863 MA_API void ma_encoder_uninit(ma_encoder* pEncoder)
51864 {
51865  if (pEncoder == NULL) {
51866  return;
51867  }
51868 
51869  if (pEncoder->onUninit) {
51870  pEncoder->onUninit(pEncoder);
51871  }
51872 
51873  /* If we have a file handle, close it. */
51874  if (pEncoder->onWrite == ma_encoder__on_write_stdio) {
51875  fclose((FILE*)pEncoder->pFile);
51876  }
51877 }
51878 
51879 
51880 MA_API ma_uint64 ma_encoder_write_pcm_frames(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount)
51881 {
51882  if (pEncoder == NULL || pFramesIn == NULL) {
51883  return 0;
51884  }
51885 
51886  return pEncoder->onWritePCMFrames(pEncoder, pFramesIn, frameCount);
51887 }
51888 #endif /* MA_NO_ENCODING */
51889 
51890 
51891 
51892 /**************************************************************************************************************************************************************
51893 
51894 Generation
51895 
51896 **************************************************************************************************************************************************************/
51897 #ifndef MA_NO_GENERATION
51898 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)
51899 {
51901 
51903  config.format = format;
51904  config.channels = channels;
51905  config.sampleRate = sampleRate;
51906  config.type = type;
51907  config.amplitude = amplitude;
51908  config.frequency = frequency;
51909 
51910  return config;
51911 }
51912 
51913 static ma_result ma_waveform__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
51914 {
51915  ma_uint64 framesRead = ma_waveform_read_pcm_frames((ma_waveform*)pDataSource, pFramesOut, frameCount);
51916 
51917  if (pFramesRead != NULL) {
51918  *pFramesRead = framesRead;
51919  }
51920 
51921  if (framesRead == 0) {
51922  return MA_AT_END;
51923  }
51924 
51925  return MA_SUCCESS;
51926 }
51927 
51928 static ma_result ma_waveform__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
51929 {
51930  return ma_waveform_seek_to_pcm_frame((ma_waveform*)pDataSource, frameIndex);
51931 }
51932 
51933 static ma_result ma_waveform__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
51934 {
51935  ma_waveform* pWaveform = (ma_waveform*)pDataSource;
51936 
51937  *pFormat = pWaveform->config.format;
51938  *pChannels = pWaveform->config.channels;
51939  *pSampleRate = pWaveform->config.sampleRate;
51940 
51941  return MA_SUCCESS;
51942 }
51943 
51945 {
51946  ma_waveform* pWaveform = (ma_waveform*)pDataSource;
51947 
51948  *pCursor = (ma_uint64)(pWaveform->time / pWaveform->advance);
51949 
51950  return MA_SUCCESS;
51951 }
51952 
51953 static double ma_waveform__calculate_advance(ma_uint32 sampleRate, double frequency)
51954 {
51955  return (1.0 / (sampleRate / frequency));
51956 }
51957 
51958 static void ma_waveform__update_advance(ma_waveform* pWaveform)
51959 {
51960  pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
51961 }
51962 
51964 {
51967  NULL, /* onMap */
51968  NULL, /* onUnmap */
51971  NULL /* onGetLength. There's no notion of a length in waveforms. */
51972 };
51973 
51975 {
51976  ma_result result;
51977  ma_data_source_config dataSourceConfig;
51978 
51979  if (pWaveform == NULL) {
51980  return MA_INVALID_ARGS;
51981  }
51982 
51983  MA_ZERO_OBJECT(pWaveform);
51984 
51985  dataSourceConfig = ma_data_source_config_init();
51986  dataSourceConfig.vtable = &g_ma_waveform_data_source_vtable;
51987 
51988  result = ma_data_source_init(&dataSourceConfig, &pWaveform->ds);
51989  if (result != MA_SUCCESS) {
51990  return result;
51991  }
51992 
51993  pWaveform->config = *pConfig;
51994  pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
51995  pWaveform->time = 0;
51996 
51997  return MA_SUCCESS;
51998 }
51999 
52000 MA_API void ma_waveform_uninit(ma_waveform* pWaveform)
52001 {
52002  if (pWaveform == NULL) {
52003  return;
52004  }
52005 
52006  ma_data_source_uninit(&pWaveform->ds);
52007 }
52008 
52009 MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude)
52010 {
52011  if (pWaveform == NULL) {
52012  return MA_INVALID_ARGS;
52013  }
52014 
52015  pWaveform->config.amplitude = amplitude;
52016  return MA_SUCCESS;
52017 }
52018 
52019 MA_API ma_result ma_waveform_set_frequency(ma_waveform* pWaveform, double frequency)
52020 {
52021  if (pWaveform == NULL) {
52022  return MA_INVALID_ARGS;
52023  }
52024 
52025  pWaveform->config.frequency = frequency;
52026  ma_waveform__update_advance(pWaveform);
52027 
52028  return MA_SUCCESS;
52029 }
52030 
52032 {
52033  if (pWaveform == NULL) {
52034  return MA_INVALID_ARGS;
52035  }
52036 
52037  pWaveform->config.type = type;
52038  return MA_SUCCESS;
52039 }
52040 
52042 {
52043  if (pWaveform == NULL) {
52044  return MA_INVALID_ARGS;
52045  }
52046 
52047  pWaveform->config.sampleRate = sampleRate;
52048  ma_waveform__update_advance(pWaveform);
52049 
52050  return MA_SUCCESS;
52051 }
52052 
52053 static float ma_waveform_sine_f32(double time, double amplitude)
52054 {
52055  return (float)(ma_sind(MA_TAU_D * time) * amplitude);
52056 }
52057 
52058 static ma_int16 ma_waveform_sine_s16(double time, double amplitude)
52059 {
52060  return ma_pcm_sample_f32_to_s16(ma_waveform_sine_f32(time, amplitude));
52061 }
52062 
52063 static float ma_waveform_square_f32(double time, double amplitude)
52064 {
52065  double f = time - (ma_int64)time;
52066  double r;
52067 
52068  if (f < 0.5) {
52069  r = amplitude;
52070  } else {
52071  r = -amplitude;
52072  }
52073 
52074  return (float)r;
52075 }
52076 
52077 static ma_int16 ma_waveform_square_s16(double time, double amplitude)
52078 {
52079  return ma_pcm_sample_f32_to_s16(ma_waveform_square_f32(time, amplitude));
52080 }
52081 
52082 static float ma_waveform_triangle_f32(double time, double amplitude)
52083 {
52084  double f = time - (ma_int64)time;
52085  double r;
52086 
52087  r = 2 * ma_abs(2 * (f - 0.5)) - 1;
52088 
52089  return (float)(r * amplitude);
52090 }
52091 
52092 static ma_int16 ma_waveform_triangle_s16(double time, double amplitude)
52093 {
52094  return ma_pcm_sample_f32_to_s16(ma_waveform_triangle_f32(time, amplitude));
52095 }
52096 
52097 static float ma_waveform_sawtooth_f32(double time, double amplitude)
52098 {
52099  double f = time - (ma_int64)time;
52100  double r;
52101 
52102  r = 2 * (f - 0.5);
52103 
52104  return (float)(r * amplitude);
52105 }
52106 
52107 static ma_int16 ma_waveform_sawtooth_s16(double time, double amplitude)
52108 {
52109  return ma_pcm_sample_f32_to_s16(ma_waveform_sawtooth_f32(time, amplitude));
52110 }
52111 
52112 static void ma_waveform_read_pcm_frames__sine(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
52113 {
52114  ma_uint64 iFrame;
52115  ma_uint64 iChannel;
52116  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
52117  ma_uint32 bpf = bps * pWaveform->config.channels;
52118 
52119  MA_ASSERT(pWaveform != NULL);
52120  MA_ASSERT(pFramesOut != NULL);
52121 
52122  if (pWaveform->config.format == ma_format_f32) {
52123  float* pFramesOutF32 = (float*)pFramesOut;
52124  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52125  float s = ma_waveform_sine_f32(pWaveform->time, pWaveform->config.amplitude);
52126  pWaveform->time += pWaveform->advance;
52127 
52128  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52129  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
52130  }
52131  }
52132  } else if (pWaveform->config.format == ma_format_s16) {
52133  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52134  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52135  ma_int16 s = ma_waveform_sine_s16(pWaveform->time, pWaveform->config.amplitude);
52136  pWaveform->time += pWaveform->advance;
52137 
52138  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52139  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
52140  }
52141  }
52142  } else {
52143  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52144  float s = ma_waveform_sine_f32(pWaveform->time, pWaveform->config.amplitude);
52145  pWaveform->time += pWaveform->advance;
52146 
52147  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52148  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52149  }
52150  }
52151  }
52152 }
52153 
52154 static void ma_waveform_read_pcm_frames__square(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
52155 {
52156  ma_uint64 iFrame;
52157  ma_uint64 iChannel;
52158  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
52159  ma_uint32 bpf = bps * pWaveform->config.channels;
52160 
52161  MA_ASSERT(pWaveform != NULL);
52162  MA_ASSERT(pFramesOut != NULL);
52163 
52164  if (pWaveform->config.format == ma_format_f32) {
52165  float* pFramesOutF32 = (float*)pFramesOut;
52166  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52167  float s = ma_waveform_square_f32(pWaveform->time, pWaveform->config.amplitude);
52168  pWaveform->time += pWaveform->advance;
52169 
52170  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52171  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
52172  }
52173  }
52174  } else if (pWaveform->config.format == ma_format_s16) {
52175  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52176  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52177  ma_int16 s = ma_waveform_square_s16(pWaveform->time, pWaveform->config.amplitude);
52178  pWaveform->time += pWaveform->advance;
52179 
52180  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52181  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
52182  }
52183  }
52184  } else {
52185  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52186  float s = ma_waveform_square_f32(pWaveform->time, pWaveform->config.amplitude);
52187  pWaveform->time += pWaveform->advance;
52188 
52189  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52190  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52191  }
52192  }
52193  }
52194 }
52195 
52196 static void ma_waveform_read_pcm_frames__triangle(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
52197 {
52198  ma_uint64 iFrame;
52199  ma_uint64 iChannel;
52200  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
52201  ma_uint32 bpf = bps * pWaveform->config.channels;
52202 
52203  MA_ASSERT(pWaveform != NULL);
52204  MA_ASSERT(pFramesOut != NULL);
52205 
52206  if (pWaveform->config.format == ma_format_f32) {
52207  float* pFramesOutF32 = (float*)pFramesOut;
52208  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52209  float s = ma_waveform_triangle_f32(pWaveform->time, pWaveform->config.amplitude);
52210  pWaveform->time += pWaveform->advance;
52211 
52212  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52213  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
52214  }
52215  }
52216  } else if (pWaveform->config.format == ma_format_s16) {
52217  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52218  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52219  ma_int16 s = ma_waveform_triangle_s16(pWaveform->time, pWaveform->config.amplitude);
52220  pWaveform->time += pWaveform->advance;
52221 
52222  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52223  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
52224  }
52225  }
52226  } else {
52227  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52228  float s = ma_waveform_triangle_f32(pWaveform->time, pWaveform->config.amplitude);
52229  pWaveform->time += pWaveform->advance;
52230 
52231  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52232  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52233  }
52234  }
52235  }
52236 }
52237 
52238 static void ma_waveform_read_pcm_frames__sawtooth(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
52239 {
52240  ma_uint64 iFrame;
52241  ma_uint64 iChannel;
52242  ma_uint32 bps = ma_get_bytes_per_sample(pWaveform->config.format);
52243  ma_uint32 bpf = bps * pWaveform->config.channels;
52244 
52245  MA_ASSERT(pWaveform != NULL);
52246  MA_ASSERT(pFramesOut != NULL);
52247 
52248  if (pWaveform->config.format == ma_format_f32) {
52249  float* pFramesOutF32 = (float*)pFramesOut;
52250  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52251  float s = ma_waveform_sawtooth_f32(pWaveform->time, pWaveform->config.amplitude);
52252  pWaveform->time += pWaveform->advance;
52253 
52254  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52255  pFramesOutF32[iFrame*pWaveform->config.channels + iChannel] = s;
52256  }
52257  }
52258  } else if (pWaveform->config.format == ma_format_s16) {
52259  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52260  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52261  ma_int16 s = ma_waveform_sawtooth_s16(pWaveform->time, pWaveform->config.amplitude);
52262  pWaveform->time += pWaveform->advance;
52263 
52264  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52265  pFramesOutS16[iFrame*pWaveform->config.channels + iChannel] = s;
52266  }
52267  }
52268  } else {
52269  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52270  float s = ma_waveform_sawtooth_f32(pWaveform->time, pWaveform->config.amplitude);
52271  pWaveform->time += pWaveform->advance;
52272 
52273  for (iChannel = 0; iChannel < pWaveform->config.channels; iChannel += 1) {
52274  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pWaveform->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52275  }
52276  }
52277  }
52278 }
52279 
52280 MA_API ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount)
52281 {
52282  if (pWaveform == NULL) {
52283  return 0;
52284  }
52285 
52286  if (pFramesOut != NULL) {
52287  switch (pWaveform->config.type)
52288  {
52289  case ma_waveform_type_sine:
52290  {
52291  ma_waveform_read_pcm_frames__sine(pWaveform, pFramesOut, frameCount);
52292  } break;
52293 
52295  {
52296  ma_waveform_read_pcm_frames__square(pWaveform, pFramesOut, frameCount);
52297  } break;
52298 
52300  {
52301  ma_waveform_read_pcm_frames__triangle(pWaveform, pFramesOut, frameCount);
52302  } break;
52303 
52305  {
52306  ma_waveform_read_pcm_frames__sawtooth(pWaveform, pFramesOut, frameCount);
52307  } break;
52308 
52309  default: return 0;
52310  }
52311  } else {
52312  pWaveform->time += pWaveform->advance * (ma_int64)frameCount; /* Cast to int64 required for VC6. Won't affect anything in practice. */
52313  }
52314 
52315  return frameCount;
52316 }
52317 
52319 {
52320  if (pWaveform == NULL) {
52321  return MA_INVALID_ARGS;
52322  }
52323 
52324  pWaveform->time = pWaveform->advance * (ma_int64)frameIndex; /* Casting for VC6. Won't be an issue in practice. */
52325 
52326  return MA_SUCCESS;
52327 }
52328 
52329 
52330 MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels, ma_noise_type type, ma_int32 seed, double amplitude)
52331 {
52334 
52335  config.format = format;
52336  config.channels = channels;
52337  config.type = type;
52338  config.seed = seed;
52339  config.amplitude = amplitude;
52340 
52341  if (config.seed == 0) {
52342  config.seed = MA_DEFAULT_LCG_SEED;
52343  }
52344 
52345  return config;
52346 }
52347 
52348 
52349 static ma_result ma_noise__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
52350 {
52351  ma_uint64 framesRead = ma_noise_read_pcm_frames((ma_noise*)pDataSource, pFramesOut, frameCount);
52352 
52353  if (pFramesRead != NULL) {
52354  *pFramesRead = framesRead;
52355  }
52356 
52357  if (framesRead == 0) {
52358  return MA_AT_END;
52359  }
52360 
52361  return MA_SUCCESS;
52362 }
52363 
52364 static ma_result ma_noise__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
52365 {
52366  /* No-op. Just pretend to be successful. */
52367  (void)pDataSource;
52368  (void)frameIndex;
52369  return MA_SUCCESS;
52370 }
52371 
52372 static ma_result ma_noise__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
52373 {
52374  ma_noise* pNoise = (ma_noise*)pDataSource;
52375 
52376  *pFormat = pNoise->config.format;
52377  *pChannels = pNoise->config.channels;
52378  *pSampleRate = 0; /* There is no notion of sample rate with noise generation. */
52379 
52380  return MA_SUCCESS;
52381 }
52382 
52384 {
52386  ma_noise__data_source_on_seek, /* No-op for noise. */
52387  NULL, /* onMap */
52388  NULL, /* onUnmap */
52390  NULL, /* onGetCursor. No notion of a cursor for noise. */
52391  NULL /* onGetLength. No notion of a length for noise. */
52392 };
52393 
52394 MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise)
52395 {
52396  ma_result result;
52397  ma_data_source_config dataSourceConfig;
52398 
52399  if (pNoise == NULL) {
52400  return MA_INVALID_ARGS;
52401  }
52402 
52403  MA_ZERO_OBJECT(pNoise);
52404 
52405  if (pConfig == NULL) {
52406  return MA_INVALID_ARGS;
52407  }
52408 
52409  if (pConfig->channels < MA_MIN_CHANNELS || pConfig->channels > MA_MAX_CHANNELS) {
52410  return MA_INVALID_ARGS;
52411  }
52412 
52413  dataSourceConfig = ma_data_source_config_init();
52414  dataSourceConfig.vtable = &g_ma_noise_data_source_vtable;
52415 
52416  result = ma_data_source_init(&dataSourceConfig, &pNoise->ds);
52417  if (result != MA_SUCCESS) {
52418  return result;
52419  }
52420 
52421  pNoise->config = *pConfig;
52422  ma_lcg_seed(&pNoise->lcg, pConfig->seed);
52423 
52424  if (pNoise->config.type == ma_noise_type_pink) {
52425  ma_uint32 iChannel;
52426  for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
52427  pNoise->state.pink.accumulation[iChannel] = 0;
52428  pNoise->state.pink.counter[iChannel] = 1;
52429  }
52430  }
52431 
52432  if (pNoise->config.type == ma_noise_type_brownian) {
52433  ma_uint32 iChannel;
52434  for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
52435  pNoise->state.brownian.accumulation[iChannel] = 0;
52436  }
52437  }
52438 
52439  return MA_SUCCESS;
52440 }
52441 
52442 MA_API void ma_noise_uninit(ma_noise* pNoise)
52443 {
52444  if (pNoise == NULL) {
52445  return;
52446  }
52447 
52448  ma_data_source_uninit(&pNoise->ds);
52449 }
52450 
52451 MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude)
52452 {
52453  if (pNoise == NULL) {
52454  return MA_INVALID_ARGS;
52455  }
52456 
52457  pNoise->config.amplitude = amplitude;
52458  return MA_SUCCESS;
52459 }
52460 
52462 {
52463  if (pNoise == NULL) {
52464  return MA_INVALID_ARGS;
52465  }
52466 
52467  pNoise->lcg.state = seed;
52468  return MA_SUCCESS;
52469 }
52470 
52471 
52473 {
52474  if (pNoise == NULL) {
52475  return MA_INVALID_ARGS;
52476  }
52477 
52478  pNoise->config.type = type;
52479  return MA_SUCCESS;
52480 }
52481 
52482 static MA_INLINE float ma_noise_f32_white(ma_noise* pNoise)
52483 {
52484  return (float)(ma_lcg_rand_f64(&pNoise->lcg) * pNoise->config.amplitude);
52485 }
52486 
52488 {
52490 }
52491 
52492 static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__white(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
52493 {
52494  ma_uint64 iFrame;
52495  ma_uint32 iChannel;
52496  const ma_uint32 channels = pNoise->config.channels;
52497  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
52498 
52499  if (pNoise->config.format == ma_format_f32) {
52500  float* pFramesOutF32 = (float*)pFramesOut;
52501  if (pNoise->config.duplicateChannels) {
52502  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52503  float s = ma_noise_f32_white(pNoise);
52504  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52505  pFramesOutF32[iFrame*channels + iChannel] = s;
52506  }
52507  }
52508  } else {
52509  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52510  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52511  pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_white(pNoise);
52512  }
52513  }
52514  }
52515  } else if (pNoise->config.format == ma_format_s16) {
52516  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52517  if (pNoise->config.duplicateChannels) {
52518  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52519  ma_int16 s = ma_noise_s16_white(pNoise);
52520  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52521  pFramesOutS16[iFrame*channels + iChannel] = s;
52522  }
52523  }
52524  } else {
52525  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52526  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52527  pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_white(pNoise);
52528  }
52529  }
52530  }
52531  } else {
52532  const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
52533  const ma_uint32 bpf = bps * channels;
52534 
52535  if (pNoise->config.duplicateChannels) {
52536  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52537  float s = ma_noise_f32_white(pNoise);
52538  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52539  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52540  }
52541  }
52542  } else {
52543  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52544  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52545  float s = ma_noise_f32_white(pNoise);
52546  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52547  }
52548  }
52549  }
52550  }
52551 
52552  return frameCount;
52553 }
52554 
52555 
52556 static MA_INLINE unsigned int ma_tzcnt32(unsigned int x)
52557 {
52558  unsigned int n;
52559 
52560  /* Special case for odd numbers since they should happen about half the time. */
52561  if (x & 0x1) {
52562  return 0;
52563  }
52564 
52565  if (x == 0) {
52566  return sizeof(x) << 3;
52567  }
52568 
52569  n = 1;
52570  if ((x & 0x0000FFFF) == 0) { x >>= 16; n += 16; }
52571  if ((x & 0x000000FF) == 0) { x >>= 8; n += 8; }
52572  if ((x & 0x0000000F) == 0) { x >>= 4; n += 4; }
52573  if ((x & 0x00000003) == 0) { x >>= 2; n += 2; }
52574  n -= x & 0x00000001;
52575 
52576  return n;
52577 }
52578 
52579 /*
52580 Pink noise generation based on Tonic (public domain) with modifications. https://github.com/TonicAudio/Tonic/blob/master/src/Tonic/Noise.h
52581 
52582 This is basically _the_ reference for pink noise from what I've found: http://www.firstpr.com.au/dsp/pink-noise/
52583 */
52584 static MA_INLINE float ma_noise_f32_pink(ma_noise* pNoise, ma_uint32 iChannel)
52585 {
52586  double result;
52587  double binPrev;
52588  double binNext;
52589  unsigned int ibin;
52590 
52591  ibin = ma_tzcnt32(pNoise->state.pink.counter[iChannel]) & (ma_countof(pNoise->state.pink.bin[0]) - 1);
52592 
52593  binPrev = pNoise->state.pink.bin[iChannel][ibin];
52594  binNext = ma_lcg_rand_f64(&pNoise->lcg);
52595  pNoise->state.pink.bin[iChannel][ibin] = binNext;
52596 
52597  pNoise->state.pink.accumulation[iChannel] += (binNext - binPrev);
52598  pNoise->state.pink.counter[iChannel] += 1;
52599 
52600  result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.pink.accumulation[iChannel]);
52601  result /= 10;
52602 
52603  return (float)(result * pNoise->config.amplitude);
52604 }
52605 
52606 static MA_INLINE ma_int16 ma_noise_s16_pink(ma_noise* pNoise, ma_uint32 iChannel)
52607 {
52608  return ma_pcm_sample_f32_to_s16(ma_noise_f32_pink(pNoise, iChannel));
52609 }
52610 
52611 static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__pink(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
52612 {
52613  ma_uint64 iFrame;
52614  ma_uint32 iChannel;
52615  const ma_uint32 channels = pNoise->config.channels;
52616  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
52617 
52618  if (pNoise->config.format == ma_format_f32) {
52619  float* pFramesOutF32 = (float*)pFramesOut;
52620  if (pNoise->config.duplicateChannels) {
52621  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52622  float s = ma_noise_f32_pink(pNoise, 0);
52623  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52624  pFramesOutF32[iFrame*channels + iChannel] = s;
52625  }
52626  }
52627  } else {
52628  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52629  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52630  pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_pink(pNoise, iChannel);
52631  }
52632  }
52633  }
52634  } else if (pNoise->config.format == ma_format_s16) {
52635  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52636  if (pNoise->config.duplicateChannels) {
52637  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52638  ma_int16 s = ma_noise_s16_pink(pNoise, 0);
52639  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52640  pFramesOutS16[iFrame*channels + iChannel] = s;
52641  }
52642  }
52643  } else {
52644  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52645  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52646  pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_pink(pNoise, iChannel);
52647  }
52648  }
52649  }
52650  } else {
52651  const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
52652  const ma_uint32 bpf = bps * channels;
52653 
52654  if (pNoise->config.duplicateChannels) {
52655  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52656  float s = ma_noise_f32_pink(pNoise, 0);
52657  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52658  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52659  }
52660  }
52661  } else {
52662  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52663  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52664  float s = ma_noise_f32_pink(pNoise, iChannel);
52665  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52666  }
52667  }
52668  }
52669  }
52670 
52671  return frameCount;
52672 }
52673 
52674 
52675 static MA_INLINE float ma_noise_f32_brownian(ma_noise* pNoise, ma_uint32 iChannel)
52676 {
52677  double result;
52678 
52679  result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.brownian.accumulation[iChannel]);
52680  result /= 1.005; /* Don't escape the -1..1 range on average. */
52681 
52682  pNoise->state.brownian.accumulation[iChannel] = result;
52683  result /= 20;
52684 
52685  return (float)(result * pNoise->config.amplitude);
52686 }
52687 
52688 static MA_INLINE ma_int16 ma_noise_s16_brownian(ma_noise* pNoise, ma_uint32 iChannel)
52689 {
52690  return ma_pcm_sample_f32_to_s16(ma_noise_f32_brownian(pNoise, iChannel));
52691 }
52692 
52693 static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__brownian(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
52694 {
52695  ma_uint64 iFrame;
52696  ma_uint32 iChannel;
52697  const ma_uint32 channels = pNoise->config.channels;
52698  MA_ASSUME(channels >= MA_MIN_CHANNELS && channels <= MA_MAX_CHANNELS);
52699 
52700  if (pNoise->config.format == ma_format_f32) {
52701  float* pFramesOutF32 = (float*)pFramesOut;
52702  if (pNoise->config.duplicateChannels) {
52703  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52704  float s = ma_noise_f32_brownian(pNoise, 0);
52705  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52706  pFramesOutF32[iFrame*channels + iChannel] = s;
52707  }
52708  }
52709  } else {
52710  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52711  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52712  pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_brownian(pNoise, iChannel);
52713  }
52714  }
52715  }
52716  } else if (pNoise->config.format == ma_format_s16) {
52717  ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
52718  if (pNoise->config.duplicateChannels) {
52719  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52720  ma_int16 s = ma_noise_s16_brownian(pNoise, 0);
52721  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52722  pFramesOutS16[iFrame*channels + iChannel] = s;
52723  }
52724  }
52725  } else {
52726  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52727  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52728  pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_brownian(pNoise, iChannel);
52729  }
52730  }
52731  }
52732  } else {
52733  const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
52734  const ma_uint32 bpf = bps * channels;
52735 
52736  if (pNoise->config.duplicateChannels) {
52737  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52738  float s = ma_noise_f32_brownian(pNoise, 0);
52739  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52740  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52741  }
52742  }
52743  } else {
52744  for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
52745  for (iChannel = 0; iChannel < channels; iChannel += 1) {
52746  float s = ma_noise_f32_brownian(pNoise, iChannel);
52747  ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
52748  }
52749  }
52750  }
52751  }
52752 
52753  return frameCount;
52754 }
52755 
52756 MA_API ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
52757 {
52758  if (pNoise == NULL) {
52759  return 0;
52760  }
52761 
52762  /* 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. */
52763  if (pFramesOut == NULL) {
52764  return frameCount;
52765  }
52766 
52767  if (pNoise->config.type == ma_noise_type_white) {
52768  return ma_noise_read_pcm_frames__white(pNoise, pFramesOut, frameCount);
52769  }
52770 
52771  if (pNoise->config.type == ma_noise_type_pink) {
52772  return ma_noise_read_pcm_frames__pink(pNoise, pFramesOut, frameCount);
52773  }
52774 
52775  if (pNoise->config.type == ma_noise_type_brownian) {
52776  return ma_noise_read_pcm_frames__brownian(pNoise, pFramesOut, frameCount);
52777  }
52778 
52779  /* Should never get here. */
52781  return 0;
52782 }
52783 #endif /* MA_NO_GENERATION */
52784 
52785 
52786 
52787 /**************************************************************************************************************************************************************
52788 ***************************************************************************************************************************************************************
52789 
52790 Auto Generated
52791 ==============
52792 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
52793 code below please report the bug to the respective repository for the relevant project (probably dr_libs).
52794 
52795 ***************************************************************************************************************************************************************
52796 **************************************************************************************************************************************************************/
52797 #if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING))
52798 #if !defined(DR_WAV_IMPLEMENTATION) && !defined(DRWAV_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
52799 /* dr_wav_c begin */
52800 #ifndef dr_wav_c
52801 #define dr_wav_c
52802 #include <stdlib.h>
52803 #include <string.h>
52804 #include <limits.h>
52805 #ifndef DR_WAV_NO_STDIO
52806 #include <stdio.h>
52807 #include <wchar.h>
52808 #endif
52809 #ifndef DRWAV_ASSERT
52810 #include <assert.h>
52811 #define DRWAV_ASSERT(expression) assert(expression)
52812 #endif
52813 #ifndef DRWAV_MALLOC
52814 #define DRWAV_MALLOC(sz) malloc((sz))
52815 #endif
52816 #ifndef DRWAV_REALLOC
52817 #define DRWAV_REALLOC(p, sz) realloc((p), (sz))
52818 #endif
52819 #ifndef DRWAV_FREE
52820 #define DRWAV_FREE(p) free((p))
52821 #endif
52822 #ifndef DRWAV_COPY_MEMORY
52823 #define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
52824 #endif
52825 #ifndef DRWAV_ZERO_MEMORY
52826 #define DRWAV_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
52827 #endif
52828 #ifndef DRWAV_ZERO_OBJECT
52829 #define DRWAV_ZERO_OBJECT(p) DRWAV_ZERO_MEMORY((p), sizeof(*p))
52830 #endif
52831 #define drwav_countof(x) (sizeof(x) / sizeof(x[0]))
52832 #define drwav_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
52833 #define drwav_min(a, b) (((a) < (b)) ? (a) : (b))
52834 #define drwav_max(a, b) (((a) > (b)) ? (a) : (b))
52835 #define drwav_clamp(x, lo, hi) (drwav_max((lo), drwav_min((hi), (x))))
52836 #define DRWAV_MAX_SIMD_VECTOR_SIZE 64
52837 #if defined(__x86_64__) || defined(_M_X64)
52838  #define DRWAV_X64
52839 #elif defined(__i386) || defined(_M_IX86)
52840  #define DRWAV_X86
52841 #elif defined(__arm__) || defined(_M_ARM)
52842  #define DRWAV_ARM
52843 #endif
52844 #ifdef _MSC_VER
52845  #define DRWAV_INLINE __forceinline
52846 #elif defined(__GNUC__)
52847  #if defined(__STRICT_ANSI__)
52848  #define DRWAV_INLINE __inline__ __attribute__((always_inline))
52849  #else
52850  #define DRWAV_INLINE inline __attribute__((always_inline))
52851  #endif
52852 #elif defined(__WATCOMC__)
52853  #define DRWAV_INLINE __inline
52854 #else
52855  #define DRWAV_INLINE
52856 #endif
52857 #if defined(SIZE_MAX)
52858  #define DRWAV_SIZE_MAX SIZE_MAX
52859 #else
52860  #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
52861  #define DRWAV_SIZE_MAX ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
52862  #else
52863  #define DRWAV_SIZE_MAX 0xFFFFFFFF
52864  #endif
52865 #endif
52866 #if defined(_MSC_VER) && _MSC_VER >= 1400
52867  #define DRWAV_HAS_BYTESWAP16_INTRINSIC
52868  #define DRWAV_HAS_BYTESWAP32_INTRINSIC
52869  #define DRWAV_HAS_BYTESWAP64_INTRINSIC
52870 #elif defined(__clang__)
52871  #if defined(__has_builtin)
52872  #if __has_builtin(__builtin_bswap16)
52873  #define DRWAV_HAS_BYTESWAP16_INTRINSIC
52874  #endif
52875  #if __has_builtin(__builtin_bswap32)
52876  #define DRWAV_HAS_BYTESWAP32_INTRINSIC
52877  #endif
52878  #if __has_builtin(__builtin_bswap64)
52879  #define DRWAV_HAS_BYTESWAP64_INTRINSIC
52880  #endif
52881  #endif
52882 #elif defined(__GNUC__)
52883  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
52884  #define DRWAV_HAS_BYTESWAP32_INTRINSIC
52885  #define DRWAV_HAS_BYTESWAP64_INTRINSIC
52886  #endif
52887  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
52888  #define DRWAV_HAS_BYTESWAP16_INTRINSIC
52889  #endif
52890 #endif
52891 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision)
52892 {
52893  if (pMajor) {
52894  *pMajor = DRWAV_VERSION_MAJOR;
52895  }
52896  if (pMinor) {
52897  *pMinor = DRWAV_VERSION_MINOR;
52898  }
52899  if (pRevision) {
52900  *pRevision = DRWAV_VERSION_REVISION;
52901  }
52902 }
52903 DRWAV_API const char* drwav_version_string(void)
52904 {
52905  return DRWAV_VERSION_STRING;
52906 }
52907 #ifndef DRWAV_MAX_SAMPLE_RATE
52908 #define DRWAV_MAX_SAMPLE_RATE 384000
52909 #endif
52910 #ifndef DRWAV_MAX_CHANNELS
52911 #define DRWAV_MAX_CHANNELS 256
52912 #endif
52913 #ifndef DRWAV_MAX_BITS_PER_SAMPLE
52914 #define DRWAV_MAX_BITS_PER_SAMPLE 64
52915 #endif
52916 static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00};
52917 static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
52918 static const drwav_uint8 drwavGUID_W64_FMT [16] = {0x66,0x6D,0x74,0x20, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
52919 static const drwav_uint8 drwavGUID_W64_FACT[16] = {0x66,0x61,0x63,0x74, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
52920 static const drwav_uint8 drwavGUID_W64_DATA[16] = {0x64,0x61,0x74,0x61, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
52921 static DRWAV_INLINE int drwav__is_little_endian(void)
52922 {
52923 #if defined(DRWAV_X86) || defined(DRWAV_X64)
52924  return DRWAV_TRUE;
52925 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
52926  return DRWAV_TRUE;
52927 #else
52928  int n = 1;
52929  return (*(char*)&n) == 1;
52930 #endif
52931 }
52932 static DRWAV_INLINE void drwav_bytes_to_guid(const drwav_uint8* data, drwav_uint8* guid)
52933 {
52934  int i;
52935  for (i = 0; i < 16; ++i) {
52936  guid[i] = data[i];
52937  }
52938 }
52940 {
52941 #ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
52942  #if defined(_MSC_VER)
52943  return _byteswap_ushort(n);
52944  #elif defined(__GNUC__) || defined(__clang__)
52945  return __builtin_bswap16(n);
52946  #else
52947  #error "This compiler does not support the byte swap intrinsic."
52948  #endif
52949 #else
52950  return ((n & 0xFF00) >> 8) |
52951  ((n & 0x00FF) << 8);
52952 #endif
52953 }
52955 {
52956 #ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
52957  #if defined(_MSC_VER)
52958  return _byteswap_ulong(n);
52959  #elif defined(__GNUC__) || defined(__clang__)
52960  #if defined(DRWAV_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRWAV_64BIT)
52961  drwav_uint32 r;
52962  __asm__ __volatile__ (
52963  #if defined(DRWAV_64BIT)
52964  "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n)
52965  #else
52966  "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
52967  #endif
52968  );
52969  return r;
52970  #else
52971  return __builtin_bswap32(n);
52972  #endif
52973  #else
52974  #error "This compiler does not support the byte swap intrinsic."
52975  #endif
52976 #else
52977  return ((n & 0xFF000000) >> 24) |
52978  ((n & 0x00FF0000) >> 8) |
52979  ((n & 0x0000FF00) << 8) |
52980  ((n & 0x000000FF) << 24);
52981 #endif
52982 }
52984 {
52985 #ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
52986  #if defined(_MSC_VER)
52987  return _byteswap_uint64(n);
52988  #elif defined(__GNUC__) || defined(__clang__)
52989  return __builtin_bswap64(n);
52990  #else
52991  #error "This compiler does not support the byte swap intrinsic."
52992  #endif
52993 #else
52994  return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
52995  ((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
52996  ((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
52997  ((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
52998  ((n & ((drwav_uint64)0xFF000000 )) << 8) |
52999  ((n & ((drwav_uint64)0x00FF0000 )) << 24) |
53000  ((n & ((drwav_uint64)0x0000FF00 )) << 40) |
53001  ((n & ((drwav_uint64)0x000000FF )) << 56);
53002 #endif
53003 }
53005 {
53007 }
53008 static DRWAV_INLINE void drwav__bswap_samples_s16(drwav_int16* pSamples, drwav_uint64 sampleCount)
53009 {
53010  drwav_uint64 iSample;
53011  for (iSample = 0; iSample < sampleCount; iSample += 1) {
53012  pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
53013  }
53014 }
53016 {
53017  drwav_uint8 t;
53018  t = p[0];
53019  p[0] = p[2];
53020  p[2] = t;
53021 }
53022 static DRWAV_INLINE void drwav__bswap_samples_s24(drwav_uint8* pSamples, drwav_uint64 sampleCount)
53023 {
53024  drwav_uint64 iSample;
53025  for (iSample = 0; iSample < sampleCount; iSample += 1) {
53026  drwav_uint8* pSample = pSamples + (iSample*3);
53027  drwav__bswap_s24(pSample);
53028  }
53029 }
53031 {
53033 }
53034 static DRWAV_INLINE void drwav__bswap_samples_s32(drwav_int32* pSamples, drwav_uint64 sampleCount)
53035 {
53036  drwav_uint64 iSample;
53037  for (iSample = 0; iSample < sampleCount; iSample += 1) {
53038  pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
53039  }
53040 }
53041 static DRWAV_INLINE float drwav__bswap_f32(float n)
53042 {
53043  union {
53044  drwav_uint32 i;
53045  float f;
53046  } x;
53047  x.f = n;
53048  x.i = drwav__bswap32(x.i);
53049  return x.f;
53050 }
53051 static DRWAV_INLINE void drwav__bswap_samples_f32(float* pSamples, drwav_uint64 sampleCount)
53052 {
53053  drwav_uint64 iSample;
53054  for (iSample = 0; iSample < sampleCount; iSample += 1) {
53055  pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
53056  }
53057 }
53058 static DRWAV_INLINE double drwav__bswap_f64(double n)
53059 {
53060  union {
53061  drwav_uint64 i;
53062  double f;
53063  } x;
53064  x.f = n;
53065  x.i = drwav__bswap64(x.i);
53066  return x.f;
53067 }
53068 static DRWAV_INLINE void drwav__bswap_samples_f64(double* pSamples, drwav_uint64 sampleCount)
53069 {
53070  drwav_uint64 iSample;
53071  for (iSample = 0; iSample < sampleCount; iSample += 1) {
53072  pSamples[iSample] = drwav__bswap_f64(pSamples[iSample]);
53073  }
53074 }
53075 static DRWAV_INLINE void drwav__bswap_samples_pcm(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
53076 {
53077  switch (bytesPerSample)
53078  {
53079  case 2:
53080  {
53081  drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
53082  } break;
53083  case 3:
53084  {
53085  drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
53086  } break;
53087  case 4:
53088  {
53089  drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
53090  } break;
53091  default:
53092  {
53094  } break;
53095  }
53096 }
53097 static DRWAV_INLINE void drwav__bswap_samples_ieee(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
53098 {
53099  switch (bytesPerSample)
53100  {
53101  #if 0
53102  case 2:
53103  {
53104  drwav__bswap_samples_f16((drwav_float16*)pSamples, sampleCount);
53105  } break;
53106  #endif
53107  case 4:
53108  {
53109  drwav__bswap_samples_f32((float*)pSamples, sampleCount);
53110  } break;
53111  case 8:
53112  {
53113  drwav__bswap_samples_f64((double*)pSamples, sampleCount);
53114  } break;
53115  default:
53116  {
53118  } break;
53119  }
53120 }
53121 static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample, drwav_uint16 format)
53122 {
53123  switch (format)
53124  {
53125  case DR_WAVE_FORMAT_PCM:
53126  {
53127  drwav__bswap_samples_pcm(pSamples, sampleCount, bytesPerSample);
53128  } break;
53130  {
53131  drwav__bswap_samples_ieee(pSamples, sampleCount, bytesPerSample);
53132  } break;
53133  case DR_WAVE_FORMAT_ALAW:
53134  case DR_WAVE_FORMAT_MULAW:
53135  {
53136  drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
53137  } break;
53138  case DR_WAVE_FORMAT_ADPCM:
53140  default:
53141  {
53143  } break;
53144  }
53145 }
53146 DRWAV_PRIVATE void* drwav__malloc_default(size_t sz, void* pUserData)
53147 {
53148  (void)pUserData;
53149  return DRWAV_MALLOC(sz);
53150 }
53151 DRWAV_PRIVATE void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
53152 {
53153  (void)pUserData;
53154  return DRWAV_REALLOC(p, sz);
53155 }
53156 DRWAV_PRIVATE void drwav__free_default(void* p, void* pUserData)
53157 {
53158  (void)pUserData;
53159  DRWAV_FREE(p);
53160 }
53161 DRWAV_PRIVATE void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
53162 {
53163  if (pAllocationCallbacks == NULL) {
53164  return NULL;
53165  }
53166  if (pAllocationCallbacks->onMalloc != NULL) {
53167  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
53168  }
53169  if (pAllocationCallbacks->onRealloc != NULL) {
53170  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
53171  }
53172  return NULL;
53173 }
53174 DRWAV_PRIVATE void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
53175 {
53176  if (pAllocationCallbacks == NULL) {
53177  return NULL;
53178  }
53179  if (pAllocationCallbacks->onRealloc != NULL) {
53180  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
53181  }
53182  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
53183  void* p2;
53184  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
53185  if (p2 == NULL) {
53186  return NULL;
53187  }
53188  if (p != NULL) {
53189  DRWAV_COPY_MEMORY(p2, p, szOld);
53190  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
53191  }
53192  return p2;
53193  }
53194  return NULL;
53195 }
53196 DRWAV_PRIVATE void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
53197 {
53198  if (p == NULL || pAllocationCallbacks == NULL) {
53199  return;
53200  }
53201  if (pAllocationCallbacks->onFree != NULL) {
53202  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
53203  }
53204 }
53206 {
53207  if (pAllocationCallbacks != NULL) {
53208  return *pAllocationCallbacks;
53209  } else {
53210  drwav_allocation_callbacks allocationCallbacks;
53211  allocationCallbacks.pUserData = NULL;
53212  allocationCallbacks.onMalloc = drwav__malloc_default;
53213  allocationCallbacks.onRealloc = drwav__realloc_default;
53214  allocationCallbacks.onFree = drwav__free_default;
53215  return allocationCallbacks;
53216  }
53217 }
53219 {
53220  return
53221  formatTag == DR_WAVE_FORMAT_ADPCM ||
53222  formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
53223 }
53225 {
53226  return (unsigned int)(chunkSize % 2);
53227 }
53229 {
53230  return (unsigned int)(chunkSize % 8);
53231 }
53235 DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
53236 {
53237  if (container == drwav_container_riff || container == drwav_container_rf64) {
53238  drwav_uint8 sizeInBytes[4];
53239  if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
53240  return DRWAV_AT_END;
53241  }
53242  if (onRead(pUserData, sizeInBytes, 4) != 4) {
53243  return DRWAV_INVALID_FILE;
53244  }
53245  pHeaderOut->sizeInBytes = drwav_bytes_to_u32(sizeInBytes);
53246  pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
53247  *pRunningBytesReadOut += 8;
53248  } else {
53249  drwav_uint8 sizeInBytes[8];
53250  if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
53251  return DRWAV_AT_END;
53252  }
53253  if (onRead(pUserData, sizeInBytes, 8) != 8) {
53254  return DRWAV_INVALID_FILE;
53255  }
53256  pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24;
53257  pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
53258  *pRunningBytesReadOut += 24;
53259  }
53260  return DRWAV_SUCCESS;
53261 }
53263 {
53264  drwav_uint64 bytesRemainingToSeek = offset;
53265  while (bytesRemainingToSeek > 0) {
53266  if (bytesRemainingToSeek > 0x7FFFFFFF) {
53267  if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
53268  return DRWAV_FALSE;
53269  }
53270  bytesRemainingToSeek -= 0x7FFFFFFF;
53271  } else {
53272  if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
53273  return DRWAV_FALSE;
53274  }
53275  bytesRemainingToSeek = 0;
53276  }
53277  }
53278  return DRWAV_TRUE;
53279 }
53281 {
53282  if (offset <= 0x7FFFFFFF) {
53283  return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
53284  }
53285  if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
53286  return DRWAV_FALSE;
53287  }
53288  offset -= 0x7FFFFFFF;
53289  for (;;) {
53290  if (offset <= 0x7FFFFFFF) {
53291  return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
53292  }
53293  if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
53294  return DRWAV_FALSE;
53295  }
53296  offset -= 0x7FFFFFFF;
53297  }
53298 }
53299 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)
53300 {
53302  drwav_uint8 fmt[16];
53303  if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
53304  return DRWAV_FALSE;
53305  }
53306  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))) {
53307  if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
53308  return DRWAV_FALSE;
53309  }
53310  *pRunningBytesReadOut += header.sizeInBytes + header.paddingSize;
53311  if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
53312  return DRWAV_FALSE;
53313  }
53314  }
53315  if (container == drwav_container_riff || container == drwav_container_rf64) {
53316  if (!drwav_fourcc_equal(header.id.fourcc, "fmt ")) {
53317  return DRWAV_FALSE;
53318  }
53319  } else {
53320  if (!drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT)) {
53321  return DRWAV_FALSE;
53322  }
53323  }
53324  if (onRead(pUserData, fmt, sizeof(fmt)) != sizeof(fmt)) {
53325  return DRWAV_FALSE;
53326  }
53327  *pRunningBytesReadOut += sizeof(fmt);
53328  fmtOut->formatTag = drwav_bytes_to_u16(fmt + 0);
53329  fmtOut->channels = drwav_bytes_to_u16(fmt + 2);
53330  fmtOut->sampleRate = drwav_bytes_to_u32(fmt + 4);
53331  fmtOut->avgBytesPerSec = drwav_bytes_to_u32(fmt + 8);
53332  fmtOut->blockAlign = drwav_bytes_to_u16(fmt + 12);
53333  fmtOut->bitsPerSample = drwav_bytes_to_u16(fmt + 14);
53334  fmtOut->extendedSize = 0;
53335  fmtOut->validBitsPerSample = 0;
53336  fmtOut->channelMask = 0;
53337  memset(fmtOut->subFormat, 0, sizeof(fmtOut->subFormat));
53338  if (header.sizeInBytes > 16) {
53339  drwav_uint8 fmt_cbSize[2];
53340  int bytesReadSoFar = 0;
53341  if (onRead(pUserData, fmt_cbSize, sizeof(fmt_cbSize)) != sizeof(fmt_cbSize)) {
53342  return DRWAV_FALSE;
53343  }
53344  *pRunningBytesReadOut += sizeof(fmt_cbSize);
53345  bytesReadSoFar = 18;
53346  fmtOut->extendedSize = drwav_bytes_to_u16(fmt_cbSize);
53347  if (fmtOut->extendedSize > 0) {
53348  if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
53349  if (fmtOut->extendedSize != 22) {
53350  return DRWAV_FALSE;
53351  }
53352  }
53353  if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
53354  drwav_uint8 fmtext[22];
53355  if (onRead(pUserData, fmtext, fmtOut->extendedSize) != fmtOut->extendedSize) {
53356  return DRWAV_FALSE;
53357  }
53358  fmtOut->validBitsPerSample = drwav_bytes_to_u16(fmtext + 0);
53359  fmtOut->channelMask = drwav_bytes_to_u32(fmtext + 2);
53360  drwav_bytes_to_guid(fmtext + 6, fmtOut->subFormat);
53361  } else {
53362  if (!onSeek(pUserData, fmtOut->extendedSize, drwav_seek_origin_current)) {
53363  return DRWAV_FALSE;
53364  }
53365  }
53366  *pRunningBytesReadOut += fmtOut->extendedSize;
53367  bytesReadSoFar += fmtOut->extendedSize;
53368  }
53369  if (!onSeek(pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current)) {
53370  return DRWAV_FALSE;
53371  }
53372  *pRunningBytesReadOut += (header.sizeInBytes - bytesReadSoFar);
53373  }
53374  if (header.paddingSize > 0) {
53375  if (!onSeek(pUserData, header.paddingSize, drwav_seek_origin_current)) {
53376  return DRWAV_FALSE;
53377  }
53378  *pRunningBytesReadOut += header.paddingSize;
53379  }
53380  return DRWAV_TRUE;
53381 }
53382 DRWAV_PRIVATE size_t drwav__on_read(drwav_read_proc onRead, void* pUserData, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
53383 {
53384  size_t bytesRead;
53385  DRWAV_ASSERT(onRead != NULL);
53386  DRWAV_ASSERT(pCursor != NULL);
53387  bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
53388  *pCursor += bytesRead;
53389  return bytesRead;
53390 }
53391 #if 0
53392 DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserData, int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
53393 {
53394  DRWAV_ASSERT(onSeek != NULL);
53395  DRWAV_ASSERT(pCursor != NULL);
53396  if (!onSeek(pUserData, offset, origin)) {
53397  return DRWAV_FALSE;
53398  }
53399  if (origin == drwav_seek_origin_start) {
53400  *pCursor = offset;
53401  } else {
53402  *pCursor += offset;
53403  }
53404  return DRWAV_TRUE;
53405 }
53406 #endif
53407 #define DRWAV_SMPL_BYTES 36
53408 #define DRWAV_SMPL_LOOP_BYTES 24
53409 #define DRWAV_INST_BYTES 7
53410 #define DRWAV_ACID_BYTES 24
53411 #define DRWAV_CUE_BYTES 4
53412 #define DRWAV_BEXT_BYTES 602
53413 #define DRWAV_BEXT_DESCRIPTION_BYTES 256
53414 #define DRWAV_BEXT_ORIGINATOR_NAME_BYTES 32
53415 #define DRWAV_BEXT_ORIGINATOR_REF_BYTES 32
53416 #define DRWAV_BEXT_RESERVED_BYTES 180
53417 #define DRWAV_BEXT_UMID_BYTES 64
53418 #define DRWAV_CUE_POINT_BYTES 24
53419 #define DRWAV_LIST_LABEL_OR_NOTE_BYTES 4
53420 #define DRWAV_LIST_LABELLED_TEXT_BYTES 20
53421 #define DRWAV_METADATA_ALIGNMENT 8
53422 typedef enum
53423 {
53427 typedef struct
53428 {
53429  drwav_read_proc onRead;
53430  drwav_seek_proc onSeek;
53431  void *pReadSeekUserData;
53433  drwav_metadata *pMetadata;
53434  drwav_uint32 metadataCount;
53435  drwav_uint8 *pData;
53436  drwav_uint8 *pDataCursor;
53437  drwav_uint64 metadataCursor;
53438  drwav_uint64 extraCapacity;
53441 {
53442  drwav_uint64 cap = sizeof(drwav_metadata) * (drwav_uint64)pParser->metadataCount + pParser->extraCapacity;
53443  if (cap > DRWAV_SIZE_MAX) {
53444  return 0;
53445  }
53446  return (size_t)cap;
53447 }
53448 DRWAV_PRIVATE drwav_uint8* drwav__metadata_get_memory(drwav__metadata_parser* pParser, size_t size, size_t align)
53449 {
53450  drwav_uint8* pResult;
53451  if (align) {
53452  drwav_uintptr modulo = (drwav_uintptr)pParser->pDataCursor % align;
53453  if (modulo != 0) {
53454  pParser->pDataCursor += align - modulo;
53455  }
53456  }
53457  pResult = pParser->pDataCursor;
53458  DRWAV_ASSERT((pResult + size) <= (pParser->pData + drwav__metadata_memory_capacity(pParser)));
53459  pParser->pDataCursor += size;
53460  return pResult;
53461 }
53463 {
53464  size_t extra = bytes + (align ? (align - 1) : 0);
53465  pParser->extraCapacity += extra;
53466 }
53468 {
53469  if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
53470  free(pParser->pData);
53471  pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
53472  pParser->pDataCursor = pParser->pData;
53473  if (pParser->pData == NULL) {
53474  return DRWAV_OUT_OF_MEMORY;
53475  }
53476  pParser->pMetadata = (drwav_metadata*)drwav__metadata_get_memory(pParser, sizeof(drwav_metadata) * pParser->metadataCount, 1);
53477  pParser->metadataCursor = 0;
53478  }
53479  return DRWAV_SUCCESS;
53480 }
53481 DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
53482 {
53483  if (pCursor != NULL) {
53484  return drwav__on_read(pParser->onRead, pParser->pReadSeekUserData, pBufferOut, bytesToRead, pCursor);
53485  } else {
53486  return pParser->onRead(pParser->pReadSeekUserData, pBufferOut, bytesToRead);
53487  }
53488 }
53490 {
53491  drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
53492  drwav_uint64 totalBytesRead = 0;
53493  size_t bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
53495  if (bytesJustRead == sizeof(smplHeaderData)) {
53496  drwav_uint32 iSampleLoop;
53497  pMetadata->type = drwav_metadata_type_smpl;
53498  pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
53499  pMetadata->data.smpl.productId = drwav_bytes_to_u32(smplHeaderData + 4);
53500  pMetadata->data.smpl.samplePeriodNanoseconds = drwav_bytes_to_u32(smplHeaderData + 8);
53501  pMetadata->data.smpl.midiUnityNote = drwav_bytes_to_u32(smplHeaderData + 12);
53502  pMetadata->data.smpl.midiPitchFraction = drwav_bytes_to_u32(smplHeaderData + 16);
53503  pMetadata->data.smpl.smpteFormat = drwav_bytes_to_u32(smplHeaderData + 20);
53504  pMetadata->data.smpl.smpteOffset = drwav_bytes_to_u32(smplHeaderData + 24);
53505  pMetadata->data.smpl.sampleLoopCount = drwav_bytes_to_u32(smplHeaderData + 28);
53506  pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
53508  for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
53509  drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
53510  bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
53511  if (bytesJustRead == sizeof(smplLoopData)) {
53512  pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
53513  pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
53514  pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
53515  pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
53516  pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
53517  pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
53518  } else {
53519  break;
53520  }
53521  }
53522  if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
53525  bytesJustRead = drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
53526  }
53527  }
53528  return totalBytesRead;
53529 }
53531 {
53532  drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
53533  drwav_uint64 totalBytesRead = 0;
53534  size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData, sizeof(cueHeaderSectionData), &totalBytesRead);
53536  if (bytesJustRead == sizeof(cueHeaderSectionData)) {
53537  pMetadata->type = drwav_metadata_type_cue;
53538  pMetadata->data.cue.cuePointCount = drwav_bytes_to_u32(cueHeaderSectionData);
53540  DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
53541  if (pMetadata->data.cue.cuePointCount > 0) {
53542  drwav_uint32 iCuePoint;
53543  for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
53544  drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
53545  bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData, sizeof(cuePointData), &totalBytesRead);
53546  if (bytesJustRead == sizeof(cuePointData)) {
53547  pMetadata->data.cue.pCuePoints[iCuePoint].id = drwav_bytes_to_u32(cuePointData + 0);
53548  pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
53549  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0] = cuePointData[8];
53550  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1] = cuePointData[9];
53551  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2] = cuePointData[10];
53552  pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
53553  pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
53554  pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
53555  pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
53556  } else {
53557  break;
53558  }
53559  }
53560  }
53561  }
53562  return totalBytesRead;
53563 }
53565 {
53566  drwav_uint8 instData[DRWAV_INST_BYTES];
53567  drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, instData, sizeof(instData), NULL);
53569  if (bytesRead == sizeof(instData)) {
53570  pMetadata->type = drwav_metadata_type_inst;
53571  pMetadata->data.inst.midiUnityNote = (drwav_int8)instData[0];
53572  pMetadata->data.inst.fineTuneCents = (drwav_int8)instData[1];
53573  pMetadata->data.inst.gainDecibels = (drwav_int8)instData[2];
53574  pMetadata->data.inst.lowNote = (drwav_int8)instData[3];
53575  pMetadata->data.inst.highNote = (drwav_int8)instData[4];
53576  pMetadata->data.inst.lowVelocity = (drwav_int8)instData[5];
53577  pMetadata->data.inst.highVelocity = (drwav_int8)instData[6];
53578  }
53579  return bytesRead;
53580 }
53582 {
53583  drwav_uint8 acidData[DRWAV_ACID_BYTES];
53584  drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
53586  if (bytesRead == sizeof(acidData)) {
53587  pMetadata->type = drwav_metadata_type_acid;
53588  pMetadata->data.acid.flags = drwav_bytes_to_u32(acidData + 0);
53589  pMetadata->data.acid.midiUnityNote = drwav_bytes_to_u16(acidData + 4);
53590  pMetadata->data.acid.reserved1 = drwav_bytes_to_u16(acidData + 6);
53591  pMetadata->data.acid.reserved2 = drwav_bytes_to_f32(acidData + 8);
53592  pMetadata->data.acid.numBeats = drwav_bytes_to_u32(acidData + 12);
53593  pMetadata->data.acid.meterDenominator = drwav_bytes_to_u16(acidData + 16);
53594  pMetadata->data.acid.meterNumerator = drwav_bytes_to_u16(acidData + 18);
53595  pMetadata->data.acid.tempo = drwav_bytes_to_f32(acidData + 20);
53596  }
53597  return bytesRead;
53598 }
53599 DRWAV_PRIVATE size_t drwav__strlen_clamped(char* str, size_t maxToRead)
53600 {
53601  size_t result = 0;
53602  while (*str++ && result < maxToRead) {
53603  result += 1;
53604  }
53605  return result;
53606 }
53607 DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, char* str, size_t maxToRead)
53608 {
53609  size_t len = drwav__strlen_clamped(str, maxToRead);
53610  if (len) {
53611  char* result = (char*)drwav__metadata_get_memory(pParser, len + 1, 1);
53612  DRWAV_ASSERT(result != NULL);
53613  memcpy(result, str, len);
53614  result[len] = '\0';
53615  return result;
53616  } else {
53617  return NULL;
53618  }
53619 }
53621 {
53622  drwav_uint8 bextData[DRWAV_BEXT_BYTES];
53623  drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
53625  if (bytesRead == sizeof(bextData)) {
53626  drwav_uint8* pReadPointer;
53627  drwav_uint32 timeReferenceLow;
53628  drwav_uint32 timeReferenceHigh;
53629  size_t extraBytes;
53630  pMetadata->type = drwav_metadata_type_bext;
53631  pReadPointer = bextData;
53632  pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_DESCRIPTION_BYTES);
53633  pReadPointer += DRWAV_BEXT_DESCRIPTION_BYTES;
53634  pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
53635  pReadPointer += DRWAV_BEXT_ORIGINATOR_NAME_BYTES;
53636  pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
53637  pReadPointer += DRWAV_BEXT_ORIGINATOR_REF_BYTES;
53638  memcpy(pReadPointer, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate));
53639  pReadPointer += sizeof(pMetadata->data.bext.pOriginationDate);
53640  memcpy(pReadPointer, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime));
53641  pReadPointer += sizeof(pMetadata->data.bext.pOriginationTime);
53642  timeReferenceLow = drwav_bytes_to_u32(pReadPointer);
53643  pReadPointer += sizeof(drwav_uint32);
53644  timeReferenceHigh = drwav_bytes_to_u32(pReadPointer);
53645  pReadPointer += sizeof(drwav_uint32);
53646  pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
53647  pMetadata->data.bext.version = drwav_bytes_to_u16(pReadPointer);
53648  pReadPointer += sizeof(drwav_uint16);
53650  memcpy(pMetadata->data.bext.pUMID, pReadPointer, DRWAV_BEXT_UMID_BYTES);
53651  pReadPointer += DRWAV_BEXT_UMID_BYTES;
53652  pMetadata->data.bext.loudnessValue = drwav_bytes_to_u16(pReadPointer);
53653  pReadPointer += sizeof(drwav_uint16);
53654  pMetadata->data.bext.loudnessRange = drwav_bytes_to_u16(pReadPointer);
53655  pReadPointer += sizeof(drwav_uint16);
53656  pMetadata->data.bext.maxTruePeakLevel = drwav_bytes_to_u16(pReadPointer);
53657  pReadPointer += sizeof(drwav_uint16);
53658  pMetadata->data.bext.maxMomentaryLoudness = drwav_bytes_to_u16(pReadPointer);
53659  pReadPointer += sizeof(drwav_uint16);
53660  pMetadata->data.bext.maxShortTermLoudness = drwav_bytes_to_u16(pReadPointer);
53661  pReadPointer += sizeof(drwav_uint16);
53662  DRWAV_ASSERT((pReadPointer + DRWAV_BEXT_RESERVED_BYTES) == (bextData + DRWAV_BEXT_BYTES));
53663  extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
53664  if (extraBytes > 0) {
53665  pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
53666  DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
53667  bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
53668  pMetadata->data.bext.codingHistorySize = (drwav_uint32)strlen(pMetadata->data.bext.pCodingHistory);
53669  } else {
53670  pMetadata->data.bext.pCodingHistory = NULL;
53671  pMetadata->data.bext.codingHistorySize = 0;
53672  }
53673  }
53674  return bytesRead;
53675 }
53677 {
53678  drwav_uint8 cueIDBuffer[DRWAV_LIST_LABEL_OR_NOTE_BYTES];
53679  drwav_uint64 totalBytesRead = 0;
53680  size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueIDBuffer, sizeof(cueIDBuffer), &totalBytesRead);
53682  if (bytesJustRead == sizeof(cueIDBuffer)) {
53683  drwav_uint32 sizeIncludingNullTerminator;
53684  pMetadata->type = type;
53685  pMetadata->data.labelOrNote.cuePointId = drwav_bytes_to_u32(cueIDBuffer);
53686  sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
53687  if (sizeIncludingNullTerminator > 0) {
53688  pMetadata->data.labelOrNote.stringLength = sizeIncludingNullTerminator - 1;
53689  pMetadata->data.labelOrNote.pString = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
53690  DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
53691  bytesJustRead = drwav__metadata_parser_read(pParser, pMetadata->data.labelOrNote.pString, sizeIncludingNullTerminator, &totalBytesRead);
53692  } else {
53693  pMetadata->data.labelOrNote.stringLength = 0;
53694  pMetadata->data.labelOrNote.pString = NULL;
53695  }
53696  }
53697  return totalBytesRead;
53698 }
53700 {
53701  drwav_uint8 buffer[DRWAV_LIST_LABELLED_TEXT_BYTES];
53702  drwav_uint64 totalBytesRead = 0;
53703  size_t bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &totalBytesRead);
53705  if (bytesJustRead == sizeof(buffer)) {
53706  drwav_uint32 sizeIncludingNullTerminator;
53708  pMetadata->data.labelledCueRegion.cuePointId = drwav_bytes_to_u32(buffer + 0);
53709  pMetadata->data.labelledCueRegion.sampleLength = drwav_bytes_to_u32(buffer + 4);
53710  pMetadata->data.labelledCueRegion.purposeId[0] = buffer[8];
53711  pMetadata->data.labelledCueRegion.purposeId[1] = buffer[9];
53712  pMetadata->data.labelledCueRegion.purposeId[2] = buffer[10];
53713  pMetadata->data.labelledCueRegion.purposeId[3] = buffer[11];
53714  pMetadata->data.labelledCueRegion.country = drwav_bytes_to_u16(buffer + 12);
53715  pMetadata->data.labelledCueRegion.language = drwav_bytes_to_u16(buffer + 14);
53716  pMetadata->data.labelledCueRegion.dialect = drwav_bytes_to_u16(buffer + 16);
53717  pMetadata->data.labelledCueRegion.codePage = drwav_bytes_to_u16(buffer + 18);
53718  sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
53719  if (sizeIncludingNullTerminator > 0) {
53720  pMetadata->data.labelledCueRegion.stringLength = sizeIncludingNullTerminator - 1;
53721  pMetadata->data.labelledCueRegion.pString = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
53723  bytesJustRead = drwav__metadata_parser_read(pParser, pMetadata->data.labelledCueRegion.pString, sizeIncludingNullTerminator, &totalBytesRead);
53724  } else {
53725  pMetadata->data.labelledCueRegion.stringLength = 0;
53726  pMetadata->data.labelledCueRegion.pString = NULL;
53727  }
53728  }
53729  return totalBytesRead;
53730 }
53732 {
53733  drwav_uint64 bytesRead = 0;
53734  drwav_uint32 stringSizeWithNullTerminator = (drwav_uint32)chunkSize;
53735  if (pParser->stage == drwav__metadata_parser_stage_count) {
53736  pParser->metadataCount += 1;
53737  drwav__metadata_request_extra_memory_for_stage_2(pParser, stringSizeWithNullTerminator, 1);
53738  } else {
53739  drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
53740  pMetadata->type = type;
53741  if (stringSizeWithNullTerminator > 0) {
53742  pMetadata->data.infoText.stringLength = stringSizeWithNullTerminator - 1;
53743  pMetadata->data.infoText.pString = (char*)drwav__metadata_get_memory(pParser, stringSizeWithNullTerminator, 1);
53744  DRWAV_ASSERT(pMetadata->data.infoText.pString != NULL);
53745  bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.infoText.pString, (size_t)stringSizeWithNullTerminator, NULL);
53746  if (bytesRead == chunkSize) {
53747  pParser->metadataCursor += 1;
53748  } else {
53749  }
53750  } else {
53751  pMetadata->data.infoText.stringLength = 0;
53752  pMetadata->data.infoText.pString = NULL;
53753  pParser->metadataCursor += 1;
53754  }
53755  }
53756  return bytesRead;
53757 }
53759 {
53760  drwav_uint64 bytesRead = 0;
53761  if (location == drwav_metadata_location_invalid) {
53762  return 0;
53763  }
53764  if (drwav_fourcc_equal(pChunkId, "data") || drwav_fourcc_equal(pChunkId, "fmt") || drwav_fourcc_equal(pChunkId, "fact")) {
53765  return 0;
53766  }
53767  if (pParser->stage == drwav__metadata_parser_stage_count) {
53768  pParser->metadataCount += 1;
53769  drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)chunkSize, 1);
53770  } else {
53771  drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
53772  pMetadata->type = drwav_metadata_type_unknown;
53773  pMetadata->data.unknown.chunkLocation = location;
53774  pMetadata->data.unknown.id[0] = pChunkId[0];
53775  pMetadata->data.unknown.id[1] = pChunkId[1];
53776  pMetadata->data.unknown.id[2] = pChunkId[2];
53777  pMetadata->data.unknown.id[3] = pChunkId[3];
53778  pMetadata->data.unknown.dataSizeInBytes = (drwav_uint32)chunkSize;
53779  pMetadata->data.unknown.pData = (drwav_uint8 *)drwav__metadata_get_memory(pParser, (size_t)chunkSize, 1);
53780  DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
53781  bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes, NULL);
53782  if (bytesRead == pMetadata->data.unknown.dataSizeInBytes) {
53783  pParser->metadataCursor += 1;
53784  } else {
53785  }
53786  }
53787  return bytesRead;
53788 }
53789 DRWAV_PRIVATE drwav_bool32 drwav__chunk_matches(drwav_uint64 allowedMetadataTypes, const drwav_uint8* pChunkID, drwav_metadata_type type, const char* pID)
53790 {
53791  return (allowedMetadataTypes & type) && drwav_fourcc_equal(pChunkID, pID);
53792 }
53794 {
53795  const drwav_uint8 *pChunkID = pChunkHeader->id.fourcc;
53796  drwav_uint64 bytesRead = 0;
53797  if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_smpl, "smpl")) {
53798  if (pChunkHeader->sizeInBytes >= DRWAV_SMPL_BYTES) {
53799  if (pParser->stage == drwav__metadata_parser_stage_count) {
53800  drwav_uint8 buffer[4];
53801  size_t bytesJustRead;
53802  if (!pParser->onSeek(pParser->pReadSeekUserData, 28, drwav_seek_origin_current)) {
53803  return bytesRead;
53804  }
53805  bytesRead += 28;
53806  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
53807  if (bytesJustRead == sizeof(buffer)) {
53808  drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
53809  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
53810  if (bytesJustRead == sizeof(buffer)) {
53811  drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
53812  pParser->metadataCount += 1;
53814  drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
53815  }
53816  }
53817  } else {
53818  bytesRead = drwav__read_smpl_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
53819  if (bytesRead == pChunkHeader->sizeInBytes) {
53820  pParser->metadataCursor += 1;
53821  } else {
53822  }
53823  }
53824  } else {
53825  }
53826  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_inst, "inst")) {
53827  if (pChunkHeader->sizeInBytes == DRWAV_INST_BYTES) {
53828  if (pParser->stage == drwav__metadata_parser_stage_count) {
53829  pParser->metadataCount += 1;
53830  } else {
53831  bytesRead = drwav__read_inst_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
53832  if (bytesRead == pChunkHeader->sizeInBytes) {
53833  pParser->metadataCursor += 1;
53834  } else {
53835  }
53836  }
53837  } else {
53838  }
53839  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_acid, "acid")) {
53840  if (pChunkHeader->sizeInBytes == DRWAV_ACID_BYTES) {
53841  if (pParser->stage == drwav__metadata_parser_stage_count) {
53842  pParser->metadataCount += 1;
53843  } else {
53844  bytesRead = drwav__read_acid_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
53845  if (bytesRead == pChunkHeader->sizeInBytes) {
53846  pParser->metadataCursor += 1;
53847  } else {
53848  }
53849  }
53850  } else {
53851  }
53852  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_cue, "cue ")) {
53853  if (pChunkHeader->sizeInBytes >= DRWAV_CUE_BYTES) {
53854  if (pParser->stage == drwav__metadata_parser_stage_count) {
53855  size_t cueCount;
53856  pParser->metadataCount += 1;
53857  cueCount = (size_t)(pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES;
53859  } else {
53860  bytesRead = drwav__read_cue_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
53861  if (bytesRead == pChunkHeader->sizeInBytes) {
53862  pParser->metadataCursor += 1;
53863  } else {
53864  }
53865  }
53866  } else {
53867  }
53868  } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_bext, "bext")) {
53869  if (pChunkHeader->sizeInBytes >= DRWAV_BEXT_BYTES) {
53870  if (pParser->stage == drwav__metadata_parser_stage_count) {
53871  char buffer[DRWAV_BEXT_DESCRIPTION_BYTES + 1];
53872  size_t allocSizeNeeded = DRWAV_BEXT_UMID_BYTES;
53873  size_t bytesJustRead;
53874  buffer[DRWAV_BEXT_DESCRIPTION_BYTES] = '\0';
53875  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_DESCRIPTION_BYTES, &bytesRead);
53876  if (bytesJustRead != DRWAV_BEXT_DESCRIPTION_BYTES) {
53877  return bytesRead;
53878  }
53879  allocSizeNeeded += strlen(buffer) + 1;
53880  buffer[DRWAV_BEXT_ORIGINATOR_NAME_BYTES] = '\0';
53881  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_NAME_BYTES, &bytesRead);
53882  if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_NAME_BYTES) {
53883  return bytesRead;
53884  }
53885  allocSizeNeeded += strlen(buffer) + 1;
53886  buffer[DRWAV_BEXT_ORIGINATOR_REF_BYTES] = '\0';
53887  bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_REF_BYTES, &bytesRead);
53888  if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_REF_BYTES) {
53889  return bytesRead;
53890  }
53891  allocSizeNeeded += strlen(buffer) + 1;
53892  allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES;
53893  drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
53894  pParser->metadataCount += 1;
53895  } else {
53896  bytesRead = drwav__read_bext_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], pChunkHeader->sizeInBytes);
53897  if (bytesRead == pChunkHeader->sizeInBytes) {
53898  pParser->metadataCursor += 1;
53899  } else {
53900  }
53901  }
53902  } else {
53903  }
53904  } else if (drwav_fourcc_equal(pChunkID, "LIST") || drwav_fourcc_equal(pChunkID, "list")) {
53906  while (bytesRead < pChunkHeader->sizeInBytes) {
53907  drwav_uint8 subchunkId[4];
53908  drwav_uint8 subchunkSizeBuffer[4];
53909  drwav_uint64 subchunkDataSize;
53910  drwav_uint64 subchunkBytesRead = 0;
53911  drwav_uint64 bytesJustRead = drwav__metadata_parser_read(pParser, subchunkId, sizeof(subchunkId), &bytesRead);
53912  if (bytesJustRead != sizeof(subchunkId)) {
53913  break;
53914  }
53915  if (drwav_fourcc_equal(subchunkId, "adtl")) {
53917  continue;
53918  } else if (drwav_fourcc_equal(subchunkId, "INFO")) {
53920  continue;
53921  }
53922  bytesJustRead = drwav__metadata_parser_read(pParser, subchunkSizeBuffer, sizeof(subchunkSizeBuffer), &bytesRead);
53923  if (bytesJustRead != sizeof(subchunkSizeBuffer)) {
53924  break;
53925  }
53926  subchunkDataSize = drwav_bytes_to_u32(subchunkSizeBuffer);
53927  if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_label, "labl") || drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_note, "note")) {
53928  if (subchunkDataSize >= DRWAV_LIST_LABEL_OR_NOTE_BYTES) {
53929  drwav_uint64 stringSizeWithNullTerm = subchunkDataSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
53930  if (pParser->stage == drwav__metadata_parser_stage_count) {
53931  pParser->metadataCount += 1;
53932  drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerm, 1);
53933  } else {
53934  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);
53935  if (subchunkBytesRead == subchunkDataSize) {
53936  pParser->metadataCursor += 1;
53937  } else {
53938  }
53939  }
53940  } else {
53941  }
53942  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_labelled_cue_region, "ltxt")) {
53943  if (subchunkDataSize >= DRWAV_LIST_LABELLED_TEXT_BYTES) {
53944  drwav_uint64 stringSizeWithNullTerminator = subchunkDataSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
53945  if (pParser->stage == drwav__metadata_parser_stage_count) {
53946  pParser->metadataCount += 1;
53947  drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerminator, 1);
53948  } else {
53949  subchunkBytesRead = drwav__read_list_labelled_cue_region_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize);
53950  if (subchunkBytesRead == subchunkDataSize) {
53951  pParser->metadataCursor += 1;
53952  } else {
53953  }
53954  }
53955  } else {
53956  }
53957  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_software, "ISFT")) {
53958  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_software);
53959  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_copyright, "ICOP")) {
53960  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_copyright);
53961  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_title, "INAM")) {
53962  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_title);
53963  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_artist, "IART")) {
53964  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_artist);
53965  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_comment, "ICMT")) {
53966  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_comment);
53967  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_date, "ICRD")) {
53968  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_date);
53969  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_genre, "IGNR")) {
53970  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_genre);
53971  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_album, "IPRD")) {
53972  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
53973  } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
53974  subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
53975  } else if (allowedMetadataTypes & drwav_metadata_type_unknown) {
53976  subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
53977  }
53978  bytesRead += subchunkBytesRead;
53979  DRWAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
53980  if (subchunkBytesRead < subchunkDataSize) {
53981  drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
53982  if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, drwav_seek_origin_current)) {
53983  break;
53984  }
53985  bytesRead += bytesToSeek;
53986  }
53987  if ((subchunkDataSize % 2) == 1) {
53988  if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
53989  break;
53990  }
53991  bytesRead += 1;
53992  }
53993  }
53994  } else if (allowedMetadataTypes & drwav_metadata_type_unknown) {
53995  bytesRead = drwav__metadata_process_unknown_chunk(pParser, pChunkID, pChunkHeader->sizeInBytes, drwav_metadata_location_top_level);
53996  }
53997  return bytesRead;
53998 }
54000 {
54001  if ((pWav->bitsPerSample & 0x7) == 0) {
54002  return (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
54003  } else {
54004  return pWav->fmt.blockAlign;
54005  }
54006 }
54008 {
54009  if (pFMT == NULL) {
54010  return 0;
54011  }
54012  if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
54013  return pFMT->formatTag;
54014  } else {
54015  return drwav_bytes_to_u16(pFMT->subFormat);
54016  }
54017 }
54018 DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
54019 {
54020  if (pWav == NULL || onRead == NULL || onSeek == NULL) {
54021  return DRWAV_FALSE;
54022  }
54023  DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
54024  pWav->onRead = onRead;
54025  pWav->onSeek = onSeek;
54026  pWav->pUserData = pReadSeekUserData;
54029  return DRWAV_FALSE;
54030  }
54031  return DRWAV_TRUE;
54032 }
54033 DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags)
54034 {
54035  drwav_uint64 cursor;
54036  drwav_bool32 sequential;
54037  drwav_uint8 riff[4];
54038  drwav_fmt fmt;
54039  unsigned short translatedFormatTag;
54040  drwav_bool32 foundDataChunk;
54041  drwav_uint64 dataChunkSize = 0;
54042  drwav_uint64 sampleCountFromFactChunk = 0;
54043  drwav_uint64 chunkSize;
54044  drwav__metadata_parser metadataParser;
54045  cursor = 0;
54046  sequential = (flags & DRWAV_SEQUENTIAL) != 0;
54047  if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
54048  return DRWAV_FALSE;
54049  }
54050  if (drwav_fourcc_equal(riff, "RIFF")) {
54052  } else if (drwav_fourcc_equal(riff, "riff")) {
54053  int i;
54054  drwav_uint8 riff2[12];
54056  if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
54057  return DRWAV_FALSE;
54058  }
54059  for (i = 0; i < 12; ++i) {
54060  if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
54061  return DRWAV_FALSE;
54062  }
54063  }
54064  } else if (drwav_fourcc_equal(riff, "RF64")) {
54066  } else {
54067  return DRWAV_FALSE;
54068  }
54069  if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
54070  drwav_uint8 chunkSizeBytes[4];
54071  drwav_uint8 wave[4];
54072  if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
54073  return DRWAV_FALSE;
54074  }
54075  if (pWav->container == drwav_container_riff) {
54076  if (drwav_bytes_to_u32(chunkSizeBytes) < 36) {
54077  return DRWAV_FALSE;
54078  }
54079  } else {
54080  if (drwav_bytes_to_u32(chunkSizeBytes) != 0xFFFFFFFF) {
54081  return DRWAV_FALSE;
54082  }
54083  }
54084  if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
54085  return DRWAV_FALSE;
54086  }
54087  if (!drwav_fourcc_equal(wave, "WAVE")) {
54088  return DRWAV_FALSE;
54089  }
54090  } else {
54091  drwav_uint8 chunkSizeBytes[8];
54092  drwav_uint8 wave[16];
54093  if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
54094  return DRWAV_FALSE;
54095  }
54096  if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
54097  return DRWAV_FALSE;
54098  }
54099  if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
54100  return DRWAV_FALSE;
54101  }
54102  if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
54103  return DRWAV_FALSE;
54104  }
54105  }
54106  if (pWav->container == drwav_container_rf64) {
54107  drwav_uint8 sizeBytes[8];
54108  drwav_uint64 bytesRemainingInChunk;
54110  drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
54111  if (result != DRWAV_SUCCESS) {
54112  return DRWAV_FALSE;
54113  }
54114  if (!drwav_fourcc_equal(header.id.fourcc, "ds64")) {
54115  return DRWAV_FALSE;
54116  }
54117  bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
54118  if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
54119  return DRWAV_FALSE;
54120  }
54121  bytesRemainingInChunk -= 8;
54122  cursor += 8;
54123  if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
54124  return DRWAV_FALSE;
54125  }
54126  bytesRemainingInChunk -= 8;
54127  dataChunkSize = drwav_bytes_to_u64(sizeBytes);
54128  if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
54129  return DRWAV_FALSE;
54130  }
54131  bytesRemainingInChunk -= 8;
54132  sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
54133  if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
54134  return DRWAV_FALSE;
54135  }
54136  cursor += bytesRemainingInChunk;
54137  }
54138  if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
54139  return DRWAV_FALSE;
54140  }
54141  if ((fmt.sampleRate == 0 || fmt.sampleRate > DRWAV_MAX_SAMPLE_RATE) ||
54142  (fmt.channels == 0 || fmt.channels > DRWAV_MAX_CHANNELS) ||
54144  fmt.blockAlign == 0) {
54145  return DRWAV_FALSE;
54146  }
54147  translatedFormatTag = fmt.formatTag;
54148  if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
54149  translatedFormatTag = drwav_bytes_to_u16(fmt.subFormat + 0);
54150  }
54151  memset(&metadataParser, 0, sizeof(metadataParser));
54152  if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
54153  drwav_uint64 cursorForMetadata = cursor;
54154  metadataParser.onRead = pWav->onRead;
54155  metadataParser.onSeek = pWav->onSeek;
54156  metadataParser.pReadSeekUserData = pWav->pUserData;
54157  metadataParser.stage = drwav__metadata_parser_stage_count;
54158  for (;;) {
54159  drwav_result result;
54160  drwav_uint64 bytesRead;
54161  drwav_uint64 remainingBytes;
54163  result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursorForMetadata, &header);
54164  if (result != DRWAV_SUCCESS) {
54165  break;
54166  }
54167  bytesRead = drwav__metadata_process_chunk(&metadataParser, &header, pWav->allowedMetadataTypes);
54168  DRWAV_ASSERT(bytesRead <= header.sizeInBytes);
54169  remainingBytes = header.sizeInBytes - bytesRead + header.paddingSize;
54170  if (!drwav__seek_forward(pWav->onSeek, remainingBytes, pWav->pUserData)) {
54171  break;
54172  }
54173  cursorForMetadata += remainingBytes;
54174  }
54175  if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
54176  return DRWAV_FALSE;
54177  }
54178  drwav__metadata_alloc(&metadataParser, &pWav->allocationCallbacks);
54179  metadataParser.stage = drwav__metadata_parser_stage_read;
54180  }
54181  foundDataChunk = DRWAV_FALSE;
54182  for (;;) {
54184  drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
54185  if (result != DRWAV_SUCCESS) {
54186  if (!foundDataChunk) {
54187  return DRWAV_FALSE;
54188  } else {
54189  break;
54190  }
54191  }
54192  if (!sequential && onChunk != NULL) {
54193  drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
54194  if (callbackBytesRead > 0) {
54195  if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
54196  return DRWAV_FALSE;
54197  }
54198  }
54199  }
54200  if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
54201  drwav_uint64 bytesRead = drwav__metadata_process_chunk(&metadataParser, &header, pWav->allowedMetadataTypes);
54202  if (bytesRead > 0) {
54203  if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
54204  return DRWAV_FALSE;
54205  }
54206  }
54207  }
54208  if (!foundDataChunk) {
54209  pWav->dataChunkDataPos = cursor;
54210  }
54211  chunkSize = header.sizeInBytes;
54212  if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
54213  if (drwav_fourcc_equal(header.id.fourcc, "data")) {
54214  foundDataChunk = DRWAV_TRUE;
54215  if (pWav->container != drwav_container_rf64) {
54216  dataChunkSize = chunkSize;
54217  }
54218  }
54219  } else {
54220  if (drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
54221  foundDataChunk = DRWAV_TRUE;
54222  dataChunkSize = chunkSize;
54223  }
54224  }
54225  if (foundDataChunk && sequential) {
54226  break;
54227  }
54228  if (pWav->container == drwav_container_riff) {
54229  if (drwav_fourcc_equal(header.id.fourcc, "fact")) {
54230  drwav_uint32 sampleCount;
54231  if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
54232  return DRWAV_FALSE;
54233  }
54234  chunkSize -= 4;
54235  if (!foundDataChunk) {
54236  pWav->dataChunkDataPos = cursor;
54237  }
54239  sampleCountFromFactChunk = sampleCount;
54240  } else {
54241  sampleCountFromFactChunk = 0;
54242  }
54243  }
54244  } else if (pWav->container == drwav_container_w64) {
54245  if (drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
54246  if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
54247  return DRWAV_FALSE;
54248  }
54249  chunkSize -= 8;
54250  if (!foundDataChunk) {
54251  pWav->dataChunkDataPos = cursor;
54252  }
54253  }
54254  } else if (pWav->container == drwav_container_rf64) {
54255  }
54256  chunkSize += header.paddingSize;
54257  if (!drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData)) {
54258  break;
54259  }
54260  cursor += chunkSize;
54261  if (!foundDataChunk) {
54262  pWav->dataChunkDataPos = cursor;
54263  }
54264  }
54265  pWav->pMetadata = metadataParser.pMetadata;
54266  pWav->metadataCount = metadataParser.metadataCount;
54267  if (!foundDataChunk) {
54268  return DRWAV_FALSE;
54269  }
54270  if (!sequential) {
54271  if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
54272  return DRWAV_FALSE;
54273  }
54274  cursor = pWav->dataChunkDataPos;
54275  }
54276  pWav->fmt = fmt;
54277  pWav->sampleRate = fmt.sampleRate;
54278  pWav->channels = fmt.channels;
54279  pWav->bitsPerSample = fmt.bitsPerSample;
54280  pWav->bytesRemaining = dataChunkSize;
54281  pWav->translatedFormatTag = translatedFormatTag;
54282  pWav->dataChunkDataSize = dataChunkSize;
54283  if (sampleCountFromFactChunk != 0) {
54284  pWav->totalPCMFrameCount = sampleCountFromFactChunk;
54285  } else {
54286  pWav->totalPCMFrameCount = dataChunkSize / drwav_get_bytes_per_pcm_frame(pWav);
54288  drwav_uint64 totalBlockHeaderSizeInBytes;
54289  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
54290  if ((blockCount * fmt.blockAlign) < dataChunkSize) {
54291  blockCount += 1;
54292  }
54293  totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
54294  pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
54295  }
54297  drwav_uint64 totalBlockHeaderSizeInBytes;
54298  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
54299  if ((blockCount * fmt.blockAlign) < dataChunkSize) {
54300  blockCount += 1;
54301  }
54302  totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
54303  pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
54304  pWav->totalPCMFrameCount += blockCount;
54305  }
54306  }
54308  if (pWav->channels > 2) {
54309  return DRWAV_FALSE;
54310  }
54311  }
54312 #ifdef DR_WAV_LIBSNDFILE_COMPAT
54314  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
54315  pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;
54316  }
54318  drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
54319  pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
54320  }
54321 #endif
54322  return DRWAV_TRUE;
54323 }
54324 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
54325 {
54326  return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
54327 }
54328 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)
54329 {
54330  if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
54331  return DRWAV_FALSE;
54332  }
54333  return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
54334 }
54335 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)
54336 {
54337  if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
54338  return DRWAV_FALSE;
54339  }
54341  return drwav_init__internal(pWav, NULL, NULL, flags);
54342 }
54344 {
54345  drwav_metadata *result = pWav->pMetadata;
54346  pWav->pMetadata = NULL;
54347  pWav->metadataCount = 0;
54348  return result;
54349 }
54350 DRWAV_PRIVATE size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
54351 {
54352  DRWAV_ASSERT(pWav != NULL);
54353  DRWAV_ASSERT(pWav->onWrite != NULL);
54354  return pWav->onWrite(pWav->pUserData, pData, dataSize);
54355 }
54357 {
54358  DRWAV_ASSERT(pWav != NULL);
54359  DRWAV_ASSERT(pWav->onWrite != NULL);
54360  return pWav->onWrite(pWav->pUserData, &byte, 1);
54361 }
54363 {
54364  DRWAV_ASSERT(pWav != NULL);
54365  DRWAV_ASSERT(pWav->onWrite != NULL);
54366  if (!drwav__is_little_endian()) {
54367  value = drwav__bswap16(value);
54368  }
54369  return drwav__write(pWav, &value, 2);
54370 }
54372 {
54373  DRWAV_ASSERT(pWav != NULL);
54374  DRWAV_ASSERT(pWav->onWrite != NULL);
54375  if (!drwav__is_little_endian()) {
54376  value = drwav__bswap32(value);
54377  }
54378  return drwav__write(pWav, &value, 4);
54379 }
54381 {
54382  DRWAV_ASSERT(pWav != NULL);
54383  DRWAV_ASSERT(pWav->onWrite != NULL);
54384  if (!drwav__is_little_endian()) {
54385  value = drwav__bswap64(value);
54386  }
54387  return drwav__write(pWav, &value, 8);
54388 }
54389 DRWAV_PRIVATE size_t drwav__write_f32ne_to_le(drwav* pWav, float value)
54390 {
54391  union {
54392  drwav_uint32 u32;
54393  float f32;
54394  } u;
54395  DRWAV_ASSERT(pWav != NULL);
54396  DRWAV_ASSERT(pWav->onWrite != NULL);
54397  u.f32 = value;
54398  if (!drwav__is_little_endian()) {
54399  u.u32 = drwav__bswap32(u.u32);
54400  }
54401  return drwav__write(pWav, &u.u32, 4);
54402 }
54403 DRWAV_PRIVATE size_t drwav__write_or_count(drwav* pWav, const void* pData, size_t dataSize)
54404 {
54405  if (pWav == NULL) {
54406  return dataSize;
54407  }
54408  return drwav__write(pWav, pData, dataSize);
54409 }
54411 {
54412  if (pWav == NULL) {
54413  return 1;
54414  }
54415  return drwav__write_byte(pWav, byte);
54416 }
54418 {
54419  if (pWav == NULL) {
54420  return 2;
54421  }
54422  return drwav__write_u16ne_to_le(pWav, value);
54423 }
54425 {
54426  if (pWav == NULL) {
54427  return 4;
54428  }
54429  return drwav__write_u32ne_to_le(pWav, value);
54430 }
54431 #if 0
54432 DRWAV_PRIVATE size_t drwav__write_or_count_u64ne_to_le(drwav* pWav, drwav_uint64 value)
54433 {
54434  if (pWav == NULL) {
54435  return 8;
54436  }
54437  return drwav__write_u64ne_to_le(pWav, value);
54438 }
54439 #endif
54440 DRWAV_PRIVATE size_t drwav__write_or_count_f32ne_to_le(drwav* pWav, float value)
54441 {
54442  if (pWav == NULL) {
54443  return 4;
54444  }
54445  return drwav__write_f32ne_to_le(pWav, value);
54446 }
54447 DRWAV_PRIVATE size_t drwav__write_or_count_string_to_fixed_size_buf(drwav* pWav, char* str, size_t bufFixedSize)
54448 {
54449  size_t len;
54450  if (pWav == NULL) {
54451  return bufFixedSize;
54452  }
54453  len = drwav__strlen_clamped(str, bufFixedSize);
54454  drwav__write_or_count(pWav, str, len);
54455  if (len < bufFixedSize) {
54456  size_t i;
54457  for (i = 0; i < bufFixedSize - len; ++i) {
54458  drwav__write_byte(pWav, 0);
54459  }
54460  }
54461  return bufFixedSize;
54462 }
54463 DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav* pWav, drwav_metadata* pMetadatas, drwav_uint32 metadataCount)
54464 {
54465  size_t bytesWritten = 0;
54466  drwav_bool32 hasListAdtl = DRWAV_FALSE;
54467  drwav_bool32 hasListInfo = DRWAV_FALSE;
54468  drwav_uint32 iMetadata;
54469  if (pMetadatas == NULL || metadataCount == 0) {
54470  return 0;
54471  }
54472  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
54473  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
54474  drwav_uint32 chunkSize = 0;
54476  hasListInfo = DRWAV_TRUE;
54477  }
54479  hasListAdtl = DRWAV_TRUE;
54480  }
54481  switch (pMetadata->type) {
54482  case drwav_metadata_type_smpl:
54483  {
54484  drwav_uint32 iLoop;
54485  chunkSize = DRWAV_SMPL_BYTES + DRWAV_SMPL_LOOP_BYTES * pMetadata->data.smpl.sampleLoopCount + pMetadata->data.smpl.samplerSpecificDataSizeInBytes;
54486  bytesWritten += drwav__write_or_count(pWav, "smpl", 4);
54487  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54488  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.manufacturerId);
54489  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.productId);
54490  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplePeriodNanoseconds);
54491  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiUnityNote);
54492  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiPitchFraction);
54493  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteFormat);
54494  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteOffset);
54495  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.sampleLoopCount);
54496  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
54497  for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
54498  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
54499  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
54500  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
54501  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
54502  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
54503  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
54504  }
54505  if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
54506  bytesWritten += drwav__write(pWav, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
54507  }
54508  } break;
54510  {
54511  chunkSize = DRWAV_INST_BYTES;
54512  bytesWritten += drwav__write_or_count(pWav, "inst", 4);
54513  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54514  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.midiUnityNote, 1);
54515  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.fineTuneCents, 1);
54516  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.gainDecibels, 1);
54517  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowNote, 1);
54518  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highNote, 1);
54519  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowVelocity, 1);
54520  bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highVelocity, 1);
54521  } break;
54523  {
54524  drwav_uint32 iCuePoint;
54525  chunkSize = DRWAV_CUE_BYTES + DRWAV_CUE_POINT_BYTES * pMetadata->data.cue.cuePointCount;
54526  bytesWritten += drwav__write_or_count(pWav, "cue ", 4);
54527  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54528  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.cuePointCount);
54529  for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
54530  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].id);
54531  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition);
54532  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
54533  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
54534  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
54535  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
54536  }
54537  } break;
54539  {
54540  chunkSize = DRWAV_ACID_BYTES;
54541  bytesWritten += drwav__write_or_count(pWav, "acid", 4);
54542  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54543  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.flags);
54544  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.midiUnityNote);
54545  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.reserved1);
54546  bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.reserved2);
54547  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.numBeats);
54548  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterDenominator);
54549  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterNumerator);
54550  bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.tempo);
54551  } break;
54553  {
54554  char reservedBuf[DRWAV_BEXT_RESERVED_BYTES];
54555  drwav_uint32 timeReferenceLow;
54556  drwav_uint32 timeReferenceHigh;
54557  chunkSize = DRWAV_BEXT_BYTES + pMetadata->data.bext.codingHistorySize;
54558  bytesWritten += drwav__write_or_count(pWav, "bext", 4);
54559  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54560  bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pDescription, DRWAV_BEXT_DESCRIPTION_BYTES);
54561  bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorName, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
54562  bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorReference, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
54563  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate));
54564  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime));
54565  timeReferenceLow = (drwav_uint32)(pMetadata->data.bext.timeReference & 0xFFFFFFFF);
54566  timeReferenceHigh = (drwav_uint32)(pMetadata->data.bext.timeReference >> 32);
54567  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceLow);
54568  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceHigh);
54569  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.version);
54570  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES);
54571  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessValue);
54572  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessRange);
54573  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxTruePeakLevel);
54574  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxMomentaryLoudness);
54575  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxShortTermLoudness);
54576  memset(reservedBuf, 0, sizeof(reservedBuf));
54577  bytesWritten += drwav__write_or_count(pWav, reservedBuf, sizeof(reservedBuf));
54578  if (pMetadata->data.bext.codingHistorySize > 0) {
54579  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pCodingHistory, pMetadata->data.bext.codingHistorySize);
54580  }
54581  } break;
54583  {
54585  chunkSize = pMetadata->data.unknown.dataSizeInBytes;
54586  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
54587  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54588  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes);
54589  }
54590  } break;
54591  default: break;
54592  }
54593  if ((chunkSize % 2) != 0) {
54594  bytesWritten += drwav__write_or_count_byte(pWav, 0);
54595  }
54596  }
54597  if (hasListInfo) {
54598  drwav_uint32 chunkSize = 4;
54599  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
54600  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
54601  if ((pMetadata->type & drwav_metadata_type_list_all_info_strings)) {
54602  chunkSize += 8;
54603  chunkSize += pMetadata->data.infoText.stringLength + 1;
54605  chunkSize += 8;
54606  chunkSize += pMetadata->data.unknown.dataSizeInBytes;
54607  }
54608  if ((chunkSize % 2) != 0) {
54609  chunkSize += 1;
54610  }
54611  }
54612  bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
54613  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54614  bytesWritten += drwav__write_or_count(pWav, "INFO", 4);
54615  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
54616  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
54617  drwav_uint32 subchunkSize = 0;
54619  const char* pID = NULL;
54620  switch (pMetadata->type) {
54621  case drwav_metadata_type_list_info_software: pID = "ISFT"; break;
54622  case drwav_metadata_type_list_info_copyright: pID = "ICOP"; break;
54623  case drwav_metadata_type_list_info_title: pID = "INAM"; break;
54624  case drwav_metadata_type_list_info_artist: pID = "IART"; break;
54625  case drwav_metadata_type_list_info_comment: pID = "ICMT"; break;
54626  case drwav_metadata_type_list_info_date: pID = "ICRD"; break;
54627  case drwav_metadata_type_list_info_genre: pID = "IGNR"; break;
54628  case drwav_metadata_type_list_info_album: pID = "IPRD"; break;
54629  case drwav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
54630  default: break;
54631  }
54632  DRWAV_ASSERT(pID != NULL);
54633  if (pMetadata->data.infoText.stringLength) {
54634  subchunkSize = pMetadata->data.infoText.stringLength + 1;
54635  bytesWritten += drwav__write_or_count(pWav, pID, 4);
54636  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
54637  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.infoText.pString, pMetadata->data.infoText.stringLength);
54638  bytesWritten += drwav__write_or_count_byte(pWav, '\0');
54639  }
54641  if (pMetadata->data.unknown.dataSizeInBytes) {
54642  subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
54643  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
54644  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.unknown.dataSizeInBytes);
54645  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
54646  }
54647  }
54648  if ((subchunkSize % 2) != 0) {
54649  bytesWritten += drwav__write_or_count_byte(pWav, 0);
54650  }
54651  }
54652  }
54653  if (hasListAdtl) {
54654  drwav_uint32 chunkSize = 4;
54655  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
54656  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
54657  switch (pMetadata->type)
54658  {
54659  case drwav_metadata_type_list_label:
54660  case drwav_metadata_type_list_note:
54661  {
54662  chunkSize += 8;
54663  chunkSize += DRWAV_LIST_LABEL_OR_NOTE_BYTES;
54664  if (pMetadata->data.labelOrNote.stringLength > 0) {
54665  chunkSize += pMetadata->data.labelOrNote.stringLength + 1;
54666  }
54667  } break;
54669  {
54670  chunkSize += 8;
54671  chunkSize += DRWAV_LIST_LABELLED_TEXT_BYTES;
54672  if (pMetadata->data.labelledCueRegion.stringLength > 0) {
54673  chunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
54674  }
54675  } break;
54677  {
54679  chunkSize += 8;
54680  chunkSize += pMetadata->data.unknown.dataSizeInBytes;
54681  }
54682  } break;
54683  default: break;
54684  }
54685  if ((chunkSize % 2) != 0) {
54686  chunkSize += 1;
54687  }
54688  }
54689  bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
54690  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
54691  bytesWritten += drwav__write_or_count(pWav, "adtl", 4);
54692  for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
54693  drwav_metadata* pMetadata = &pMetadatas[iMetadata];
54694  drwav_uint32 subchunkSize = 0;
54695  switch (pMetadata->type)
54696  {
54697  case drwav_metadata_type_list_label:
54698  case drwav_metadata_type_list_note:
54699  {
54700  if (pMetadata->data.labelOrNote.stringLength > 0) {
54701  const char *pID = NULL;
54702  if (pMetadata->type == drwav_metadata_type_list_label) {
54703  pID = "labl";
54704  }
54705  else if (pMetadata->type == drwav_metadata_type_list_note) {
54706  pID = "note";
54707  }
54708  DRWAV_ASSERT(pID != NULL);
54709  DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
54710  subchunkSize = DRWAV_LIST_LABEL_OR_NOTE_BYTES;
54711  bytesWritten += drwav__write_or_count(pWav, pID, 4);
54712  subchunkSize += pMetadata->data.labelOrNote.stringLength + 1;
54713  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
54714  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelOrNote.cuePointId);
54715  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelOrNote.pString, pMetadata->data.labelOrNote.stringLength);
54716  bytesWritten += drwav__write_or_count_byte(pWav, '\0');
54717  }
54718  } break;
54720  {
54721  subchunkSize = DRWAV_LIST_LABELLED_TEXT_BYTES;
54722  bytesWritten += drwav__write_or_count(pWav, "ltxt", 4);
54723  if (pMetadata->data.labelledCueRegion.stringLength > 0) {
54724  subchunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
54725  }
54726  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
54727  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.cuePointId);
54728  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.sampleLength);
54729  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.purposeId, 4);
54730  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.country);
54731  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.language);
54732  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.dialect);
54733  bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.codePage);
54734  if (pMetadata->data.labelledCueRegion.stringLength > 0) {
54735  DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
54736  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.pString, pMetadata->data.labelledCueRegion.stringLength);
54737  bytesWritten += drwav__write_or_count_byte(pWav, '\0');
54738  }
54739  } break;
54741  {
54743  subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
54744  DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
54745  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
54746  bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
54747  bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
54748  }
54749  } break;
54750  default: break;
54751  }
54752  if ((subchunkSize % 2) != 0) {
54753  bytesWritten += drwav__write_or_count_byte(pWav, 0);
54754  }
54755  }
54756  }
54757  DRWAV_ASSERT((bytesWritten % 2) == 0);
54758  return bytesWritten;
54759 }
54761 {
54762  drwav_uint64 chunkSize = 4 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, pMetadata, metadataCount) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
54763  if (chunkSize > 0xFFFFFFFFUL) {
54764  chunkSize = 0xFFFFFFFFUL;
54765  }
54766  return (drwav_uint32)chunkSize;
54767 }
54769 {
54770  if (dataChunkSize <= 0xFFFFFFFFUL) {
54771  return (drwav_uint32)dataChunkSize;
54772  } else {
54773  return 0xFFFFFFFFUL;
54774  }
54775 }
54777 {
54778  drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
54779  return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;
54780 }
54782 {
54783  return 24 + dataChunkSize;
54784 }
54786 {
54787  drwav_uint64 chunkSize = 4 + 36 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, metadata, numMetadata) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
54788  if (chunkSize > 0xFFFFFFFFUL) {
54789  chunkSize = 0xFFFFFFFFUL;
54790  }
54791  return chunkSize;
54792 }
54794 {
54795  return dataChunkSize;
54796 }
54797 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)
54798 {
54799  if (pWav == NULL || onWrite == NULL) {
54800  return DRWAV_FALSE;
54801  }
54802  if (!isSequential && onSeek == NULL) {
54803  return DRWAV_FALSE;
54804  }
54805  if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
54806  return DRWAV_FALSE;
54807  }
54808  if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
54809  return DRWAV_FALSE;
54810  }
54811  DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
54812  pWav->onWrite = onWrite;
54813  pWav->onSeek = onSeek;
54814  pWav->pUserData = pUserData;
54817  return DRWAV_FALSE;
54818  }
54819  pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
54820  pWav->fmt.channels = (drwav_uint16)pFormat->channels;
54821  pWav->fmt.sampleRate = pFormat->sampleRate;
54822  pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
54823  pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
54824  pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
54825  pWav->fmt.extendedSize = 0;
54826  pWav->isSequentialWrite = isSequential;
54827  return DRWAV_TRUE;
54828 }
54830 {
54831  size_t runningPos = 0;
54832  drwav_uint64 initialDataChunkSize = 0;
54833  drwav_uint64 chunkSizeFMT;
54834  if (pWav->isSequentialWrite) {
54835  initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
54836  if (pFormat->container == drwav_container_riff) {
54837  if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
54838  return DRWAV_FALSE;
54839  }
54840  }
54841  }
54842  pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
54843  if (pFormat->container == drwav_container_riff) {
54844  drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;
54845  runningPos += drwav__write(pWav, "RIFF", 4);
54846  runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
54847  runningPos += drwav__write(pWav, "WAVE", 4);
54848  } else if (pFormat->container == drwav_container_w64) {
54849  drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
54850  runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
54851  runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
54852  runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
54853  } else if (pFormat->container == drwav_container_rf64) {
54854  runningPos += drwav__write(pWav, "RF64", 4);
54855  runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
54856  runningPos += drwav__write(pWav, "WAVE", 4);
54857  }
54858  if (pFormat->container == drwav_container_rf64) {
54859  drwav_uint32 initialds64ChunkSize = 28;
54860  drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;
54861  runningPos += drwav__write(pWav, "ds64", 4);
54862  runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);
54863  runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);
54864  runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);
54865  runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);
54866  runningPos += drwav__write_u32ne_to_le(pWav, 0);
54867  }
54868  if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
54869  chunkSizeFMT = 16;
54870  runningPos += drwav__write(pWav, "fmt ", 4);
54871  runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
54872  } else if (pFormat->container == drwav_container_w64) {
54873  chunkSizeFMT = 40;
54874  runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
54875  runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
54876  }
54877  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
54878  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
54879  runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
54880  runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
54881  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
54882  runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
54883  if (!pWav->isSequentialWrite && pWav->pMetadata != NULL && pWav->metadataCount > 0 && (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64)) {
54884  runningPos += drwav__write_or_count_metadata(pWav, pWav->pMetadata, pWav->metadataCount);
54885  }
54886  pWav->dataChunkDataPos = runningPos;
54887  if (pFormat->container == drwav_container_riff) {
54888  drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
54889  runningPos += drwav__write(pWav, "data", 4);
54890  runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
54891  } else if (pFormat->container == drwav_container_w64) {
54892  drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
54893  runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
54894  runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
54895  } else if (pFormat->container == drwav_container_rf64) {
54896  runningPos += drwav__write(pWav, "data", 4);
54897  runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
54898  }
54899  pWav->container = pFormat->container;
54900  pWav->channels = (drwav_uint16)pFormat->channels;
54901  pWav->sampleRate = pFormat->sampleRate;
54902  pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
54903  pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
54904  pWav->dataChunkDataPos = runningPos;
54905  return DRWAV_TRUE;
54906 }
54907 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)
54908 {
54909  if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
54910  return DRWAV_FALSE;
54911  }
54912  return drwav_init_write__internal(pWav, pFormat, 0);
54913 }
54914 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)
54915 {
54916  if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
54917  return DRWAV_FALSE;
54918  }
54919  return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
54920 }
54921 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)
54922 {
54923  if (pFormat == NULL) {
54924  return DRWAV_FALSE;
54925  }
54926  return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
54927 }
54928 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)
54929 {
54930  if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
54931  return DRWAV_FALSE;
54932  }
54933  pWav->pMetadata = pMetadata;
54934  pWav->metadataCount = metadataCount;
54935  return drwav_init_write__internal(pWav, pFormat, 0);
54936 }
54937 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
54938 {
54939  drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalFrameCount * pFormat->channels * pFormat->bitsPerSample/8.0);
54940  drwav_uint64 riffChunkSizeBytes;
54941  drwav_uint64 fileSizeBytes = 0;
54942  if (pFormat->container == drwav_container_riff) {
54943  riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes, pMetadata, metadataCount);
54944  fileSizeBytes = (8 + riffChunkSizeBytes);
54945  } else if (pFormat->container == drwav_container_w64) {
54946  riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
54947  fileSizeBytes = riffChunkSizeBytes;
54948  } else if (pFormat->container == drwav_container_rf64) {
54949  riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes, pMetadata, metadataCount);
54950  fileSizeBytes = (8 + riffChunkSizeBytes);
54951  }
54952  return fileSizeBytes;
54953 }
54954 #ifndef DR_WAV_NO_STDIO
54955 #include <errno.h>
54957 {
54958  switch (e)
54959  {
54960  case 0: return DRWAV_SUCCESS;
54961  #ifdef EPERM
54962  case EPERM: return DRWAV_INVALID_OPERATION;
54963  #endif
54964  #ifdef ENOENT
54965  case ENOENT: return DRWAV_DOES_NOT_EXIST;
54966  #endif
54967  #ifdef ESRCH
54968  case ESRCH: return DRWAV_DOES_NOT_EXIST;
54969  #endif
54970  #ifdef EINTR
54971  case EINTR: return DRWAV_INTERRUPT;
54972  #endif
54973  #ifdef EIO
54974  case EIO: return DRWAV_IO_ERROR;
54975  #endif
54976  #ifdef ENXIO
54977  case ENXIO: return DRWAV_DOES_NOT_EXIST;
54978  #endif
54979  #ifdef E2BIG
54980  case E2BIG: return DRWAV_INVALID_ARGS;
54981  #endif
54982  #ifdef ENOEXEC
54983  case ENOEXEC: return DRWAV_INVALID_FILE;
54984  #endif
54985  #ifdef EBADF
54986  case EBADF: return DRWAV_INVALID_FILE;
54987  #endif
54988  #ifdef ECHILD
54989  case ECHILD: return DRWAV_ERROR;
54990  #endif
54991  #ifdef EAGAIN
54992  case EAGAIN: return DRWAV_UNAVAILABLE;
54993  #endif
54994  #ifdef ENOMEM
54995  case ENOMEM: return DRWAV_OUT_OF_MEMORY;
54996  #endif
54997  #ifdef EACCES
54998  case EACCES: return DRWAV_ACCESS_DENIED;
54999  #endif
55000  #ifdef EFAULT
55001  case EFAULT: return DRWAV_BAD_ADDRESS;
55002  #endif
55003  #ifdef ENOTBLK
55004  case ENOTBLK: return DRWAV_ERROR;
55005  #endif
55006  #ifdef EBUSY
55007  case EBUSY: return DRWAV_BUSY;
55008  #endif
55009  #ifdef EEXIST
55010  case EEXIST: return DRWAV_ALREADY_EXISTS;
55011  #endif
55012  #ifdef EXDEV
55013  case EXDEV: return DRWAV_ERROR;
55014  #endif
55015  #ifdef ENODEV
55016  case ENODEV: return DRWAV_DOES_NOT_EXIST;
55017  #endif
55018  #ifdef ENOTDIR
55019  case ENOTDIR: return DRWAV_NOT_DIRECTORY;
55020  #endif
55021  #ifdef EISDIR
55022  case EISDIR: return DRWAV_IS_DIRECTORY;
55023  #endif
55024  #ifdef EINVAL
55025  case EINVAL: return DRWAV_INVALID_ARGS;
55026  #endif
55027  #ifdef ENFILE
55028  case ENFILE: return DRWAV_TOO_MANY_OPEN_FILES;
55029  #endif
55030  #ifdef EMFILE
55031  case EMFILE: return DRWAV_TOO_MANY_OPEN_FILES;
55032  #endif
55033  #ifdef ENOTTY
55034  case ENOTTY: return DRWAV_INVALID_OPERATION;
55035  #endif
55036  #ifdef ETXTBSY
55037  case ETXTBSY: return DRWAV_BUSY;
55038  #endif
55039  #ifdef EFBIG
55040  case EFBIG: return DRWAV_TOO_BIG;
55041  #endif
55042  #ifdef ENOSPC
55043  case ENOSPC: return DRWAV_NO_SPACE;
55044  #endif
55045  #ifdef ESPIPE
55046  case ESPIPE: return DRWAV_BAD_SEEK;
55047  #endif
55048  #ifdef EROFS
55049  case EROFS: return DRWAV_ACCESS_DENIED;
55050  #endif
55051  #ifdef EMLINK
55052  case EMLINK: return DRWAV_TOO_MANY_LINKS;
55053  #endif
55054  #ifdef EPIPE
55055  case EPIPE: return DRWAV_BAD_PIPE;
55056  #endif
55057  #ifdef EDOM
55058  case EDOM: return DRWAV_OUT_OF_RANGE;
55059  #endif
55060  #ifdef ERANGE
55061  case ERANGE: return DRWAV_OUT_OF_RANGE;
55062  #endif
55063  #ifdef EDEADLK
55064  case EDEADLK: return DRWAV_DEADLOCK;
55065  #endif
55066  #ifdef ENAMETOOLONG
55067  case ENAMETOOLONG: return DRWAV_PATH_TOO_LONG;
55068  #endif
55069  #ifdef ENOLCK
55070  case ENOLCK: return DRWAV_ERROR;
55071  #endif
55072  #ifdef ENOSYS
55073  case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
55074  #endif
55075  #ifdef ENOTEMPTY
55076  case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
55077  #endif
55078  #ifdef ELOOP
55079  case ELOOP: return DRWAV_TOO_MANY_LINKS;
55080  #endif
55081  #ifdef ENOMSG
55082  case ENOMSG: return DRWAV_NO_MESSAGE;
55083  #endif
55084  #ifdef EIDRM
55085  case EIDRM: return DRWAV_ERROR;
55086  #endif
55087  #ifdef ECHRNG
55088  case ECHRNG: return DRWAV_ERROR;
55089  #endif
55090  #ifdef EL2NSYNC
55091  case EL2NSYNC: return DRWAV_ERROR;
55092  #endif
55093  #ifdef EL3HLT
55094  case EL3HLT: return DRWAV_ERROR;
55095  #endif
55096  #ifdef EL3RST
55097  case EL3RST: return DRWAV_ERROR;
55098  #endif
55099  #ifdef ELNRNG
55100  case ELNRNG: return DRWAV_OUT_OF_RANGE;
55101  #endif
55102  #ifdef EUNATCH
55103  case EUNATCH: return DRWAV_ERROR;
55104  #endif
55105  #ifdef ENOCSI
55106  case ENOCSI: return DRWAV_ERROR;
55107  #endif
55108  #ifdef EL2HLT
55109  case EL2HLT: return DRWAV_ERROR;
55110  #endif
55111  #ifdef EBADE
55112  case EBADE: return DRWAV_ERROR;
55113  #endif
55114  #ifdef EBADR
55115  case EBADR: return DRWAV_ERROR;
55116  #endif
55117  #ifdef EXFULL
55118  case EXFULL: return DRWAV_ERROR;
55119  #endif
55120  #ifdef ENOANO
55121  case ENOANO: return DRWAV_ERROR;
55122  #endif
55123  #ifdef EBADRQC
55124  case EBADRQC: return DRWAV_ERROR;
55125  #endif
55126  #ifdef EBADSLT
55127  case EBADSLT: return DRWAV_ERROR;
55128  #endif
55129  #ifdef EBFONT
55130  case EBFONT: return DRWAV_INVALID_FILE;
55131  #endif
55132  #ifdef ENOSTR
55133  case ENOSTR: return DRWAV_ERROR;
55134  #endif
55135  #ifdef ENODATA
55136  case ENODATA: return DRWAV_NO_DATA_AVAILABLE;
55137  #endif
55138  #ifdef ETIME
55139  case ETIME: return DRWAV_TIMEOUT;
55140  #endif
55141  #ifdef ENOSR
55142  case ENOSR: return DRWAV_NO_DATA_AVAILABLE;
55143  #endif
55144  #ifdef ENONET
55145  case ENONET: return DRWAV_NO_NETWORK;
55146  #endif
55147  #ifdef ENOPKG
55148  case ENOPKG: return DRWAV_ERROR;
55149  #endif
55150  #ifdef EREMOTE
55151  case EREMOTE: return DRWAV_ERROR;
55152  #endif
55153  #ifdef ENOLINK
55154  case ENOLINK: return DRWAV_ERROR;
55155  #endif
55156  #ifdef EADV
55157  case EADV: return DRWAV_ERROR;
55158  #endif
55159  #ifdef ESRMNT
55160  case ESRMNT: return DRWAV_ERROR;
55161  #endif
55162  #ifdef ECOMM
55163  case ECOMM: return DRWAV_ERROR;
55164  #endif
55165  #ifdef EPROTO
55166  case EPROTO: return DRWAV_ERROR;
55167  #endif
55168  #ifdef EMULTIHOP
55169  case EMULTIHOP: return DRWAV_ERROR;
55170  #endif
55171  #ifdef EDOTDOT
55172  case EDOTDOT: return DRWAV_ERROR;
55173  #endif
55174  #ifdef EBADMSG
55175  case EBADMSG: return DRWAV_BAD_MESSAGE;
55176  #endif
55177  #ifdef EOVERFLOW
55178  case EOVERFLOW: return DRWAV_TOO_BIG;
55179  #endif
55180  #ifdef ENOTUNIQ
55181  case ENOTUNIQ: return DRWAV_NOT_UNIQUE;
55182  #endif
55183  #ifdef EBADFD
55184  case EBADFD: return DRWAV_ERROR;
55185  #endif
55186  #ifdef EREMCHG
55187  case EREMCHG: return DRWAV_ERROR;
55188  #endif
55189  #ifdef ELIBACC
55190  case ELIBACC: return DRWAV_ACCESS_DENIED;
55191  #endif
55192  #ifdef ELIBBAD
55193  case ELIBBAD: return DRWAV_INVALID_FILE;
55194  #endif
55195  #ifdef ELIBSCN
55196  case ELIBSCN: return DRWAV_INVALID_FILE;
55197  #endif
55198  #ifdef ELIBMAX
55199  case ELIBMAX: return DRWAV_ERROR;
55200  #endif
55201  #ifdef ELIBEXEC
55202  case ELIBEXEC: return DRWAV_ERROR;
55203  #endif
55204  #ifdef EILSEQ
55205  case EILSEQ: return DRWAV_INVALID_DATA;
55206  #endif
55207  #ifdef ERESTART
55208  case ERESTART: return DRWAV_ERROR;
55209  #endif
55210  #ifdef ESTRPIPE
55211  case ESTRPIPE: return DRWAV_ERROR;
55212  #endif
55213  #ifdef EUSERS
55214  case EUSERS: return DRWAV_ERROR;
55215  #endif
55216  #ifdef ENOTSOCK
55217  case ENOTSOCK: return DRWAV_NOT_SOCKET;
55218  #endif
55219  #ifdef EDESTADDRREQ
55220  case EDESTADDRREQ: return DRWAV_NO_ADDRESS;
55221  #endif
55222  #ifdef EMSGSIZE
55223  case EMSGSIZE: return DRWAV_TOO_BIG;
55224  #endif
55225  #ifdef EPROTOTYPE
55226  case EPROTOTYPE: return DRWAV_BAD_PROTOCOL;
55227  #endif
55228  #ifdef ENOPROTOOPT
55229  case ENOPROTOOPT: return DRWAV_PROTOCOL_UNAVAILABLE;
55230  #endif
55231  #ifdef EPROTONOSUPPORT
55232  case EPROTONOSUPPORT: return DRWAV_PROTOCOL_NOT_SUPPORTED;
55233  #endif
55234  #ifdef ESOCKTNOSUPPORT
55235  case ESOCKTNOSUPPORT: return DRWAV_SOCKET_NOT_SUPPORTED;
55236  #endif
55237  #ifdef EOPNOTSUPP
55238  case EOPNOTSUPP: return DRWAV_INVALID_OPERATION;
55239  #endif
55240  #ifdef EPFNOSUPPORT
55241  case EPFNOSUPPORT: return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
55242  #endif
55243  #ifdef EAFNOSUPPORT
55244  case EAFNOSUPPORT: return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
55245  #endif
55246  #ifdef EADDRINUSE
55247  case EADDRINUSE: return DRWAV_ALREADY_IN_USE;
55248  #endif
55249  #ifdef EADDRNOTAVAIL
55250  case EADDRNOTAVAIL: return DRWAV_ERROR;
55251  #endif
55252  #ifdef ENETDOWN
55253  case ENETDOWN: return DRWAV_NO_NETWORK;
55254  #endif
55255  #ifdef ENETUNREACH
55256  case ENETUNREACH: return DRWAV_NO_NETWORK;
55257  #endif
55258  #ifdef ENETRESET
55259  case ENETRESET: return DRWAV_NO_NETWORK;
55260  #endif
55261  #ifdef ECONNABORTED
55262  case ECONNABORTED: return DRWAV_NO_NETWORK;
55263  #endif
55264  #ifdef ECONNRESET
55265  case ECONNRESET: return DRWAV_CONNECTION_RESET;
55266  #endif
55267  #ifdef ENOBUFS
55268  case ENOBUFS: return DRWAV_NO_SPACE;
55269  #endif
55270  #ifdef EISCONN
55271  case EISCONN: return DRWAV_ALREADY_CONNECTED;
55272  #endif
55273  #ifdef ENOTCONN
55274  case ENOTCONN: return DRWAV_NOT_CONNECTED;
55275  #endif
55276  #ifdef ESHUTDOWN
55277  case ESHUTDOWN: return DRWAV_ERROR;
55278  #endif
55279  #ifdef ETOOMANYREFS
55280  case ETOOMANYREFS: return DRWAV_ERROR;
55281  #endif
55282  #ifdef ETIMEDOUT
55283  case ETIMEDOUT: return DRWAV_TIMEOUT;
55284  #endif
55285  #ifdef ECONNREFUSED
55286  case ECONNREFUSED: return DRWAV_CONNECTION_REFUSED;
55287  #endif
55288  #ifdef EHOSTDOWN
55289  case EHOSTDOWN: return DRWAV_NO_HOST;
55290  #endif
55291  #ifdef EHOSTUNREACH
55292  case EHOSTUNREACH: return DRWAV_NO_HOST;
55293  #endif
55294  #ifdef EALREADY
55295  case EALREADY: return DRWAV_IN_PROGRESS;
55296  #endif
55297  #ifdef EINPROGRESS
55298  case EINPROGRESS: return DRWAV_IN_PROGRESS;
55299  #endif
55300  #ifdef ESTALE
55301  case ESTALE: return DRWAV_INVALID_FILE;
55302  #endif
55303  #ifdef EUCLEAN
55304  case EUCLEAN: return DRWAV_ERROR;
55305  #endif
55306  #ifdef ENOTNAM
55307  case ENOTNAM: return DRWAV_ERROR;
55308  #endif
55309  #ifdef ENAVAIL
55310  case ENAVAIL: return DRWAV_ERROR;
55311  #endif
55312  #ifdef EISNAM
55313  case EISNAM: return DRWAV_ERROR;
55314  #endif
55315  #ifdef EREMOTEIO
55316  case EREMOTEIO: return DRWAV_IO_ERROR;
55317  #endif
55318  #ifdef EDQUOT
55319  case EDQUOT: return DRWAV_NO_SPACE;
55320  #endif
55321  #ifdef ENOMEDIUM
55322  case ENOMEDIUM: return DRWAV_DOES_NOT_EXIST;
55323  #endif
55324  #ifdef EMEDIUMTYPE
55325  case EMEDIUMTYPE: return DRWAV_ERROR;
55326  #endif
55327  #ifdef ECANCELED
55328  case ECANCELED: return DRWAV_CANCELLED;
55329  #endif
55330  #ifdef ENOKEY
55331  case ENOKEY: return DRWAV_ERROR;
55332  #endif
55333  #ifdef EKEYEXPIRED
55334  case EKEYEXPIRED: return DRWAV_ERROR;
55335  #endif
55336  #ifdef EKEYREVOKED
55337  case EKEYREVOKED: return DRWAV_ERROR;
55338  #endif
55339  #ifdef EKEYREJECTED
55340  case EKEYREJECTED: return DRWAV_ERROR;
55341  #endif
55342  #ifdef EOWNERDEAD
55343  case EOWNERDEAD: return DRWAV_ERROR;
55344  #endif
55345  #ifdef ENOTRECOVERABLE
55346  case ENOTRECOVERABLE: return DRWAV_ERROR;
55347  #endif
55348  #ifdef ERFKILL
55349  case ERFKILL: return DRWAV_ERROR;
55350  #endif
55351  #ifdef EHWPOISON
55352  case EHWPOISON: return DRWAV_ERROR;
55353  #endif
55354  default: return DRWAV_ERROR;
55355  }
55356 }
55357 DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
55358 {
55359 #if defined(_MSC_VER) && _MSC_VER >= 1400
55360  errno_t err;
55361 #endif
55362  if (ppFile != NULL) {
55363  *ppFile = NULL;
55364  }
55365  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
55366  return DRWAV_INVALID_ARGS;
55367  }
55368 #if defined(_MSC_VER) && _MSC_VER >= 1400
55369  err = fopen_s(ppFile, pFilePath, pOpenMode);
55370  if (err != 0) {
55371  return drwav_result_from_errno(err);
55372  }
55373 #else
55374 #if defined(_WIN32) || defined(__APPLE__)
55375  *ppFile = fopen(pFilePath, pOpenMode);
55376 #else
55377  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
55378  *ppFile = fopen64(pFilePath, pOpenMode);
55379  #else
55380  *ppFile = fopen(pFilePath, pOpenMode);
55381  #endif
55382 #endif
55383  if (*ppFile == NULL) {
55385  if (result == DRWAV_SUCCESS) {
55386  result = DRWAV_ERROR;
55387  }
55388  return result;
55389  }
55390 #endif
55391  return DRWAV_SUCCESS;
55392 }
55393 #if defined(_WIN32)
55394  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
55395  #define DRWAV_HAS_WFOPEN
55396  #endif
55397 #endif
55398 DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
55399 {
55400  if (ppFile != NULL) {
55401  *ppFile = NULL;
55402  }
55403  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
55404  return DRWAV_INVALID_ARGS;
55405  }
55406 #if defined(DRWAV_HAS_WFOPEN)
55407  {
55408  #if defined(_MSC_VER) && _MSC_VER >= 1400
55409  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
55410  if (err != 0) {
55411  return drwav_result_from_errno(err);
55412  }
55413  #else
55414  *ppFile = _wfopen(pFilePath, pOpenMode);
55415  if (*ppFile == NULL) {
55417  }
55418  #endif
55419  (void)pAllocationCallbacks;
55420  }
55421 #else
55422  {
55423  mbstate_t mbs;
55424  size_t lenMB;
55425  const wchar_t* pFilePathTemp = pFilePath;
55426  char* pFilePathMB = NULL;
55427  char pOpenModeMB[32] = {0};
55428  DRWAV_ZERO_OBJECT(&mbs);
55429  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
55430  if (lenMB == (size_t)-1) {
55432  }
55433  pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
55434  if (pFilePathMB == NULL) {
55435  return DRWAV_OUT_OF_MEMORY;
55436  }
55437  pFilePathTemp = pFilePath;
55438  DRWAV_ZERO_OBJECT(&mbs);
55439  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
55440  {
55441  size_t i = 0;
55442  for (;;) {
55443  if (pOpenMode[i] == 0) {
55444  pOpenModeMB[i] = '\0';
55445  break;
55446  }
55447  pOpenModeMB[i] = (char)pOpenMode[i];
55448  i += 1;
55449  }
55450  }
55451  *ppFile = fopen(pFilePathMB, pOpenModeMB);
55452  drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
55453  }
55454  if (*ppFile == NULL) {
55455  return DRWAV_ERROR;
55456  }
55457 #endif
55458  return DRWAV_SUCCESS;
55459 }
55460 DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
55461 {
55462  return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
55463 }
55464 DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
55465 {
55466  return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
55467 }
55468 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
55469 {
55470  return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
55471 }
55472 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
55473 {
55474  return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
55475 }
55476 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)
55477 {
55478  drwav_bool32 result;
55479  result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
55480  if (result != DRWAV_TRUE) {
55481  fclose(pFile);
55482  return result;
55483  }
55484  pWav->allowedMetadataTypes = allowedMetadataTypes;
55485  result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
55486  if (result != DRWAV_TRUE) {
55487  fclose(pFile);
55488  return result;
55489  }
55490  return DRWAV_TRUE;
55491 }
55492 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)
55493 {
55494  FILE* pFile;
55495  if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
55496  return DRWAV_FALSE;
55497  }
55498  return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
55499 }
55500 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
55501 {
55502  return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
55503 }
55504 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)
55505 {
55506  FILE* pFile;
55507  if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
55508  return DRWAV_FALSE;
55509  }
55510  return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
55511 }
55512 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
55513 {
55514  FILE* pFile;
55515  if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
55516  return DRWAV_FALSE;
55517  }
55518  return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
55519 }
55520 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
55521 {
55522  FILE* pFile;
55523  if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
55524  return DRWAV_FALSE;
55525  }
55526  return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
55527 }
55528 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)
55529 {
55530  drwav_bool32 result;
55531  result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
55532  if (result != DRWAV_TRUE) {
55533  fclose(pFile);
55534  return result;
55535  }
55536  result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
55537  if (result != DRWAV_TRUE) {
55538  fclose(pFile);
55539  return result;
55540  }
55541  return DRWAV_TRUE;
55542 }
55543 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)
55544 {
55545  FILE* pFile;
55546  if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
55547  return DRWAV_FALSE;
55548  }
55549  return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
55550 }
55551 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)
55552 {
55553  FILE* pFile;
55554  if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
55555  return DRWAV_FALSE;
55556  }
55557  return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
55558 }
55559 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
55560 {
55561  return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
55562 }
55563 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)
55564 {
55565  return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
55566 }
55567 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)
55568 {
55569  if (pFormat == NULL) {
55570  return DRWAV_FALSE;
55571  }
55572  return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
55573 }
55574 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)
55575 {
55576  return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
55577 }
55578 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)
55579 {
55580  return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
55581 }
55582 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)
55583 {
55584  if (pFormat == NULL) {
55585  return DRWAV_FALSE;
55586  }
55587  return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
55588 }
55589 #endif
55590 DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
55591 {
55592  drwav* pWav = (drwav*)pUserData;
55593  size_t bytesRemaining;
55594  DRWAV_ASSERT(pWav != NULL);
55596  bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
55597  if (bytesToRead > bytesRemaining) {
55598  bytesToRead = bytesRemaining;
55599  }
55600  if (bytesToRead > 0) {
55601  DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
55602  pWav->memoryStream.currentReadPos += bytesToRead;
55603  }
55604  return bytesToRead;
55605 }
55606 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
55607 {
55608  drwav* pWav = (drwav*)pUserData;
55609  DRWAV_ASSERT(pWav != NULL);
55610  if (origin == drwav_seek_origin_current) {
55611  if (offset > 0) {
55612  if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
55613  return DRWAV_FALSE;
55614  }
55615  } else {
55616  if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
55617  return DRWAV_FALSE;
55618  }
55619  }
55620  pWav->memoryStream.currentReadPos += offset;
55621  } else {
55622  if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
55623  pWav->memoryStream.currentReadPos = offset;
55624  } else {
55625  return DRWAV_FALSE;
55626  }
55627  }
55628  return DRWAV_TRUE;
55629 }
55630 DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
55631 {
55632  drwav* pWav = (drwav*)pUserData;
55633  size_t bytesRemaining;
55634  DRWAV_ASSERT(pWav != NULL);
55636  bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
55637  if (bytesRemaining < bytesToWrite) {
55638  void* pNewData;
55639  size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
55640  if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
55641  newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
55642  }
55644  if (pNewData == NULL) {
55645  return 0;
55646  }
55647  *pWav->memoryStreamWrite.ppData = pNewData;
55648  pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
55649  }
55650  DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
55651  pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
55654  }
55656  return bytesToWrite;
55657 }
55658 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
55659 {
55660  drwav* pWav = (drwav*)pUserData;
55661  DRWAV_ASSERT(pWav != NULL);
55662  if (origin == drwav_seek_origin_current) {
55663  if (offset > 0) {
55664  if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
55665  offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);
55666  }
55667  } else {
55668  if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
55669  offset = -(int)pWav->memoryStreamWrite.currentWritePos;
55670  }
55671  }
55672  pWav->memoryStreamWrite.currentWritePos += offset;
55673  } else {
55674  if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
55675  pWav->memoryStreamWrite.currentWritePos = offset;
55676  } else {
55678  }
55679  }
55680  return DRWAV_TRUE;
55681 }
55682 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
55683 {
55684  return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
55685 }
55686 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)
55687 {
55688  if (data == NULL || dataSize == 0) {
55689  return DRWAV_FALSE;
55690  }
55691  if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
55692  return DRWAV_FALSE;
55693  }
55694  pWav->memoryStream.data = (const drwav_uint8*)data;
55695  pWav->memoryStream.dataSize = dataSize;
55696  pWav->memoryStream.currentReadPos = 0;
55697  return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
55698 }
55699 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)
55700 {
55701  if (data == NULL || dataSize == 0) {
55702  return DRWAV_FALSE;
55703  }
55704  if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
55705  return DRWAV_FALSE;
55706  }
55707  pWav->memoryStream.data = (const drwav_uint8*)data;
55708  pWav->memoryStream.dataSize = dataSize;
55709  pWav->memoryStream.currentReadPos = 0;
55711  return drwav_init__internal(pWav, NULL, NULL, flags);
55712 }
55713 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)
55714 {
55715  if (ppData == NULL || pDataSize == NULL) {
55716  return DRWAV_FALSE;
55717  }
55718  *ppData = NULL;
55719  *pDataSize = 0;
55720  if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
55721  return DRWAV_FALSE;
55722  }
55723  pWav->memoryStreamWrite.ppData = ppData;
55724  pWav->memoryStreamWrite.pDataSize = pDataSize;
55725  pWav->memoryStreamWrite.dataSize = 0;
55726  pWav->memoryStreamWrite.dataCapacity = 0;
55728  return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
55729 }
55730 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)
55731 {
55732  return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
55733 }
55734 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)
55735 {
55736  return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
55737 }
55738 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)
55739 {
55740  if (pFormat == NULL) {
55741  return DRWAV_FALSE;
55742  }
55743  return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
55744 }
55746 {
55747  drwav_result result = DRWAV_SUCCESS;
55748  if (pWav == NULL) {
55749  return DRWAV_INVALID_ARGS;
55750  }
55751  if (pWav->onWrite != NULL) {
55752  drwav_uint32 paddingSize = 0;
55753  if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
55755  } else {
55756  paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
55757  }
55758  if (paddingSize > 0) {
55759  drwav_uint64 paddingData = 0;
55760  drwav__write(pWav, &paddingData, paddingSize);
55761  }
55762  if (pWav->onSeek && !pWav->isSequentialWrite) {
55763  if (pWav->container == drwav_container_riff) {
55764  if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
55766  drwav__write_u32ne_to_le(pWav, riffChunkSize);
55767  }
55768  if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
55770  drwav__write_u32ne_to_le(pWav, dataChunkSize);
55771  }
55772  } else if (pWav->container == drwav_container_w64) {
55773  if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
55775  drwav__write_u64ne_to_le(pWav, riffChunkSize);
55776  }
55777  if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
55779  drwav__write_u64ne_to_le(pWav, dataChunkSize);
55780  }
55781  } else if (pWav->container == drwav_container_rf64) {
55782  int ds64BodyPos = 12 + 8;
55783  if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
55785  drwav__write_u64ne_to_le(pWav, riffChunkSize);
55786  }
55787  if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
55789  drwav__write_u64ne_to_le(pWav, dataChunkSize);
55790  }
55791  }
55792  }
55793  if (pWav->isSequentialWrite) {
55794  if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
55795  result = DRWAV_INVALID_FILE;
55796  }
55797  }
55798  } else {
55799  if (pWav->pMetadata != NULL) {
55801  }
55802  }
55803 #ifndef DR_WAV_NO_STDIO
55804  if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
55805  fclose((FILE*)pWav->pUserData);
55806  }
55807 #endif
55808  return result;
55809 }
55810 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
55811 {
55812  size_t bytesRead;
55813  if (pWav == NULL || bytesToRead == 0) {
55814  return 0;
55815  }
55816  if (bytesToRead > pWav->bytesRemaining) {
55817  bytesToRead = (size_t)pWav->bytesRemaining;
55818  }
55819  if (bytesToRead == 0) {
55820  return 0;
55821  }
55822  if (pBufferOut != NULL) {
55823  bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
55824  } else {
55825  bytesRead = 0;
55826  while (bytesRead < bytesToRead) {
55827  size_t bytesToSeek = (bytesToRead - bytesRead);
55828  if (bytesToSeek > 0x7FFFFFFF) {
55829  bytesToSeek = 0x7FFFFFFF;
55830  }
55831  if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
55832  break;
55833  }
55834  bytesRead += bytesToSeek;
55835  }
55836  while (bytesRead < bytesToRead) {
55837  drwav_uint8 buffer[4096];
55838  size_t bytesSeeked;
55839  size_t bytesToSeek = (bytesToRead - bytesRead);
55840  if (bytesToSeek > sizeof(buffer)) {
55841  bytesToSeek = sizeof(buffer);
55842  }
55843  bytesSeeked = pWav->onRead(pWav->pUserData, buffer, bytesToSeek);
55844  bytesRead += bytesSeeked;
55845  if (bytesSeeked < bytesToSeek) {
55846  break;
55847  }
55848  }
55849  }
55850  pWav->readCursorInPCMFrames += bytesRead / drwav_get_bytes_per_pcm_frame(pWav);
55851  pWav->bytesRemaining -= bytesRead;
55852  return bytesRead;
55853 }
55854 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
55855 {
55856  drwav_uint32 bytesPerFrame;
55857  drwav_uint64 bytesToRead;
55858  if (pWav == NULL || framesToRead == 0) {
55859  return 0;
55860  }
55862  return 0;
55863  }
55864  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
55865  if (bytesPerFrame == 0) {
55866  return 0;
55867  }
55868  bytesToRead = framesToRead * bytesPerFrame;
55869  if (bytesToRead > DRWAV_SIZE_MAX) {
55870  bytesToRead = (DRWAV_SIZE_MAX / bytesPerFrame) * bytesPerFrame;
55871  }
55872  if (bytesToRead == 0) {
55873  return 0;
55874  }
55875  return drwav_read_raw(pWav, (size_t)bytesToRead, pBufferOut) / bytesPerFrame;
55876 }
55877 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
55878 {
55879  drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
55880  if (pBufferOut != NULL) {
55881  drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, drwav_get_bytes_per_pcm_frame(pWav)/pWav->channels, pWav->translatedFormatTag);
55882  }
55883  return framesRead;
55884 }
55885 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
55886 {
55887  if (drwav__is_little_endian()) {
55888  return drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
55889  } else {
55890  return drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
55891  }
55892 }
55894 {
55895  if (pWav->onWrite != NULL) {
55896  return DRWAV_FALSE;
55897  }
55898  if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
55899  return DRWAV_FALSE;
55900  }
55903  DRWAV_ZERO_OBJECT(&pWav->msadpcm);
55904  } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
55905  DRWAV_ZERO_OBJECT(&pWav->ima);
55906  } else {
55908  }
55909  }
55910  pWav->readCursorInPCMFrames = 0;
55911  pWav->bytesRemaining = pWav->dataChunkDataSize;
55912  return DRWAV_TRUE;
55913 }
55915 {
55916  if (pWav == NULL || pWav->onSeek == NULL) {
55917  return DRWAV_FALSE;
55918  }
55919  if (pWav->onWrite != NULL) {
55920  return DRWAV_FALSE;
55921  }
55922  if (pWav->totalPCMFrameCount == 0) {
55923  return DRWAV_TRUE;
55924  }
55925  if (targetFrameIndex >= pWav->totalPCMFrameCount) {
55926  targetFrameIndex = pWav->totalPCMFrameCount - 1;
55927  }
55929  if (targetFrameIndex < pWav->readCursorInPCMFrames) {
55930  if (!drwav_seek_to_first_pcm_frame(pWav)) {
55931  return DRWAV_FALSE;
55932  }
55933  }
55934  if (targetFrameIndex > pWav->readCursorInPCMFrames) {
55935  drwav_uint64 offsetInFrames = targetFrameIndex - pWav->readCursorInPCMFrames;
55936  drwav_int16 devnull[2048];
55937  while (offsetInFrames > 0) {
55938  drwav_uint64 framesRead = 0;
55939  drwav_uint64 framesToRead = offsetInFrames;
55940  if (framesToRead > drwav_countof(devnull)/pWav->channels) {
55941  framesToRead = drwav_countof(devnull)/pWav->channels;
55942  }
55944  framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
55945  } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
55946  framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
55947  } else {
55949  }
55950  if (framesRead != framesToRead) {
55951  return DRWAV_FALSE;
55952  }
55953  offsetInFrames -= framesRead;
55954  }
55955  }
55956  } else {
55957  drwav_uint64 totalSizeInBytes;
55958  drwav_uint64 currentBytePos;
55959  drwav_uint64 targetBytePos;
55960  drwav_uint64 offset;
55961  totalSizeInBytes = pWav->totalPCMFrameCount * drwav_get_bytes_per_pcm_frame(pWav);
55962  DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);
55963  currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
55964  targetBytePos = targetFrameIndex * drwav_get_bytes_per_pcm_frame(pWav);
55965  if (currentBytePos < targetBytePos) {
55966  offset = (targetBytePos - currentBytePos);
55967  } else {
55968  if (!drwav_seek_to_first_pcm_frame(pWav)) {
55969  return DRWAV_FALSE;
55970  }
55971  offset = targetBytePos;
55972  }
55973  while (offset > 0) {
55974  int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
55975  if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
55976  return DRWAV_FALSE;
55977  }
55978  pWav->readCursorInPCMFrames += offset32 / drwav_get_bytes_per_pcm_frame(pWav);
55979  pWav->bytesRemaining -= offset32;
55980  offset -= offset32;
55981  }
55982  }
55983  return DRWAV_TRUE;
55984 }
55986 {
55987  if (pCursor == NULL) {
55988  return DRWAV_INVALID_ARGS;
55989  }
55990  *pCursor = 0;
55991  if (pWav == NULL) {
55992  return DRWAV_INVALID_ARGS;
55993  }
55994  *pCursor = pWav->readCursorInPCMFrames;
55995  return DRWAV_SUCCESS;
55996 }
55998 {
55999  if (pLength == NULL) {
56000  return DRWAV_INVALID_ARGS;
56001  }
56002  *pLength = 0;
56003  if (pWav == NULL) {
56004  return DRWAV_INVALID_ARGS;
56005  }
56006  *pLength = pWav->totalPCMFrameCount;
56007  return DRWAV_SUCCESS;
56008 }
56009 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
56010 {
56011  size_t bytesWritten;
56012  if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
56013  return 0;
56014  }
56015  bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
56016  pWav->dataChunkDataSize += bytesWritten;
56017  return bytesWritten;
56018 }
56019 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
56020 {
56021  drwav_uint64 bytesToWrite;
56022  drwav_uint64 bytesWritten;
56023  const drwav_uint8* pRunningData;
56024  if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
56025  return 0;
56026  }
56027  bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
56028  if (bytesToWrite > DRWAV_SIZE_MAX) {
56029  return 0;
56030  }
56031  bytesWritten = 0;
56032  pRunningData = (const drwav_uint8*)pData;
56033  while (bytesToWrite > 0) {
56034  size_t bytesJustWritten;
56035  drwav_uint64 bytesToWriteThisIteration;
56036  bytesToWriteThisIteration = bytesToWrite;
56037  DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
56038  bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
56039  if (bytesJustWritten == 0) {
56040  break;
56041  }
56042  bytesToWrite -= bytesJustWritten;
56043  bytesWritten += bytesJustWritten;
56044  pRunningData += bytesJustWritten;
56045  }
56046  return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
56047 }
56048 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
56049 {
56050  drwav_uint64 bytesToWrite;
56051  drwav_uint64 bytesWritten;
56052  drwav_uint32 bytesPerSample;
56053  const drwav_uint8* pRunningData;
56054  if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
56055  return 0;
56056  }
56057  bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
56058  if (bytesToWrite > DRWAV_SIZE_MAX) {
56059  return 0;
56060  }
56061  bytesWritten = 0;
56062  pRunningData = (const drwav_uint8*)pData;
56063  bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
56064  while (bytesToWrite > 0) {
56065  drwav_uint8 temp[4096];
56066  drwav_uint32 sampleCount;
56067  size_t bytesJustWritten;
56068  drwav_uint64 bytesToWriteThisIteration;
56069  bytesToWriteThisIteration = bytesToWrite;
56070  DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
56071  sampleCount = sizeof(temp)/bytesPerSample;
56072  if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
56073  bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
56074  }
56075  DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
56076  drwav__bswap_samples(temp, sampleCount, bytesPerSample, pWav->translatedFormatTag);
56077  bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, temp);
56078  if (bytesJustWritten == 0) {
56079  break;
56080  }
56081  bytesToWrite -= bytesJustWritten;
56082  bytesWritten += bytesJustWritten;
56083  pRunningData += bytesJustWritten;
56084  }
56085  return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
56086 }
56087 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
56088 {
56089  if (drwav__is_little_endian()) {
56090  return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
56091  } else {
56092  return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
56093  }
56094 }
56096 {
56097  drwav_uint64 totalFramesRead = 0;
56098  DRWAV_ASSERT(pWav != NULL);
56099  DRWAV_ASSERT(framesToRead > 0);
56100  while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
56101  DRWAV_ASSERT(framesToRead > 0);
56102  if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
56103  if (pWav->channels == 1) {
56104  drwav_uint8 header[7];
56105  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
56106  return totalFramesRead;
56107  }
56108  pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
56109  pWav->msadpcm.predictor[0] = header[0];
56110  pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 1);
56111  pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 3);
56112  pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 5);
56113  pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0];
56114  pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1];
56115  pWav->msadpcm.cachedFrameCount = 2;
56116  } else {
56117  drwav_uint8 header[14];
56118  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
56119  return totalFramesRead;
56120  }
56121  pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
56122  pWav->msadpcm.predictor[0] = header[0];
56123  pWav->msadpcm.predictor[1] = header[1];
56124  pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 2);
56125  pWav->msadpcm.delta[1] = drwav_bytes_to_s16(header + 4);
56126  pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 6);
56127  pWav->msadpcm.prevFrames[1][1] = (drwav_int32)drwav_bytes_to_s16(header + 8);
56128  pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 10);
56129  pWav->msadpcm.prevFrames[1][0] = (drwav_int32)drwav_bytes_to_s16(header + 12);
56130  pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
56131  pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
56132  pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
56133  pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
56134  pWav->msadpcm.cachedFrameCount = 2;
56135  }
56136  }
56137  while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
56138  if (pBufferOut != NULL) {
56139  drwav_uint32 iSample = 0;
56140  for (iSample = 0; iSample < pWav->channels; iSample += 1) {
56141  pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
56142  }
56143  pBufferOut += pWav->channels;
56144  }
56145  framesToRead -= 1;
56146  totalFramesRead += 1;
56147  pWav->readCursorInPCMFrames += 1;
56148  pWav->msadpcm.cachedFrameCount -= 1;
56149  }
56150  if (framesToRead == 0) {
56151  break;
56152  }
56153  if (pWav->msadpcm.cachedFrameCount == 0) {
56154  if (pWav->msadpcm.bytesRemainingInBlock == 0) {
56155  continue;
56156  } else {
56157  static drwav_int32 adaptationTable[] = {
56158  230, 230, 230, 230, 307, 409, 512, 614,
56159  768, 614, 512, 409, 307, 230, 230, 230
56160  };
56161  static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
56162  static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
56163  drwav_uint8 nibbles;
56164  drwav_int32 nibble0;
56165  drwav_int32 nibble1;
56166  if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
56167  return totalFramesRead;
56168  }
56169  pWav->msadpcm.bytesRemainingInBlock -= 1;
56170  nibble0 = ((nibbles & 0xF0) >> 4); if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
56171  nibble1 = ((nibbles & 0x0F) >> 0); if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
56172  if (pWav->channels == 1) {
56173  drwav_int32 newSample0;
56174  drwav_int32 newSample1;
56175  newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
56176  newSample0 += nibble0 * pWav->msadpcm.delta[0];
56177  newSample0 = drwav_clamp(newSample0, -32768, 32767);
56178  pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
56179  if (pWav->msadpcm.delta[0] < 16) {
56180  pWav->msadpcm.delta[0] = 16;
56181  }
56182  pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
56183  pWav->msadpcm.prevFrames[0][1] = newSample0;
56184  newSample1 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
56185  newSample1 += nibble1 * pWav->msadpcm.delta[0];
56186  newSample1 = drwav_clamp(newSample1, -32768, 32767);
56187  pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
56188  if (pWav->msadpcm.delta[0] < 16) {
56189  pWav->msadpcm.delta[0] = 16;
56190  }
56191  pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
56192  pWav->msadpcm.prevFrames[0][1] = newSample1;
56193  pWav->msadpcm.cachedFrames[2] = newSample0;
56194  pWav->msadpcm.cachedFrames[3] = newSample1;
56195  pWav->msadpcm.cachedFrameCount = 2;
56196  } else {
56197  drwav_int32 newSample0;
56198  drwav_int32 newSample1;
56199  newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
56200  newSample0 += nibble0 * pWav->msadpcm.delta[0];
56201  newSample0 = drwav_clamp(newSample0, -32768, 32767);
56202  pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
56203  if (pWav->msadpcm.delta[0] < 16) {
56204  pWav->msadpcm.delta[0] = 16;
56205  }
56206  pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
56207  pWav->msadpcm.prevFrames[0][1] = newSample0;
56208  newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
56209  newSample1 += nibble1 * pWav->msadpcm.delta[1];
56210  newSample1 = drwav_clamp(newSample1, -32768, 32767);
56211  pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
56212  if (pWav->msadpcm.delta[1] < 16) {
56213  pWav->msadpcm.delta[1] = 16;
56214  }
56215  pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
56216  pWav->msadpcm.prevFrames[1][1] = newSample1;
56217  pWav->msadpcm.cachedFrames[2] = newSample0;
56218  pWav->msadpcm.cachedFrames[3] = newSample1;
56219  pWav->msadpcm.cachedFrameCount = 1;
56220  }
56221  }
56222  }
56223  }
56224  return totalFramesRead;
56225 }
56227 {
56228  drwav_uint64 totalFramesRead = 0;
56229  drwav_uint32 iChannel;
56230  static drwav_int32 indexTable[16] = {
56231  -1, -1, -1, -1, 2, 4, 6, 8,
56232  -1, -1, -1, -1, 2, 4, 6, 8
56233  };
56234  static drwav_int32 stepTable[89] = {
56235  7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
56236  19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
56237  50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
56238  130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
56239  337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
56240  876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
56241  2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
56242  5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
56243  15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
56244  };
56245  DRWAV_ASSERT(pWav != NULL);
56246  DRWAV_ASSERT(framesToRead > 0);
56247  while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
56248  DRWAV_ASSERT(framesToRead > 0);
56249  if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
56250  if (pWav->channels == 1) {
56251  drwav_uint8 header[4];
56252  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
56253  return totalFramesRead;
56254  }
56255  pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
56256  if (header[2] >= drwav_countof(stepTable)) {
56258  pWav->ima.bytesRemainingInBlock = 0;
56259  return totalFramesRead;
56260  }
56261  pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
56262  pWav->ima.stepIndex[0] = header[2];
56263  pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
56264  pWav->ima.cachedFrameCount = 1;
56265  } else {
56266  drwav_uint8 header[8];
56267  if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
56268  return totalFramesRead;
56269  }
56270  pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
56271  if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
56273  pWav->ima.bytesRemainingInBlock = 0;
56274  return totalFramesRead;
56275  }
56276  pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
56277  pWav->ima.stepIndex[0] = header[2];
56278  pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
56279  pWav->ima.stepIndex[1] = header[6];
56280  pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
56281  pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
56282  pWav->ima.cachedFrameCount = 1;
56283  }
56284  }
56285  while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
56286  if (pBufferOut != NULL) {
56287  drwav_uint32 iSample;
56288  for (iSample = 0; iSample < pWav->channels; iSample += 1) {
56289  pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
56290  }
56291  pBufferOut += pWav->channels;
56292  }
56293  framesToRead -= 1;
56294  totalFramesRead += 1;
56295  pWav->readCursorInPCMFrames += 1;
56296  pWav->ima.cachedFrameCount -= 1;
56297  }
56298  if (framesToRead == 0) {
56299  break;
56300  }
56301  if (pWav->ima.cachedFrameCount == 0) {
56302  if (pWav->ima.bytesRemainingInBlock == 0) {
56303  continue;
56304  } else {
56305  pWav->ima.cachedFrameCount = 8;
56306  for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
56307  drwav_uint32 iByte;
56308  drwav_uint8 nibbles[4];
56309  if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
56310  pWav->ima.cachedFrameCount = 0;
56311  return totalFramesRead;
56312  }
56313  pWav->ima.bytesRemainingInBlock -= 4;
56314  for (iByte = 0; iByte < 4; ++iByte) {
56315  drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
56316  drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
56317  drwav_int32 step = stepTable[pWav->ima.stepIndex[iChannel]];
56318  drwav_int32 predictor = pWav->ima.predictor[iChannel];
56319  drwav_int32 diff = step >> 3;
56320  if (nibble0 & 1) diff += step >> 2;
56321  if (nibble0 & 2) diff += step >> 1;
56322  if (nibble0 & 4) diff += step;
56323  if (nibble0 & 8) diff = -diff;
56324  predictor = drwav_clamp(predictor + diff, -32768, 32767);
56325  pWav->ima.predictor[iChannel] = predictor;
56326  pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
56327  pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
56328  step = stepTable[pWav->ima.stepIndex[iChannel]];
56329  predictor = pWav->ima.predictor[iChannel];
56330  diff = step >> 3;
56331  if (nibble1 & 1) diff += step >> 2;
56332  if (nibble1 & 2) diff += step >> 1;
56333  if (nibble1 & 4) diff += step;
56334  if (nibble1 & 8) diff = -diff;
56335  predictor = drwav_clamp(predictor + diff, -32768, 32767);
56336  pWav->ima.predictor[iChannel] = predictor;
56337  pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
56338  pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
56339  }
56340  }
56341  }
56342  }
56343  }
56344  return totalFramesRead;
56345 }
56346 #ifndef DR_WAV_NO_CONVERSION_API
56347 static unsigned short g_drwavAlawTable[256] = {
56348  0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
56349  0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
56350  0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
56351  0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
56352  0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
56353  0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
56354  0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
56355  0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
56356  0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
56357  0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
56358  0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
56359  0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
56360  0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
56361  0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
56362  0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
56363  0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
56364 };
56365 static unsigned short g_drwavMulawTable[256] = {
56366  0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
56367  0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
56368  0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
56369  0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
56370  0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
56371  0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
56372  0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
56373  0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
56374  0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
56375  0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
56376  0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
56377  0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
56378  0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
56379  0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
56380  0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
56381  0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
56382 };
56384 {
56385  return (short)g_drwavAlawTable[sampleIn];
56386 }
56388 {
56389  return (short)g_drwavMulawTable[sampleIn];
56390 }
56391 DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
56392 {
56393  unsigned int i;
56394  if (bytesPerSample == 1) {
56395  drwav_u8_to_s16(pOut, pIn, totalSampleCount);
56396  return;
56397  }
56398  if (bytesPerSample == 2) {
56399  for (i = 0; i < totalSampleCount; ++i) {
56400  *pOut++ = ((const drwav_int16*)pIn)[i];
56401  }
56402  return;
56403  }
56404  if (bytesPerSample == 3) {
56405  drwav_s24_to_s16(pOut, pIn, totalSampleCount);
56406  return;
56407  }
56408  if (bytesPerSample == 4) {
56409  drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
56410  return;
56411  }
56412  if (bytesPerSample > 8) {
56413  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
56414  return;
56415  }
56416  for (i = 0; i < totalSampleCount; ++i) {
56417  drwav_uint64 sample = 0;
56418  unsigned int shift = (8 - bytesPerSample) * 8;
56419  unsigned int j;
56420  for (j = 0; j < bytesPerSample; j += 1) {
56421  DRWAV_ASSERT(j < 8);
56422  sample |= (drwav_uint64)(pIn[j]) << shift;
56423  shift += 8;
56424  }
56425  pIn += j;
56426  *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
56427  }
56428 }
56429 DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
56430 {
56431  if (bytesPerSample == 4) {
56432  drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
56433  return;
56434  } else if (bytesPerSample == 8) {
56435  drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
56436  return;
56437  } else {
56438  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
56439  return;
56440  }
56441 }
56443 {
56444  drwav_uint64 totalFramesRead;
56445  drwav_uint8 sampleData[4096];
56446  drwav_uint32 bytesPerFrame;
56447  if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
56448  return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
56449  }
56450  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56451  if (bytesPerFrame == 0) {
56452  return 0;
56453  }
56454  totalFramesRead = 0;
56455  while (framesToRead > 0) {
56456  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56457  if (framesRead == 0) {
56458  break;
56459  }
56460  drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
56461  pBufferOut += framesRead*pWav->channels;
56462  framesToRead -= framesRead;
56463  totalFramesRead += framesRead;
56464  }
56465  return totalFramesRead;
56466 }
56468 {
56469  drwav_uint64 totalFramesRead;
56470  drwav_uint8 sampleData[4096];
56471  drwav_uint32 bytesPerFrame;
56472  if (pBufferOut == NULL) {
56473  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
56474  }
56475  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56476  if (bytesPerFrame == 0) {
56477  return 0;
56478  }
56479  totalFramesRead = 0;
56480  while (framesToRead > 0) {
56481  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56482  if (framesRead == 0) {
56483  break;
56484  }
56485  drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
56486  pBufferOut += framesRead*pWav->channels;
56487  framesToRead -= framesRead;
56488  totalFramesRead += framesRead;
56489  }
56490  return totalFramesRead;
56491 }
56493 {
56494  drwav_uint64 totalFramesRead;
56495  drwav_uint8 sampleData[4096];
56496  drwav_uint32 bytesPerFrame;
56497  if (pBufferOut == NULL) {
56498  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
56499  }
56500  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56501  if (bytesPerFrame == 0) {
56502  return 0;
56503  }
56504  totalFramesRead = 0;
56505  while (framesToRead > 0) {
56506  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56507  if (framesRead == 0) {
56508  break;
56509  }
56510  drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
56511  pBufferOut += framesRead*pWav->channels;
56512  framesToRead -= framesRead;
56513  totalFramesRead += framesRead;
56514  }
56515  return totalFramesRead;
56516 }
56518 {
56519  drwav_uint64 totalFramesRead;
56520  drwav_uint8 sampleData[4096];
56521  drwav_uint32 bytesPerFrame;
56522  if (pBufferOut == NULL) {
56523  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
56524  }
56525  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56526  if (bytesPerFrame == 0) {
56527  return 0;
56528  }
56529  totalFramesRead = 0;
56530  while (framesToRead > 0) {
56531  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56532  if (framesRead == 0) {
56533  break;
56534  }
56535  drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
56536  pBufferOut += framesRead*pWav->channels;
56537  framesToRead -= framesRead;
56538  totalFramesRead += framesRead;
56539  }
56540  return totalFramesRead;
56541 }
56543 {
56544  if (pWav == NULL || framesToRead == 0) {
56545  return 0;
56546  }
56547  if (pBufferOut == NULL) {
56548  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
56549  }
56550  if (framesToRead * pWav->channels * sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
56551  framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int16) / pWav->channels;
56552  }
56553  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
56554  return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
56555  }
56557  return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
56558  }
56560  return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
56561  }
56563  return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
56564  }
56566  return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
56567  }
56569  return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
56570  }
56571  return 0;
56572 }
56574 {
56575  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
56576  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
56577  drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
56578  }
56579  return framesRead;
56580 }
56582 {
56583  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
56584  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
56585  drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
56586  }
56587  return framesRead;
56588 }
56589 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
56590 {
56591  int r;
56592  size_t i;
56593  for (i = 0; i < sampleCount; ++i) {
56594  int x = pIn[i];
56595  r = x << 8;
56596  r = r - 32768;
56597  pOut[i] = (short)r;
56598  }
56599 }
56600 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
56601 {
56602  int r;
56603  size_t i;
56604  for (i = 0; i < sampleCount; ++i) {
56605  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;
56606  r = x >> 8;
56607  pOut[i] = (short)r;
56608  }
56609 }
56610 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount)
56611 {
56612  int r;
56613  size_t i;
56614  for (i = 0; i < sampleCount; ++i) {
56615  int x = pIn[i];
56616  r = x >> 16;
56617  pOut[i] = (short)r;
56618  }
56619 }
56620 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount)
56621 {
56622  int r;
56623  size_t i;
56624  for (i = 0; i < sampleCount; ++i) {
56625  float x = pIn[i];
56626  float c;
56627  c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
56628  c = c + 1;
56629  r = (int)(c * 32767.5f);
56630  r = r - 32768;
56631  pOut[i] = (short)r;
56632  }
56633 }
56634 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount)
56635 {
56636  int r;
56637  size_t i;
56638  for (i = 0; i < sampleCount; ++i) {
56639  double x = pIn[i];
56640  double c;
56641  c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
56642  c = c + 1;
56643  r = (int)(c * 32767.5);
56644  r = r - 32768;
56645  pOut[i] = (short)r;
56646  }
56647 }
56648 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
56649 {
56650  size_t i;
56651  for (i = 0; i < sampleCount; ++i) {
56652  pOut[i] = drwav__alaw_to_s16(pIn[i]);
56653  }
56654 }
56655 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
56656 {
56657  size_t i;
56658  for (i = 0; i < sampleCount; ++i) {
56659  pOut[i] = drwav__mulaw_to_s16(pIn[i]);
56660  }
56661 }
56662 DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
56663 {
56664  unsigned int i;
56665  if (bytesPerSample == 1) {
56666  drwav_u8_to_f32(pOut, pIn, sampleCount);
56667  return;
56668  }
56669  if (bytesPerSample == 2) {
56670  drwav_s16_to_f32(pOut, (const drwav_int16*)pIn, sampleCount);
56671  return;
56672  }
56673  if (bytesPerSample == 3) {
56674  drwav_s24_to_f32(pOut, pIn, sampleCount);
56675  return;
56676  }
56677  if (bytesPerSample == 4) {
56678  drwav_s32_to_f32(pOut, (const drwav_int32*)pIn, sampleCount);
56679  return;
56680  }
56681  if (bytesPerSample > 8) {
56682  DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
56683  return;
56684  }
56685  for (i = 0; i < sampleCount; ++i) {
56686  drwav_uint64 sample = 0;
56687  unsigned int shift = (8 - bytesPerSample) * 8;
56688  unsigned int j;
56689  for (j = 0; j < bytesPerSample; j += 1) {
56690  DRWAV_ASSERT(j < 8);
56691  sample |= (drwav_uint64)(pIn[j]) << shift;
56692  shift += 8;
56693  }
56694  pIn += j;
56695  *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
56696  }
56697 }
56698 DRWAV_PRIVATE void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
56699 {
56700  if (bytesPerSample == 4) {
56701  unsigned int i;
56702  for (i = 0; i < sampleCount; ++i) {
56703  *pOut++ = ((const float*)pIn)[i];
56704  }
56705  return;
56706  } else if (bytesPerSample == 8) {
56707  drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
56708  return;
56709  } else {
56710  DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
56711  return;
56712  }
56713 }
56714 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56715 {
56716  drwav_uint64 totalFramesRead;
56717  drwav_uint8 sampleData[4096];
56718  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56719  if (bytesPerFrame == 0) {
56720  return 0;
56721  }
56722  totalFramesRead = 0;
56723  while (framesToRead > 0) {
56724  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56725  if (framesRead == 0) {
56726  break;
56727  }
56728  drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)framesRead*pWav->channels, bytesPerFrame/pWav->channels);
56729  pBufferOut += framesRead*pWav->channels;
56730  framesToRead -= framesRead;
56731  totalFramesRead += framesRead;
56732  }
56733  return totalFramesRead;
56734 }
56735 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56736 {
56737  drwav_uint64 totalFramesRead = 0;
56738  drwav_int16 samples16[2048];
56739  while (framesToRead > 0) {
56740  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
56741  if (framesRead == 0) {
56742  break;
56743  }
56744  drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
56745  pBufferOut += framesRead*pWav->channels;
56746  framesToRead -= framesRead;
56747  totalFramesRead += framesRead;
56748  }
56749  return totalFramesRead;
56750 }
56751 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56752 {
56753  drwav_uint64 totalFramesRead = 0;
56754  drwav_int16 samples16[2048];
56755  while (framesToRead > 0) {
56756  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
56757  if (framesRead == 0) {
56758  break;
56759  }
56760  drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
56761  pBufferOut += framesRead*pWav->channels;
56762  framesToRead -= framesRead;
56763  totalFramesRead += framesRead;
56764  }
56765  return totalFramesRead;
56766 }
56767 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56768 {
56769  drwav_uint64 totalFramesRead;
56770  drwav_uint8 sampleData[4096];
56771  drwav_uint32 bytesPerFrame;
56772  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
56773  return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
56774  }
56775  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56776  if (bytesPerFrame == 0) {
56777  return 0;
56778  }
56779  totalFramesRead = 0;
56780  while (framesToRead > 0) {
56781  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56782  if (framesRead == 0) {
56783  break;
56784  }
56785  drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
56786  pBufferOut += framesRead*pWav->channels;
56787  framesToRead -= framesRead;
56788  totalFramesRead += framesRead;
56789  }
56790  return totalFramesRead;
56791 }
56792 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56793 {
56794  drwav_uint64 totalFramesRead;
56795  drwav_uint8 sampleData[4096];
56796  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56797  if (bytesPerFrame == 0) {
56798  return 0;
56799  }
56800  totalFramesRead = 0;
56801  while (framesToRead > 0) {
56802  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56803  if (framesRead == 0) {
56804  break;
56805  }
56806  drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
56807  pBufferOut += framesRead*pWav->channels;
56808  framesToRead -= framesRead;
56809  totalFramesRead += framesRead;
56810  }
56811  return totalFramesRead;
56812 }
56813 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56814 {
56815  drwav_uint64 totalFramesRead;
56816  drwav_uint8 sampleData[4096];
56817  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
56818  if (bytesPerFrame == 0) {
56819  return 0;
56820  }
56821  totalFramesRead = 0;
56822  while (framesToRead > 0) {
56823  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
56824  if (framesRead == 0) {
56825  break;
56826  }
56827  drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
56828  pBufferOut += framesRead*pWav->channels;
56829  framesToRead -= framesRead;
56830  totalFramesRead += framesRead;
56831  }
56832  return totalFramesRead;
56833 }
56834 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56835 {
56836  if (pWav == NULL || framesToRead == 0) {
56837  return 0;
56838  }
56839  if (pBufferOut == NULL) {
56840  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
56841  }
56842  if (framesToRead * pWav->channels * sizeof(float) > DRWAV_SIZE_MAX) {
56843  framesToRead = DRWAV_SIZE_MAX / sizeof(float) / pWav->channels;
56844  }
56845  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
56846  return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
56847  }
56849  return drwav_read_pcm_frames_f32__msadpcm(pWav, framesToRead, pBufferOut);
56850  }
56852  return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
56853  }
56855  return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
56856  }
56858  return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
56859  }
56861  return drwav_read_pcm_frames_f32__ima(pWav, framesToRead, pBufferOut);
56862  }
56863  return 0;
56864 }
56865 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56866 {
56867  drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
56868  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
56869  drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
56870  }
56871  return framesRead;
56872 }
56873 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
56874 {
56875  drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
56876  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
56877  drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
56878  }
56879  return framesRead;
56880 }
56881 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
56882 {
56883  size_t i;
56884  if (pOut == NULL || pIn == NULL) {
56885  return;
56886  }
56887 #ifdef DR_WAV_LIBSNDFILE_COMPAT
56888  for (i = 0; i < sampleCount; ++i) {
56889  *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
56890  }
56891 #else
56892  for (i = 0; i < sampleCount; ++i) {
56893  float x = pIn[i];
56894  x = x * 0.00784313725490196078f;
56895  x = x - 1;
56896  *pOut++ = x;
56897  }
56898 #endif
56899 }
56900 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount)
56901 {
56902  size_t i;
56903  if (pOut == NULL || pIn == NULL) {
56904  return;
56905  }
56906  for (i = 0; i < sampleCount; ++i) {
56907  *pOut++ = pIn[i] * 0.000030517578125f;
56908  }
56909 }
56910 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
56911 {
56912  size_t i;
56913  if (pOut == NULL || pIn == NULL) {
56914  return;
56915  }
56916  for (i = 0; i < sampleCount; ++i) {
56917  double x;
56918  drwav_uint32 a = ((drwav_uint32)(pIn[i*3+0]) << 8);
56919  drwav_uint32 b = ((drwav_uint32)(pIn[i*3+1]) << 16);
56920  drwav_uint32 c = ((drwav_uint32)(pIn[i*3+2]) << 24);
56921  x = (double)((drwav_int32)(a | b | c) >> 8);
56922  *pOut++ = (float)(x * 0.00000011920928955078125);
56923  }
56924 }
56925 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount)
56926 {
56927  size_t i;
56928  if (pOut == NULL || pIn == NULL) {
56929  return;
56930  }
56931  for (i = 0; i < sampleCount; ++i) {
56932  *pOut++ = (float)(pIn[i] / 2147483648.0);
56933  }
56934 }
56935 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount)
56936 {
56937  size_t i;
56938  if (pOut == NULL || pIn == NULL) {
56939  return;
56940  }
56941  for (i = 0; i < sampleCount; ++i) {
56942  *pOut++ = (float)pIn[i];
56943  }
56944 }
56945 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
56946 {
56947  size_t i;
56948  if (pOut == NULL || pIn == NULL) {
56949  return;
56950  }
56951  for (i = 0; i < sampleCount; ++i) {
56952  *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
56953  }
56954 }
56955 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
56956 {
56957  size_t i;
56958  if (pOut == NULL || pIn == NULL) {
56959  return;
56960  }
56961  for (i = 0; i < sampleCount; ++i) {
56962  *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
56963  }
56964 }
56965 DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
56966 {
56967  unsigned int i;
56968  if (bytesPerSample == 1) {
56969  drwav_u8_to_s32(pOut, pIn, totalSampleCount);
56970  return;
56971  }
56972  if (bytesPerSample == 2) {
56973  drwav_s16_to_s32(pOut, (const drwav_int16*)pIn, totalSampleCount);
56974  return;
56975  }
56976  if (bytesPerSample == 3) {
56977  drwav_s24_to_s32(pOut, pIn, totalSampleCount);
56978  return;
56979  }
56980  if (bytesPerSample == 4) {
56981  for (i = 0; i < totalSampleCount; ++i) {
56982  *pOut++ = ((const drwav_int32*)pIn)[i];
56983  }
56984  return;
56985  }
56986  if (bytesPerSample > 8) {
56987  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
56988  return;
56989  }
56990  for (i = 0; i < totalSampleCount; ++i) {
56991  drwav_uint64 sample = 0;
56992  unsigned int shift = (8 - bytesPerSample) * 8;
56993  unsigned int j;
56994  for (j = 0; j < bytesPerSample; j += 1) {
56995  DRWAV_ASSERT(j < 8);
56996  sample |= (drwav_uint64)(pIn[j]) << shift;
56997  shift += 8;
56998  }
56999  pIn += j;
57000  *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
57001  }
57002 }
57003 DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
57004 {
57005  if (bytesPerSample == 4) {
57006  drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
57007  return;
57008  } else if (bytesPerSample == 8) {
57009  drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
57010  return;
57011  } else {
57012  DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
57013  return;
57014  }
57015 }
57017 {
57018  drwav_uint64 totalFramesRead;
57019  drwav_uint8 sampleData[4096];
57020  drwav_uint32 bytesPerFrame;
57021  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
57022  return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
57023  }
57024  bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
57025  if (bytesPerFrame == 0) {
57026  return 0;
57027  }
57028  totalFramesRead = 0;
57029  while (framesToRead > 0) {
57030  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
57031  if (framesRead == 0) {
57032  break;
57033  }
57034  drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
57035  pBufferOut += framesRead*pWav->channels;
57036  framesToRead -= framesRead;
57037  totalFramesRead += framesRead;
57038  }
57039  return totalFramesRead;
57040 }
57042 {
57043  drwav_uint64 totalFramesRead = 0;
57044  drwav_int16 samples16[2048];
57045  while (framesToRead > 0) {
57046  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
57047  if (framesRead == 0) {
57048  break;
57049  }
57050  drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
57051  pBufferOut += framesRead*pWav->channels;
57052  framesToRead -= framesRead;
57053  totalFramesRead += framesRead;
57054  }
57055  return totalFramesRead;
57056 }
57058 {
57059  drwav_uint64 totalFramesRead = 0;
57060  drwav_int16 samples16[2048];
57061  while (framesToRead > 0) {
57062  drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
57063  if (framesRead == 0) {
57064  break;
57065  }
57066  drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));
57067  pBufferOut += framesRead*pWav->channels;
57068  framesToRead -= framesRead;
57069  totalFramesRead += framesRead;
57070  }
57071  return totalFramesRead;
57072 }
57074 {
57075  drwav_uint64 totalFramesRead;
57076  drwav_uint8 sampleData[4096];
57077  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
57078  if (bytesPerFrame == 0) {
57079  return 0;
57080  }
57081  totalFramesRead = 0;
57082  while (framesToRead > 0) {
57083  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
57084  if (framesRead == 0) {
57085  break;
57086  }
57087  drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
57088  pBufferOut += framesRead*pWav->channels;
57089  framesToRead -= framesRead;
57090  totalFramesRead += framesRead;
57091  }
57092  return totalFramesRead;
57093 }
57095 {
57096  drwav_uint64 totalFramesRead;
57097  drwav_uint8 sampleData[4096];
57098  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
57099  if (bytesPerFrame == 0) {
57100  return 0;
57101  }
57102  totalFramesRead = 0;
57103  while (framesToRead > 0) {
57104  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
57105  if (framesRead == 0) {
57106  break;
57107  }
57108  drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
57109  pBufferOut += framesRead*pWav->channels;
57110  framesToRead -= framesRead;
57111  totalFramesRead += framesRead;
57112  }
57113  return totalFramesRead;
57114 }
57116 {
57117  drwav_uint64 totalFramesRead;
57118  drwav_uint8 sampleData[4096];
57119  drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
57120  if (bytesPerFrame == 0) {
57121  return 0;
57122  }
57123  totalFramesRead = 0;
57124  while (framesToRead > 0) {
57125  drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
57126  if (framesRead == 0) {
57127  break;
57128  }
57129  drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
57130  pBufferOut += framesRead*pWav->channels;
57131  framesToRead -= framesRead;
57132  totalFramesRead += framesRead;
57133  }
57134  return totalFramesRead;
57135 }
57137 {
57138  if (pWav == NULL || framesToRead == 0) {
57139  return 0;
57140  }
57141  if (pBufferOut == NULL) {
57142  return drwav_read_pcm_frames(pWav, framesToRead, NULL);
57143  }
57144  if (framesToRead * pWav->channels * sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
57145  framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int32) / pWav->channels;
57146  }
57147  if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
57148  return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
57149  }
57151  return drwav_read_pcm_frames_s32__msadpcm(pWav, framesToRead, pBufferOut);
57152  }
57154  return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
57155  }
57157  return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
57158  }
57160  return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
57161  }
57163  return drwav_read_pcm_frames_s32__ima(pWav, framesToRead, pBufferOut);
57164  }
57165  return 0;
57166 }
57168 {
57169  drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
57170  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
57171  drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
57172  }
57173  return framesRead;
57174 }
57176 {
57177  drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
57178  if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
57179  drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
57180  }
57181  return framesRead;
57182 }
57183 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
57184 {
57185  size_t i;
57186  if (pOut == NULL || pIn == NULL) {
57187  return;
57188  }
57189  for (i = 0; i < sampleCount; ++i) {
57190  *pOut++ = ((int)pIn[i] - 128) << 24;
57191  }
57192 }
57193 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount)
57194 {
57195  size_t i;
57196  if (pOut == NULL || pIn == NULL) {
57197  return;
57198  }
57199  for (i = 0; i < sampleCount; ++i) {
57200  *pOut++ = pIn[i] << 16;
57201  }
57202 }
57203 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
57204 {
57205  size_t i;
57206  if (pOut == NULL || pIn == NULL) {
57207  return;
57208  }
57209  for (i = 0; i < sampleCount; ++i) {
57210  unsigned int s0 = pIn[i*3 + 0];
57211  unsigned int s1 = pIn[i*3 + 1];
57212  unsigned int s2 = pIn[i*3 + 2];
57213  drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
57214  *pOut++ = sample32;
57215  }
57216 }
57217 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
57218 {
57219  size_t i;
57220  if (pOut == NULL || pIn == NULL) {
57221  return;
57222  }
57223  for (i = 0; i < sampleCount; ++i) {
57224  *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
57225  }
57226 }
57227 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
57228 {
57229  size_t i;
57230  if (pOut == NULL || pIn == NULL) {
57231  return;
57232  }
57233  for (i = 0; i < sampleCount; ++i) {
57234  *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
57235  }
57236 }
57237 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
57238 {
57239  size_t i;
57240  if (pOut == NULL || pIn == NULL) {
57241  return;
57242  }
57243  for (i = 0; i < sampleCount; ++i) {
57244  *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
57245  }
57246 }
57247 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
57248 {
57249  size_t i;
57250  if (pOut == NULL || pIn == NULL) {
57251  return;
57252  }
57253  for (i= 0; i < sampleCount; ++i) {
57254  *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
57255  }
57256 }
57257 DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
57258 {
57259  drwav_uint64 sampleDataSize;
57260  drwav_int16* pSampleData;
57261  drwav_uint64 framesRead;
57262  DRWAV_ASSERT(pWav != NULL);
57263  sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
57264  if (sampleDataSize > DRWAV_SIZE_MAX) {
57265  drwav_uninit(pWav);
57266  return NULL;
57267  }
57268  pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
57269  if (pSampleData == NULL) {
57270  drwav_uninit(pWav);
57271  return NULL;
57272  }
57273  framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
57274  if (framesRead != pWav->totalPCMFrameCount) {
57275  drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
57276  drwav_uninit(pWav);
57277  return NULL;
57278  }
57279  drwav_uninit(pWav);
57280  if (sampleRate) {
57281  *sampleRate = pWav->sampleRate;
57282  }
57283  if (channels) {
57284  *channels = pWav->channels;
57285  }
57286  if (totalFrameCount) {
57287  *totalFrameCount = pWav->totalPCMFrameCount;
57288  }
57289  return pSampleData;
57290 }
57291 DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
57292 {
57293  drwav_uint64 sampleDataSize;
57294  float* pSampleData;
57295  drwav_uint64 framesRead;
57296  DRWAV_ASSERT(pWav != NULL);
57297  sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
57298  if (sampleDataSize > DRWAV_SIZE_MAX) {
57299  drwav_uninit(pWav);
57300  return NULL;
57301  }
57302  pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
57303  if (pSampleData == NULL) {
57304  drwav_uninit(pWav);
57305  return NULL;
57306  }
57307  framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
57308  if (framesRead != pWav->totalPCMFrameCount) {
57309  drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
57310  drwav_uninit(pWav);
57311  return NULL;
57312  }
57313  drwav_uninit(pWav);
57314  if (sampleRate) {
57315  *sampleRate = pWav->sampleRate;
57316  }
57317  if (channels) {
57318  *channels = pWav->channels;
57319  }
57320  if (totalFrameCount) {
57321  *totalFrameCount = pWav->totalPCMFrameCount;
57322  }
57323  return pSampleData;
57324 }
57325 DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
57326 {
57327  drwav_uint64 sampleDataSize;
57328  drwav_int32* pSampleData;
57329  drwav_uint64 framesRead;
57330  DRWAV_ASSERT(pWav != NULL);
57331  sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
57332  if (sampleDataSize > DRWAV_SIZE_MAX) {
57333  drwav_uninit(pWav);
57334  return NULL;
57335  }
57336  pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
57337  if (pSampleData == NULL) {
57338  drwav_uninit(pWav);
57339  return NULL;
57340  }
57341  framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
57342  if (framesRead != pWav->totalPCMFrameCount) {
57343  drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
57344  drwav_uninit(pWav);
57345  return NULL;
57346  }
57347  drwav_uninit(pWav);
57348  if (sampleRate) {
57349  *sampleRate = pWav->sampleRate;
57350  }
57351  if (channels) {
57352  *channels = pWav->channels;
57353  }
57354  if (totalFrameCount) {
57355  *totalFrameCount = pWav->totalPCMFrameCount;
57356  }
57357  return pSampleData;
57358 }
57359 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)
57360 {
57361  drwav wav;
57362  if (channelsOut) {
57363  *channelsOut = 0;
57364  }
57365  if (sampleRateOut) {
57366  *sampleRateOut = 0;
57367  }
57368  if (totalFrameCountOut) {
57369  *totalFrameCountOut = 0;
57370  }
57371  if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
57372  return NULL;
57373  }
57374  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57375 }
57376 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)
57377 {
57378  drwav wav;
57379  if (channelsOut) {
57380  *channelsOut = 0;
57381  }
57382  if (sampleRateOut) {
57383  *sampleRateOut = 0;
57384  }
57385  if (totalFrameCountOut) {
57386  *totalFrameCountOut = 0;
57387  }
57388  if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
57389  return NULL;
57390  }
57391  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57392 }
57393 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)
57394 {
57395  drwav wav;
57396  if (channelsOut) {
57397  *channelsOut = 0;
57398  }
57399  if (sampleRateOut) {
57400  *sampleRateOut = 0;
57401  }
57402  if (totalFrameCountOut) {
57403  *totalFrameCountOut = 0;
57404  }
57405  if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
57406  return NULL;
57407  }
57408  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57409 }
57410 #ifndef DR_WAV_NO_STDIO
57411 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)
57412 {
57413  drwav wav;
57414  if (channelsOut) {
57415  *channelsOut = 0;
57416  }
57417  if (sampleRateOut) {
57418  *sampleRateOut = 0;
57419  }
57420  if (totalFrameCountOut) {
57421  *totalFrameCountOut = 0;
57422  }
57423  if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
57424  return NULL;
57425  }
57426  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57427 }
57428 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)
57429 {
57430  drwav wav;
57431  if (channelsOut) {
57432  *channelsOut = 0;
57433  }
57434  if (sampleRateOut) {
57435  *sampleRateOut = 0;
57436  }
57437  if (totalFrameCountOut) {
57438  *totalFrameCountOut = 0;
57439  }
57440  if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
57441  return NULL;
57442  }
57443  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57444 }
57445 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)
57446 {
57447  drwav wav;
57448  if (channelsOut) {
57449  *channelsOut = 0;
57450  }
57451  if (sampleRateOut) {
57452  *sampleRateOut = 0;
57453  }
57454  if (totalFrameCountOut) {
57455  *totalFrameCountOut = 0;
57456  }
57457  if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
57458  return NULL;
57459  }
57460  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57461 }
57462 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)
57463 {
57464  drwav wav;
57465  if (sampleRateOut) {
57466  *sampleRateOut = 0;
57467  }
57468  if (channelsOut) {
57469  *channelsOut = 0;
57470  }
57471  if (totalFrameCountOut) {
57472  *totalFrameCountOut = 0;
57473  }
57474  if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
57475  return NULL;
57476  }
57477  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57478 }
57479 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)
57480 {
57481  drwav wav;
57482  if (sampleRateOut) {
57483  *sampleRateOut = 0;
57484  }
57485  if (channelsOut) {
57486  *channelsOut = 0;
57487  }
57488  if (totalFrameCountOut) {
57489  *totalFrameCountOut = 0;
57490  }
57491  if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
57492  return NULL;
57493  }
57494  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57495 }
57496 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)
57497 {
57498  drwav wav;
57499  if (sampleRateOut) {
57500  *sampleRateOut = 0;
57501  }
57502  if (channelsOut) {
57503  *channelsOut = 0;
57504  }
57505  if (totalFrameCountOut) {
57506  *totalFrameCountOut = 0;
57507  }
57508  if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
57509  return NULL;
57510  }
57511  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57512 }
57513 #endif
57514 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)
57515 {
57516  drwav wav;
57517  if (channelsOut) {
57518  *channelsOut = 0;
57519  }
57520  if (sampleRateOut) {
57521  *sampleRateOut = 0;
57522  }
57523  if (totalFrameCountOut) {
57524  *totalFrameCountOut = 0;
57525  }
57526  if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
57527  return NULL;
57528  }
57529  return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57530 }
57531 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)
57532 {
57533  drwav wav;
57534  if (channelsOut) {
57535  *channelsOut = 0;
57536  }
57537  if (sampleRateOut) {
57538  *sampleRateOut = 0;
57539  }
57540  if (totalFrameCountOut) {
57541  *totalFrameCountOut = 0;
57542  }
57543  if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
57544  return NULL;
57545  }
57546  return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57547 }
57548 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)
57549 {
57550  drwav wav;
57551  if (channelsOut) {
57552  *channelsOut = 0;
57553  }
57554  if (sampleRateOut) {
57555  *sampleRateOut = 0;
57556  }
57557  if (totalFrameCountOut) {
57558  *totalFrameCountOut = 0;
57559  }
57560  if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
57561  return NULL;
57562  }
57563  return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
57564 }
57565 #endif
57566 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
57567 {
57568  if (pAllocationCallbacks != NULL) {
57569  drwav__free_from_callbacks(p, pAllocationCallbacks);
57570  } else {
57572  }
57573 }
57575 {
57576  return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
57577 }
57579 {
57580  return (drwav_int16)drwav_bytes_to_u16(data);
57581 }
57583 {
57584  return ((drwav_uint32)data[0] << 0) | ((drwav_uint32)data[1] << 8) | ((drwav_uint32)data[2] << 16) | ((drwav_uint32)data[3] << 24);
57585 }
57586 DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data)
57587 {
57588  union {
57589  drwav_uint32 u32;
57590  float f32;
57591  } value;
57592  value.u32 = drwav_bytes_to_u32(data);
57593  return value.f32;
57594 }
57596 {
57597  return (drwav_int32)drwav_bytes_to_u32(data);
57598 }
57600 {
57601  return
57602  ((drwav_uint64)data[0] << 0) | ((drwav_uint64)data[1] << 8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
57603  ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
57604 }
57606 {
57607  return (drwav_int64)drwav_bytes_to_u64(data);
57608 }
57610 {
57611  int i;
57612  for (i = 0; i < 16; i += 1) {
57613  if (a[i] != b[i]) {
57614  return DRWAV_FALSE;
57615  }
57616  }
57617  return DRWAV_TRUE;
57618 }
57619 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
57620 {
57621  return
57622  a[0] == b[0] &&
57623  a[1] == b[1] &&
57624  a[2] == b[2] &&
57625  a[3] == b[3];
57626 }
57627 #endif
57628 /* dr_wav_c end */
57629 #endif /* DRWAV_IMPLEMENTATION */
57630 #endif /* MA_NO_WAV */
57631 
57632 #if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING)
57633 #if !defined(DR_FLAC_IMPLEMENTATION) && !defined(DRFLAC_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
57634 /* dr_flac_c begin */
57635 #ifndef dr_flac_c
57636 #define dr_flac_c
57637 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
57638  #pragma GCC diagnostic push
57639  #if __GNUC__ >= 7
57640  #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
57641  #endif
57642 #endif
57643 #ifdef __linux__
57644  #ifndef _BSD_SOURCE
57645  #define _BSD_SOURCE
57646  #endif
57647  #ifndef _DEFAULT_SOURCE
57648  #define _DEFAULT_SOURCE
57649  #endif
57650  #ifndef __USE_BSD
57651  #define __USE_BSD
57652  #endif
57653  #include <endian.h>
57654 #endif
57655 #include <stdlib.h>
57656 #include <string.h>
57657 #ifdef _MSC_VER
57658  #define DRFLAC_INLINE __forceinline
57659 #elif defined(__GNUC__)
57660  #if defined(__STRICT_ANSI__)
57661  #define DRFLAC_INLINE __inline__ __attribute__((always_inline))
57662  #else
57663  #define DRFLAC_INLINE inline __attribute__((always_inline))
57664  #endif
57665 #elif defined(__WATCOMC__)
57666  #define DRFLAC_INLINE __inline
57667 #else
57668  #define DRFLAC_INLINE
57669 #endif
57670 #if defined(__x86_64__) || defined(_M_X64)
57671  #define DRFLAC_X64
57672 #elif defined(__i386) || defined(_M_IX86)
57673  #define DRFLAC_X86
57674 #elif defined(__arm__) || defined(_M_ARM) || defined(_M_ARM64)
57675  #define DRFLAC_ARM
57676 #endif
57677 #if !defined(DR_FLAC_NO_SIMD)
57678  #if defined(DRFLAC_X64) || defined(DRFLAC_X86)
57679  #if defined(_MSC_VER) && !defined(__clang__)
57680  #if _MSC_VER >= 1400 && !defined(DRFLAC_NO_SSE2)
57681  #define DRFLAC_SUPPORT_SSE2
57682  #endif
57683  #if _MSC_VER >= 1600 && !defined(DRFLAC_NO_SSE41)
57684  #define DRFLAC_SUPPORT_SSE41
57685  #endif
57686  #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
57687  #if defined(__SSE2__) && !defined(DRFLAC_NO_SSE2)
57688  #define DRFLAC_SUPPORT_SSE2
57689  #endif
57690  #if defined(__SSE4_1__) && !defined(DRFLAC_NO_SSE41)
57691  #define DRFLAC_SUPPORT_SSE41
57692  #endif
57693  #endif
57694  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
57695  #if !defined(DRFLAC_SUPPORT_SSE2) && !defined(DRFLAC_NO_SSE2) && __has_include(<emmintrin.h>)
57696  #define DRFLAC_SUPPORT_SSE2
57697  #endif
57698  #if !defined(DRFLAC_SUPPORT_SSE41) && !defined(DRFLAC_NO_SSE41) && __has_include(<smmintrin.h>)
57699  #define DRFLAC_SUPPORT_SSE41
57700  #endif
57701  #endif
57702  #if defined(DRFLAC_SUPPORT_SSE41)
57703  #include <smmintrin.h>
57704  #elif defined(DRFLAC_SUPPORT_SSE2)
57705  #include <emmintrin.h>
57706  #endif
57707  #endif
57708  #if defined(DRFLAC_ARM)
57709  #if !defined(DRFLAC_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
57710  #define DRFLAC_SUPPORT_NEON
57711  #endif
57712  #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
57713  #if !defined(DRFLAC_SUPPORT_NEON) && !defined(DRFLAC_NO_NEON) && __has_include(<arm_neon.h>)
57714  #define DRFLAC_SUPPORT_NEON
57715  #endif
57716  #endif
57717  #if defined(DRFLAC_SUPPORT_NEON)
57718  #include <arm_neon.h>
57719  #endif
57720  #endif
57721 #endif
57722 #if !defined(DR_FLAC_NO_SIMD) && (defined(DRFLAC_X86) || defined(DRFLAC_X64))
57723  #if defined(_MSC_VER) && !defined(__clang__)
57724  #if _MSC_VER >= 1400
57725  #include <intrin.h>
57726  static void drflac__cpuid(int info[4], int fid)
57727  {
57728  __cpuid(info, fid);
57729  }
57730  #else
57731  #define DRFLAC_NO_CPUID
57732  #endif
57733  #else
57734  #if defined(__GNUC__) || defined(__clang__)
57735  static void drflac__cpuid(int info[4], int fid)
57736  {
57737  #if defined(DRFLAC_X86) && defined(__PIC__)
57738  __asm__ __volatile__ (
57739  "xchg{l} {%%}ebx, %k1;"
57740  "cpuid;"
57741  "xchg{l} {%%}ebx, %k1;"
57742  : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
57743  );
57744  #else
57745  __asm__ __volatile__ (
57746  "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
57747  );
57748  #endif
57749  }
57750  #else
57751  #define DRFLAC_NO_CPUID
57752  #endif
57753  #endif
57754 #else
57755  #define DRFLAC_NO_CPUID
57756 #endif
57758 {
57759 #if defined(DRFLAC_SUPPORT_SSE2)
57760  #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE2)
57761  #if defined(DRFLAC_X64)
57762  return DRFLAC_TRUE;
57763  #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
57764  return DRFLAC_TRUE;
57765  #else
57766  #if defined(DRFLAC_NO_CPUID)
57767  return DRFLAC_FALSE;
57768  #else
57769  int info[4];
57770  drflac__cpuid(info, 1);
57771  return (info[3] & (1 << 26)) != 0;
57772  #endif
57773  #endif
57774  #else
57775  return DRFLAC_FALSE;
57776  #endif
57777 #else
57778  return DRFLAC_FALSE;
57779 #endif
57780 }
57782 {
57783 #if defined(DRFLAC_SUPPORT_SSE41)
57784  #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE41)
57785  #if defined(DRFLAC_X64)
57786  return DRFLAC_TRUE;
57787  #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE4_1__)
57788  return DRFLAC_TRUE;
57789  #else
57790  #if defined(DRFLAC_NO_CPUID)
57791  return DRFLAC_FALSE;
57792  #else
57793  int info[4];
57794  drflac__cpuid(info, 1);
57795  return (info[2] & (1 << 19)) != 0;
57796  #endif
57797  #endif
57798  #else
57799  return DRFLAC_FALSE;
57800  #endif
57801 #else
57802  return DRFLAC_FALSE;
57803 #endif
57804 }
57805 #if defined(_MSC_VER) && _MSC_VER >= 1500 && (defined(DRFLAC_X86) || defined(DRFLAC_X64)) && !defined(__clang__)
57806  #define DRFLAC_HAS_LZCNT_INTRINSIC
57807 #elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
57808  #define DRFLAC_HAS_LZCNT_INTRINSIC
57809 #elif defined(__clang__)
57810  #if defined(__has_builtin)
57811  #if __has_builtin(__builtin_clzll) || __has_builtin(__builtin_clzl)
57812  #define DRFLAC_HAS_LZCNT_INTRINSIC
57813  #endif
57814  #endif
57815 #endif
57816 #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(__clang__)
57817  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
57818  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
57819  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
57820 #elif defined(__clang__)
57821  #if defined(__has_builtin)
57822  #if __has_builtin(__builtin_bswap16)
57823  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
57824  #endif
57825  #if __has_builtin(__builtin_bswap32)
57826  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
57827  #endif
57828  #if __has_builtin(__builtin_bswap64)
57829  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
57830  #endif
57831  #endif
57832 #elif defined(__GNUC__)
57833  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
57834  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
57835  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
57836  #endif
57837  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
57838  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
57839  #endif
57840 #elif defined(__WATCOMC__) && defined(__386__)
57841  #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
57842  #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
57843  #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
57844  extern __inline drflac_uint16 _watcom_bswap16(drflac_uint16);
57845  extern __inline drflac_uint32 _watcom_bswap32(drflac_uint32);
57846  extern __inline drflac_uint64 _watcom_bswap64(drflac_uint64);
57847 #pragma aux _watcom_bswap16 = \
57848  "xchg al, ah" \
57849  parm [ax] \
57850  modify [ax];
57851 #pragma aux _watcom_bswap32 = \
57852  "bswap eax" \
57853  parm [eax] \
57854  modify [eax];
57855 #pragma aux _watcom_bswap64 = \
57856  "bswap eax" \
57857  "bswap edx" \
57858  "xchg eax,edx" \
57859  parm [eax edx] \
57860  modify [eax edx];
57861 #endif
57862 #ifndef DRFLAC_ASSERT
57863 #include <assert.h>
57864 #define DRFLAC_ASSERT(expression) assert(expression)
57865 #endif
57866 #ifndef DRFLAC_MALLOC
57867 #define DRFLAC_MALLOC(sz) malloc((sz))
57868 #endif
57869 #ifndef DRFLAC_REALLOC
57870 #define DRFLAC_REALLOC(p, sz) realloc((p), (sz))
57871 #endif
57872 #ifndef DRFLAC_FREE
57873 #define DRFLAC_FREE(p) free((p))
57874 #endif
57875 #ifndef DRFLAC_COPY_MEMORY
57876 #define DRFLAC_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
57877 #endif
57878 #ifndef DRFLAC_ZERO_MEMORY
57879 #define DRFLAC_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
57880 #endif
57881 #ifndef DRFLAC_ZERO_OBJECT
57882 #define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
57883 #endif
57884 #define DRFLAC_MAX_SIMD_VECTOR_SIZE 64
57885 typedef drflac_int32 drflac_result;
57886 #define DRFLAC_SUCCESS 0
57887 #define DRFLAC_ERROR -1
57888 #define DRFLAC_INVALID_ARGS -2
57889 #define DRFLAC_INVALID_OPERATION -3
57890 #define DRFLAC_OUT_OF_MEMORY -4
57891 #define DRFLAC_OUT_OF_RANGE -5
57892 #define DRFLAC_ACCESS_DENIED -6
57893 #define DRFLAC_DOES_NOT_EXIST -7
57894 #define DRFLAC_ALREADY_EXISTS -8
57895 #define DRFLAC_TOO_MANY_OPEN_FILES -9
57896 #define DRFLAC_INVALID_FILE -10
57897 #define DRFLAC_TOO_BIG -11
57898 #define DRFLAC_PATH_TOO_LONG -12
57899 #define DRFLAC_NAME_TOO_LONG -13
57900 #define DRFLAC_NOT_DIRECTORY -14
57901 #define DRFLAC_IS_DIRECTORY -15
57902 #define DRFLAC_DIRECTORY_NOT_EMPTY -16
57903 #define DRFLAC_END_OF_FILE -17
57904 #define DRFLAC_NO_SPACE -18
57905 #define DRFLAC_BUSY -19
57906 #define DRFLAC_IO_ERROR -20
57907 #define DRFLAC_INTERRUPT -21
57908 #define DRFLAC_UNAVAILABLE -22
57909 #define DRFLAC_ALREADY_IN_USE -23
57910 #define DRFLAC_BAD_ADDRESS -24
57911 #define DRFLAC_BAD_SEEK -25
57912 #define DRFLAC_BAD_PIPE -26
57913 #define DRFLAC_DEADLOCK -27
57914 #define DRFLAC_TOO_MANY_LINKS -28
57915 #define DRFLAC_NOT_IMPLEMENTED -29
57916 #define DRFLAC_NO_MESSAGE -30
57917 #define DRFLAC_BAD_MESSAGE -31
57918 #define DRFLAC_NO_DATA_AVAILABLE -32
57919 #define DRFLAC_INVALID_DATA -33
57920 #define DRFLAC_TIMEOUT -34
57921 #define DRFLAC_NO_NETWORK -35
57922 #define DRFLAC_NOT_UNIQUE -36
57923 #define DRFLAC_NOT_SOCKET -37
57924 #define DRFLAC_NO_ADDRESS -38
57925 #define DRFLAC_BAD_PROTOCOL -39
57926 #define DRFLAC_PROTOCOL_UNAVAILABLE -40
57927 #define DRFLAC_PROTOCOL_NOT_SUPPORTED -41
57928 #define DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED -42
57929 #define DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED -43
57930 #define DRFLAC_SOCKET_NOT_SUPPORTED -44
57931 #define DRFLAC_CONNECTION_RESET -45
57932 #define DRFLAC_ALREADY_CONNECTED -46
57933 #define DRFLAC_NOT_CONNECTED -47
57934 #define DRFLAC_CONNECTION_REFUSED -48
57935 #define DRFLAC_NO_HOST -49
57936 #define DRFLAC_IN_PROGRESS -50
57937 #define DRFLAC_CANCELLED -51
57938 #define DRFLAC_MEMORY_ALREADY_MAPPED -52
57939 #define DRFLAC_AT_END -53
57940 #define DRFLAC_CRC_MISMATCH -128
57941 #define DRFLAC_SUBFRAME_CONSTANT 0
57942 #define DRFLAC_SUBFRAME_VERBATIM 1
57943 #define DRFLAC_SUBFRAME_FIXED 8
57944 #define DRFLAC_SUBFRAME_LPC 32
57945 #define DRFLAC_SUBFRAME_RESERVED 255
57946 #define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE 0
57947 #define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 1
57948 #define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT 0
57949 #define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE 8
57950 #define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9
57951 #define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10
57952 #define drflac_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
57953 DRFLAC_API void drflac_version(drflac_uint32* pMajor, drflac_uint32* pMinor, drflac_uint32* pRevision)
57954 {
57955  if (pMajor) {
57956  *pMajor = DRFLAC_VERSION_MAJOR;
57957  }
57958  if (pMinor) {
57959  *pMinor = DRFLAC_VERSION_MINOR;
57960  }
57961  if (pRevision) {
57962  *pRevision = DRFLAC_VERSION_REVISION;
57963  }
57964 }
57965 DRFLAC_API const char* drflac_version_string(void)
57966 {
57967  return DRFLAC_VERSION_STRING;
57968 }
57969 #if defined(__has_feature)
57970  #if __has_feature(thread_sanitizer)
57971  #define DRFLAC_NO_THREAD_SANITIZE __attribute__((no_sanitize("thread")))
57972  #else
57973  #define DRFLAC_NO_THREAD_SANITIZE
57974  #endif
57975 #else
57976  #define DRFLAC_NO_THREAD_SANITIZE
57977 #endif
57978 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
57979 static drflac_bool32 drflac__gIsLZCNTSupported = DRFLAC_FALSE;
57980 #endif
57981 #ifndef DRFLAC_NO_CPUID
57982 static drflac_bool32 drflac__gIsSSE2Supported = DRFLAC_FALSE;
57983 static drflac_bool32 drflac__gIsSSE41Supported = DRFLAC_FALSE;
57985 {
57986  static drflac_bool32 isCPUCapsInitialized = DRFLAC_FALSE;
57987  if (!isCPUCapsInitialized) {
57988 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
57989  int info[4] = {0};
57990  drflac__cpuid(info, 0x80000001);
57991  drflac__gIsLZCNTSupported = (info[2] & (1 << 5)) != 0;
57992 #endif
57993  drflac__gIsSSE2Supported = drflac_has_sse2();
57994  drflac__gIsSSE41Supported = drflac_has_sse41();
57995  isCPUCapsInitialized = DRFLAC_TRUE;
57996  }
57997 }
57998 #else
58001 {
58002 #if defined(DRFLAC_SUPPORT_NEON)
58003  #if defined(DRFLAC_ARM) && !defined(DRFLAC_NO_NEON)
58004  #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
58005  return DRFLAC_TRUE;
58006  #else
58007  return DRFLAC_FALSE;
58008  #endif
58009  #else
58010  return DRFLAC_FALSE;
58011  #endif
58012 #else
58013  return DRFLAC_FALSE;
58014 #endif
58015 }
58017 {
58019 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
58020  drflac__gIsLZCNTSupported = DRFLAC_TRUE;
58021 #endif
58022 }
58023 #endif
58025 {
58026 #if defined(DRFLAC_X86) || defined(DRFLAC_X64)
58027  return DRFLAC_TRUE;
58028 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
58029  return DRFLAC_TRUE;
58030 #else
58031  int n = 1;
58032  return (*(char*)&n) == 1;
58033 #endif
58034 }
58036 {
58037 #ifdef DRFLAC_HAS_BYTESWAP16_INTRINSIC
58038  #if defined(_MSC_VER) && !defined(__clang__)
58039  return _byteswap_ushort(n);
58040  #elif defined(__GNUC__) || defined(__clang__)
58041  return __builtin_bswap16(n);
58042  #elif defined(__WATCOMC__) && defined(__386__)
58043  return _watcom_bswap16(n);
58044  #else
58045  #error "This compiler does not support the byte swap intrinsic."
58046  #endif
58047 #else
58048  return ((n & 0xFF00) >> 8) |
58049  ((n & 0x00FF) << 8);
58050 #endif
58051 }
58053 {
58054 #ifdef DRFLAC_HAS_BYTESWAP32_INTRINSIC
58055  #if defined(_MSC_VER) && !defined(__clang__)
58056  return _byteswap_ulong(n);
58057  #elif defined(__GNUC__) || defined(__clang__)
58058  #if defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRFLAC_64BIT)
58059  drflac_uint32 r;
58060  __asm__ __volatile__ (
58061  #if defined(DRFLAC_64BIT)
58062  "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n)
58063  #else
58064  "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
58065  #endif
58066  );
58067  return r;
58068  #else
58069  return __builtin_bswap32(n);
58070  #endif
58071  #elif defined(__WATCOMC__) && defined(__386__)
58072  return _watcom_bswap32(n);
58073  #else
58074  #error "This compiler does not support the byte swap intrinsic."
58075  #endif
58076 #else
58077  return ((n & 0xFF000000) >> 24) |
58078  ((n & 0x00FF0000) >> 8) |
58079  ((n & 0x0000FF00) << 8) |
58080  ((n & 0x000000FF) << 24);
58081 #endif
58082 }
58084 {
58085 #ifdef DRFLAC_HAS_BYTESWAP64_INTRINSIC
58086  #if defined(_MSC_VER) && !defined(__clang__)
58087  return _byteswap_uint64(n);
58088  #elif defined(__GNUC__) || defined(__clang__)
58089  return __builtin_bswap64(n);
58090  #elif defined(__WATCOMC__) && defined(__386__)
58091  return _watcom_bswap64(n);
58092  #else
58093  #error "This compiler does not support the byte swap intrinsic."
58094  #endif
58095 #else
58096  return ((n & ((drflac_uint64)0xFF000000 << 32)) >> 56) |
58097  ((n & ((drflac_uint64)0x00FF0000 << 32)) >> 40) |
58098  ((n & ((drflac_uint64)0x0000FF00 << 32)) >> 24) |
58099  ((n & ((drflac_uint64)0x000000FF << 32)) >> 8) |
58100  ((n & ((drflac_uint64)0xFF000000 )) << 8) |
58101  ((n & ((drflac_uint64)0x00FF0000 )) << 24) |
58102  ((n & ((drflac_uint64)0x0000FF00 )) << 40) |
58103  ((n & ((drflac_uint64)0x000000FF )) << 56);
58104 #endif
58105 }
58107 {
58108  if (drflac__is_little_endian()) {
58109  return drflac__swap_endian_uint16(n);
58110  }
58111  return n;
58112 }
58114 {
58115  if (drflac__is_little_endian()) {
58116  return drflac__swap_endian_uint32(n);
58117  }
58118  return n;
58119 }
58121 {
58122  if (drflac__is_little_endian()) {
58123  return drflac__swap_endian_uint64(n);
58124  }
58125  return n;
58126 }
58128 {
58129  if (!drflac__is_little_endian()) {
58130  return drflac__swap_endian_uint32(n);
58131  }
58132  return n;
58133 }
58135 {
58136  drflac_uint32 result = 0;
58137  result |= (n & 0x7F000000) >> 3;
58138  result |= (n & 0x007F0000) >> 2;
58139  result |= (n & 0x00007F00) >> 1;
58140  result |= (n & 0x0000007F) >> 0;
58141  return result;
58142 }
58143 static drflac_uint8 drflac__crc8_table[] = {
58144  0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
58145  0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
58146  0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
58147  0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
58148  0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
58149  0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
58150  0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
58151  0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
58152  0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
58153  0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
58154  0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
58155  0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
58156  0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
58157  0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
58158  0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
58159  0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
58160 };
58162  0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
58163  0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
58164  0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
58165  0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
58166  0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
58167  0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
58168  0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
58169  0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
58170  0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
58171  0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
58172  0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
58173  0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
58174  0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
58175  0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
58176  0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
58177  0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
58178  0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
58179  0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
58180  0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
58181  0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
58182  0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
58183  0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
58184  0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
58185  0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
58186  0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
58187  0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
58188  0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
58189  0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
58190  0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
58191  0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
58192  0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
58193  0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
58194 };
58196 {
58197  return drflac__crc8_table[crc ^ data];
58198 }
58200 {
58201 #ifdef DR_FLAC_NO_CRC
58202  (void)crc;
58203  (void)data;
58204  (void)count;
58205  return 0;
58206 #else
58207 #if 0
58208  drflac_uint8 p = 0x07;
58209  for (int i = count-1; i >= 0; --i) {
58210  drflac_uint8 bit = (data & (1 << i)) >> i;
58211  if (crc & 0x80) {
58212  crc = ((crc << 1) | bit) ^ p;
58213  } else {
58214  crc = ((crc << 1) | bit);
58215  }
58216  }
58217  return crc;
58218 #else
58219  drflac_uint32 wholeBytes;
58220  drflac_uint32 leftoverBits;
58221  drflac_uint64 leftoverDataMask;
58222  static drflac_uint64 leftoverDataMaskTable[8] = {
58223  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
58224  };
58225  DRFLAC_ASSERT(count <= 32);
58226  wholeBytes = count >> 3;
58227  leftoverBits = count - (wholeBytes*8);
58228  leftoverDataMask = leftoverDataMaskTable[leftoverBits];
58229  switch (wholeBytes) {
58230  case 4: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits)));
58231  case 3: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits)));
58232  case 2: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits)));
58233  case 1: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits)));
58234  case 0: if (leftoverBits > 0) crc = (drflac_uint8)((crc << leftoverBits) ^ drflac__crc8_table[(crc >> (8 - leftoverBits)) ^ (data & leftoverDataMask)]);
58235  }
58236  return crc;
58237 #endif
58238 #endif
58239 }
58241 {
58242  return (crc << 8) ^ drflac__crc16_table[(drflac_uint8)(crc >> 8) ^ data];
58243 }
58245 {
58246 #ifdef DRFLAC_64BIT
58247  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF));
58248  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF));
58249  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF));
58250  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF));
58251 #endif
58252  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF));
58253  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF));
58254  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF));
58255  crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF));
58256  return crc;
58257 }
58259 {
58260  switch (byteCount)
58261  {
58262 #ifdef DRFLAC_64BIT
58263  case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF));
58264  case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF));
58265  case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF));
58266  case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF));
58267 #endif
58268  case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF));
58269  case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF));
58270  case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF));
58271  case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF));
58272  }
58273  return crc;
58274 }
58275 #if 0
58276 static DRFLAC_INLINE drflac_uint16 drflac_crc16__32bit(drflac_uint16 crc, drflac_uint32 data, drflac_uint32 count)
58277 {
58278 #ifdef DR_FLAC_NO_CRC
58279  (void)crc;
58280  (void)data;
58281  (void)count;
58282  return 0;
58283 #else
58284 #if 0
58285  drflac_uint16 p = 0x8005;
58286  for (int i = count-1; i >= 0; --i) {
58287  drflac_uint16 bit = (data & (1ULL << i)) >> i;
58288  if (r & 0x8000) {
58289  r = ((r << 1) | bit) ^ p;
58290  } else {
58291  r = ((r << 1) | bit);
58292  }
58293  }
58294  return crc;
58295 #else
58296  drflac_uint32 wholeBytes;
58297  drflac_uint32 leftoverBits;
58298  drflac_uint64 leftoverDataMask;
58299  static drflac_uint64 leftoverDataMaskTable[8] = {
58300  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
58301  };
58302  DRFLAC_ASSERT(count <= 64);
58303  wholeBytes = count >> 3;
58304  leftoverBits = count & 7;
58305  leftoverDataMask = leftoverDataMaskTable[leftoverBits];
58306  switch (wholeBytes) {
58307  default:
58308  case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits)));
58309  case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits)));
58310  case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits)));
58311  case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits)));
58312  case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)];
58313  }
58314  return crc;
58315 #endif
58316 #endif
58317 }
58318 static DRFLAC_INLINE drflac_uint16 drflac_crc16__64bit(drflac_uint16 crc, drflac_uint64 data, drflac_uint32 count)
58319 {
58320 #ifdef DR_FLAC_NO_CRC
58321  (void)crc;
58322  (void)data;
58323  (void)count;
58324  return 0;
58325 #else
58326  drflac_uint32 wholeBytes;
58327  drflac_uint32 leftoverBits;
58328  drflac_uint64 leftoverDataMask;
58329  static drflac_uint64 leftoverDataMaskTable[8] = {
58330  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
58331  };
58332  DRFLAC_ASSERT(count <= 64);
58333  wholeBytes = count >> 3;
58334  leftoverBits = count & 7;
58335  leftoverDataMask = leftoverDataMaskTable[leftoverBits];
58336  switch (wholeBytes) {
58337  default:
58338  case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0xFF000000 << 32) << leftoverBits)) >> (56 + leftoverBits)));
58339  case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x00FF0000 << 32) << leftoverBits)) >> (48 + leftoverBits)));
58340  case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x0000FF00 << 32) << leftoverBits)) >> (40 + leftoverBits)));
58341  case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x000000FF << 32) << leftoverBits)) >> (32 + leftoverBits)));
58342  case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0xFF000000 ) << leftoverBits)) >> (24 + leftoverBits)));
58343  case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x00FF0000 ) << leftoverBits)) >> (16 + leftoverBits)));
58344  case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x0000FF00 ) << leftoverBits)) >> ( 8 + leftoverBits)));
58345  case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x000000FF ) << leftoverBits)) >> ( 0 + leftoverBits)));
58346  case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)];
58347  }
58348  return crc;
58349 #endif
58350 }
58352 {
58353 #ifdef DRFLAC_64BIT
58354  return drflac_crc16__64bit(crc, data, count);
58355 #else
58356  return drflac_crc16__32bit(crc, data, count);
58357 #endif
58358 }
58359 #endif
58360 #ifdef DRFLAC_64BIT
58361 #define drflac__be2host__cache_line drflac__be2host_64
58362 #else
58363 #define drflac__be2host__cache_line drflac__be2host_32
58364 #endif
58365 #define DRFLAC_CACHE_L1_SIZE_BYTES(bs) (sizeof((bs)->cache))
58366 #define DRFLAC_CACHE_L1_SIZE_BITS(bs) (sizeof((bs)->cache)*8)
58367 #define DRFLAC_CACHE_L1_BITS_REMAINING(bs) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (bs)->consumedBits)
58368 #define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~((~(drflac_cache_t)0) >> (_bitCount)))
58369 #define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (_bitCount))
58370 #define DRFLAC_CACHE_L1_SELECT(bs, _bitCount) (((bs)->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount))
58371 #define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)))
58372 #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)))
58373 #define DRFLAC_CACHE_L2_SIZE_BYTES(bs) (sizeof((bs)->cacheL2))
58374 #define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0]))
58375 #define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line)
58376 #ifndef DR_FLAC_NO_CRC
58378 {
58379  bs->crc16 = 0;
58380  bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
58381 }
58383 {
58384  if (bs->crc16CacheIgnoredBytes == 0) {
58385  bs->crc16 = drflac_crc16_cache(bs->crc16, bs->crc16Cache);
58386  } else {
58388  bs->crc16CacheIgnoredBytes = 0;
58389  }
58390 }
58392 {
58394  if (DRFLAC_CACHE_L1_BITS_REMAINING(bs) == 0) {
58396  } else {
58398  bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
58399  }
58400  return bs->crc16;
58401 }
58402 #endif
58404 {
58405  size_t bytesRead;
58406  size_t alignedL1LineCount;
58407  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
58408  bs->cache = bs->cacheL2[bs->nextL2Line++];
58409  return DRFLAC_TRUE;
58410  }
58411  if (bs->unalignedByteCount > 0) {
58412  return DRFLAC_FALSE;
58413  }
58414  bytesRead = bs->onRead(bs->pUserData, bs->cacheL2, DRFLAC_CACHE_L2_SIZE_BYTES(bs));
58415  bs->nextL2Line = 0;
58416  if (bytesRead == DRFLAC_CACHE_L2_SIZE_BYTES(bs)) {
58417  bs->cache = bs->cacheL2[bs->nextL2Line++];
58418  return DRFLAC_TRUE;
58419  }
58420  alignedL1LineCount = bytesRead / DRFLAC_CACHE_L1_SIZE_BYTES(bs);
58421  bs->unalignedByteCount = bytesRead - (alignedL1LineCount * DRFLAC_CACHE_L1_SIZE_BYTES(bs));
58422  if (bs->unalignedByteCount > 0) {
58423  bs->unalignedCache = bs->cacheL2[alignedL1LineCount];
58424  }
58425  if (alignedL1LineCount > 0) {
58426  size_t offset = DRFLAC_CACHE_L2_LINE_COUNT(bs) - alignedL1LineCount;
58427  size_t i;
58428  for (i = alignedL1LineCount; i > 0; --i) {
58429  bs->cacheL2[i-1 + offset] = bs->cacheL2[i-1];
58430  }
58431  bs->nextL2Line = (drflac_uint32)offset;
58432  bs->cache = bs->cacheL2[bs->nextL2Line++];
58433  return DRFLAC_TRUE;
58434  } else {
58436  return DRFLAC_FALSE;
58437  }
58438 }
58440 {
58441  size_t bytesRead;
58442 #ifndef DR_FLAC_NO_CRC
58444 #endif
58447  bs->consumedBits = 0;
58448 #ifndef DR_FLAC_NO_CRC
58449  bs->crc16Cache = bs->cache;
58450 #endif
58451  return DRFLAC_TRUE;
58452  }
58453  bytesRead = bs->unalignedByteCount;
58454  if (bytesRead == 0) {
58456  return DRFLAC_FALSE;
58457  }
58458  DRFLAC_ASSERT(bytesRead < DRFLAC_CACHE_L1_SIZE_BYTES(bs));
58459  bs->consumedBits = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bytesRead) * 8;
58462  bs->unalignedByteCount = 0;
58463 #ifndef DR_FLAC_NO_CRC
58464  bs->crc16Cache = bs->cache >> bs->consumedBits;
58465  bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
58466 #endif
58467  return DRFLAC_TRUE;
58468 }
58469 static void drflac__reset_cache(drflac_bs* bs)
58470 {
58473  bs->cache = 0;
58474  bs->unalignedByteCount = 0;
58475  bs->unalignedCache = 0;
58476 #ifndef DR_FLAC_NO_CRC
58477  bs->crc16Cache = 0;
58478  bs->crc16CacheIgnoredBytes = 0;
58479 #endif
58480 }
58481 static DRFLAC_INLINE drflac_bool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, drflac_uint32* pResultOut)
58482 {
58483  DRFLAC_ASSERT(bs != NULL);
58484  DRFLAC_ASSERT(pResultOut != NULL);
58485  DRFLAC_ASSERT(bitCount > 0);
58486  DRFLAC_ASSERT(bitCount <= 32);
58487  if (bs->consumedBits == DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
58488  if (!drflac__reload_cache(bs)) {
58489  return DRFLAC_FALSE;
58490  }
58491  }
58492  if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
58493 #ifdef DRFLAC_64BIT
58494  *pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
58495  bs->consumedBits += bitCount;
58496  bs->cache <<= bitCount;
58497 #else
58498  if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
58499  *pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
58500  bs->consumedBits += bitCount;
58501  bs->cache <<= bitCount;
58502  } else {
58503  *pResultOut = (drflac_uint32)bs->cache;
58505  bs->cache = 0;
58506  }
58507 #endif
58508  return DRFLAC_TRUE;
58509  } else {
58511  drflac_uint32 bitCountLo = bitCount - bitCountHi;
58512  drflac_uint32 resultHi;
58513  DRFLAC_ASSERT(bitCountHi > 0);
58514  DRFLAC_ASSERT(bitCountHi < 32);
58515  resultHi = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountHi);
58516  if (!drflac__reload_cache(bs)) {
58517  return DRFLAC_FALSE;
58518  }
58519  *pResultOut = (resultHi << bitCountLo) | (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo);
58520  bs->consumedBits += bitCountLo;
58521  bs->cache <<= bitCountLo;
58522  return DRFLAC_TRUE;
58523  }
58524 }
58525 static drflac_bool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, drflac_int32* pResult)
58526 {
58527  drflac_uint32 result;
58528  DRFLAC_ASSERT(bs != NULL);
58529  DRFLAC_ASSERT(pResult != NULL);
58530  DRFLAC_ASSERT(bitCount > 0);
58531  DRFLAC_ASSERT(bitCount <= 32);
58532  if (!drflac__read_uint32(bs, bitCount, &result)) {
58533  return DRFLAC_FALSE;
58534  }
58535  if (bitCount < 32) {
58536  drflac_uint32 signbit;
58537  signbit = ((result >> (bitCount-1)) & 0x01);
58538  result |= (~signbit + 1) << bitCount;
58539  }
58540  *pResult = (drflac_int32)result;
58541  return DRFLAC_TRUE;
58542 }
58543 #ifdef DRFLAC_64BIT
58544 static drflac_bool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, drflac_uint64* pResultOut)
58545 {
58546  drflac_uint32 resultHi;
58547  drflac_uint32 resultLo;
58548  DRFLAC_ASSERT(bitCount <= 64);
58549  DRFLAC_ASSERT(bitCount > 32);
58550  if (!drflac__read_uint32(bs, bitCount - 32, &resultHi)) {
58551  return DRFLAC_FALSE;
58552  }
58553  if (!drflac__read_uint32(bs, 32, &resultLo)) {
58554  return DRFLAC_FALSE;
58555  }
58556  *pResultOut = (((drflac_uint64)resultHi) << 32) | ((drflac_uint64)resultLo);
58557  return DRFLAC_TRUE;
58558 }
58559 #endif
58560 #if 0
58561 static drflac_bool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, drflac_int64* pResultOut)
58562 {
58563  drflac_uint64 result;
58564  drflac_uint64 signbit;
58565  DRFLAC_ASSERT(bitCount <= 64);
58566  if (!drflac__read_uint64(bs, bitCount, &result)) {
58567  return DRFLAC_FALSE;
58568  }
58569  signbit = ((result >> (bitCount-1)) & 0x01);
58570  result |= (~signbit + 1) << bitCount;
58571  *pResultOut = (drflac_int64)result;
58572  return DRFLAC_TRUE;
58573 }
58574 #endif
58575 static drflac_bool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, drflac_uint16* pResult)
58576 {
58577  drflac_uint32 result;
58578  DRFLAC_ASSERT(bs != NULL);
58579  DRFLAC_ASSERT(pResult != NULL);
58580  DRFLAC_ASSERT(bitCount > 0);
58581  DRFLAC_ASSERT(bitCount <= 16);
58582  if (!drflac__read_uint32(bs, bitCount, &result)) {
58583  return DRFLAC_FALSE;
58584  }
58585  *pResult = (drflac_uint16)result;
58586  return DRFLAC_TRUE;
58587 }
58588 #if 0
58589 static drflac_bool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, drflac_int16* pResult)
58590 {
58591  drflac_int32 result;
58592  DRFLAC_ASSERT(bs != NULL);
58593  DRFLAC_ASSERT(pResult != NULL);
58594  DRFLAC_ASSERT(bitCount > 0);
58595  DRFLAC_ASSERT(bitCount <= 16);
58596  if (!drflac__read_int32(bs, bitCount, &result)) {
58597  return DRFLAC_FALSE;
58598  }
58599  *pResult = (drflac_int16)result;
58600  return DRFLAC_TRUE;
58601 }
58602 #endif
58603 static drflac_bool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, drflac_uint8* pResult)
58604 {
58605  drflac_uint32 result;
58606  DRFLAC_ASSERT(bs != NULL);
58607  DRFLAC_ASSERT(pResult != NULL);
58608  DRFLAC_ASSERT(bitCount > 0);
58609  DRFLAC_ASSERT(bitCount <= 8);
58610  if (!drflac__read_uint32(bs, bitCount, &result)) {
58611  return DRFLAC_FALSE;
58612  }
58613  *pResult = (drflac_uint8)result;
58614  return DRFLAC_TRUE;
58615 }
58616 static drflac_bool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, drflac_int8* pResult)
58617 {
58618  drflac_int32 result;
58619  DRFLAC_ASSERT(bs != NULL);
58620  DRFLAC_ASSERT(pResult != NULL);
58621  DRFLAC_ASSERT(bitCount > 0);
58622  DRFLAC_ASSERT(bitCount <= 8);
58623  if (!drflac__read_int32(bs, bitCount, &result)) {
58624  return DRFLAC_FALSE;
58625  }
58626  *pResult = (drflac_int8)result;
58627  return DRFLAC_TRUE;
58628 }
58629 static drflac_bool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek)
58630 {
58631  if (bitsToSeek <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
58632  bs->consumedBits += (drflac_uint32)bitsToSeek;
58633  bs->cache <<= bitsToSeek;
58634  return DRFLAC_TRUE;
58635  } else {
58636  bitsToSeek -= DRFLAC_CACHE_L1_BITS_REMAINING(bs);
58638  bs->cache = 0;
58639 #ifdef DRFLAC_64BIT
58640  while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
58641  drflac_uint64 bin;
58642  if (!drflac__read_uint64(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) {
58643  return DRFLAC_FALSE;
58644  }
58645  bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs);
58646  }
58647 #else
58648  while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
58649  drflac_uint32 bin;
58650  if (!drflac__read_uint32(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) {
58651  return DRFLAC_FALSE;
58652  }
58653  bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs);
58654  }
58655 #endif
58656  while (bitsToSeek >= 8) {
58657  drflac_uint8 bin;
58658  if (!drflac__read_uint8(bs, 8, &bin)) {
58659  return DRFLAC_FALSE;
58660  }
58661  bitsToSeek -= 8;
58662  }
58663  if (bitsToSeek > 0) {
58664  drflac_uint8 bin;
58665  if (!drflac__read_uint8(bs, (drflac_uint32)bitsToSeek, &bin)) {
58666  return DRFLAC_FALSE;
58667  }
58668  bitsToSeek = 0;
58669  }
58670  DRFLAC_ASSERT(bitsToSeek == 0);
58671  return DRFLAC_TRUE;
58672  }
58673 }
58675 {
58676  DRFLAC_ASSERT(bs != NULL);
58678  return DRFLAC_FALSE;
58679  }
58680  for (;;) {
58681  drflac_uint8 hi;
58682 #ifndef DR_FLAC_NO_CRC
58683  drflac__reset_crc16(bs);
58684 #endif
58685  if (!drflac__read_uint8(bs, 8, &hi)) {
58686  return DRFLAC_FALSE;
58687  }
58688  if (hi == 0xFF) {
58689  drflac_uint8 lo;
58690  if (!drflac__read_uint8(bs, 6, &lo)) {
58691  return DRFLAC_FALSE;
58692  }
58693  if (lo == 0x3E) {
58694  return DRFLAC_TRUE;
58695  } else {
58697  return DRFLAC_FALSE;
58698  }
58699  }
58700  }
58701  }
58702 }
58703 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
58704 #define DRFLAC_IMPLEMENT_CLZ_LZCNT
58705 #endif
58706 #if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(__clang__)
58707 #define DRFLAC_IMPLEMENT_CLZ_MSVC
58708 #endif
58709 #if defined(__WATCOMC__) && defined(__386__)
58710 #define DRFLAC_IMPLEMENT_CLZ_WATCOM
58711 #endif
58713 {
58714  drflac_uint32 n;
58715  static drflac_uint32 clz_table_4[] = {
58716  0,
58717  4,
58718  3, 3,
58719  2, 2, 2, 2,
58720  1, 1, 1, 1, 1, 1, 1, 1
58721  };
58722  if (x == 0) {
58723  return sizeof(x)*8;
58724  }
58725  n = clz_table_4[x >> (sizeof(x)*8 - 4)];
58726  if (n == 0) {
58727 #ifdef DRFLAC_64BIT
58728  if ((x & ((drflac_uint64)0xFFFFFFFF << 32)) == 0) { n = 32; x <<= 32; }
58729  if ((x & ((drflac_uint64)0xFFFF0000 << 32)) == 0) { n += 16; x <<= 16; }
58730  if ((x & ((drflac_uint64)0xFF000000 << 32)) == 0) { n += 8; x <<= 8; }
58731  if ((x & ((drflac_uint64)0xF0000000 << 32)) == 0) { n += 4; x <<= 4; }
58732 #else
58733  if ((x & 0xFFFF0000) == 0) { n = 16; x <<= 16; }
58734  if ((x & 0xFF000000) == 0) { n += 8; x <<= 8; }
58735  if ((x & 0xF0000000) == 0) { n += 4; x <<= 4; }
58736 #endif
58737  n += clz_table_4[x >> (sizeof(x)*8 - 4)];
58738  }
58739  return n - 1;
58740 }
58741 #ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
58742 static DRFLAC_INLINE drflac_bool32 drflac__is_lzcnt_supported(void)
58743 {
58744 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
58745  return DRFLAC_TRUE;
58746 #else
58747  #ifdef DRFLAC_HAS_LZCNT_INTRINSIC
58748  return drflac__gIsLZCNTSupported;
58749  #else
58750  return DRFLAC_FALSE;
58751  #endif
58752 #endif
58753 }
58754 static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
58755 {
58756 #if defined(_MSC_VER)
58757  #ifdef DRFLAC_64BIT
58758  return (drflac_uint32)__lzcnt64(x);
58759  #else
58760  return (drflac_uint32)__lzcnt(x);
58761  #endif
58762 #else
58763  #if defined(__GNUC__) || defined(__clang__)
58764  #if defined(DRFLAC_X64)
58765  {
58766  drflac_uint64 r;
58767  __asm__ __volatile__ (
58768  "lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
58769  );
58770  return (drflac_uint32)r;
58771  }
58772  #elif defined(DRFLAC_X86)
58773  {
58774  drflac_uint32 r;
58775  __asm__ __volatile__ (
58776  "lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
58777  );
58778  return r;
58779  }
58780  #elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(DRFLAC_64BIT)
58781  {
58782  unsigned int r;
58783  __asm__ __volatile__ (
58784  #if defined(DRFLAC_64BIT)
58785  "clz %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(x)
58786  #else
58787  "clz %[out], %[in]" : [out]"=r"(r) : [in]"r"(x)
58788  #endif
58789  );
58790  return r;
58791  }
58792  #else
58793  if (x == 0) {
58794  return sizeof(x)*8;
58795  }
58796  #ifdef DRFLAC_64BIT
58797  return (drflac_uint32)__builtin_clzll((drflac_uint64)x);
58798  #else
58799  return (drflac_uint32)__builtin_clzl((drflac_uint32)x);
58800  #endif
58801  #endif
58802  #else
58803  #error "This compiler does not support the lzcnt intrinsic."
58804  #endif
58805 #endif
58806 }
58807 #endif
58808 #ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
58809 #include <intrin.h>
58810 static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x)
58811 {
58812  drflac_uint32 n;
58813  if (x == 0) {
58814  return sizeof(x)*8;
58815  }
58816 #ifdef DRFLAC_64BIT
58817  _BitScanReverse64((unsigned long*)&n, x);
58818 #else
58819  _BitScanReverse((unsigned long*)&n, x);
58820 #endif
58821  return sizeof(x)*8 - n - 1;
58822 }
58823 #endif
58824 #ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM
58825 static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
58826 #pragma aux drflac__clz_watcom = \
58827  "bsr eax, eax" \
58828  "xor eax, 31" \
58829  parm [eax] nomemory \
58830  value [eax] \
58831  modify exact [eax] nomemory;
58832 #endif
58834 {
58835 #ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
58836  if (drflac__is_lzcnt_supported()) {
58837  return drflac__clz_lzcnt(x);
58838  } else
58839 #endif
58840  {
58841 #ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
58842  return drflac__clz_msvc(x);
58843 #elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
58844  return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
58845 #else
58846  return drflac__clz_software(x);
58847 #endif
58848  }
58849 }
58850 static DRFLAC_INLINE drflac_bool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned int* pOffsetOut)
58851 {
58852  drflac_uint32 zeroCounter = 0;
58853  drflac_uint32 setBitOffsetPlus1;
58854  while (bs->cache == 0) {
58855  zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
58856  if (!drflac__reload_cache(bs)) {
58857  return DRFLAC_FALSE;
58858  }
58859  }
58860  setBitOffsetPlus1 = drflac__clz(bs->cache);
58861  setBitOffsetPlus1 += 1;
58862  bs->consumedBits += setBitOffsetPlus1;
58863  bs->cache <<= setBitOffsetPlus1;
58864  *pOffsetOut = zeroCounter + setBitOffsetPlus1 - 1;
58865  return DRFLAC_TRUE;
58866 }
58867 static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFromStart)
58868 {
58869  DRFLAC_ASSERT(bs != NULL);
58870  DRFLAC_ASSERT(offsetFromStart > 0);
58871  if (offsetFromStart > 0x7FFFFFFF) {
58872  drflac_uint64 bytesRemaining = offsetFromStart;
58873  if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
58874  return DRFLAC_FALSE;
58875  }
58876  bytesRemaining -= 0x7FFFFFFF;
58877  while (bytesRemaining > 0x7FFFFFFF) {
58878  if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
58879  return DRFLAC_FALSE;
58880  }
58881  bytesRemaining -= 0x7FFFFFFF;
58882  }
58883  if (bytesRemaining > 0) {
58884  if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
58885  return DRFLAC_FALSE;
58886  }
58887  }
58888  } else {
58889  if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
58890  return DRFLAC_FALSE;
58891  }
58892  }
58893  drflac__reset_cache(bs);
58894  return DRFLAC_TRUE;
58895 }
58897 {
58898  drflac_uint8 crc;
58899  drflac_uint64 result;
58900  drflac_uint8 utf8[7] = {0};
58901  int byteCount;
58902  int i;
58903  DRFLAC_ASSERT(bs != NULL);
58904  DRFLAC_ASSERT(pNumberOut != NULL);
58905  DRFLAC_ASSERT(pCRCOut != NULL);
58906  crc = *pCRCOut;
58907  if (!drflac__read_uint8(bs, 8, utf8)) {
58908  *pNumberOut = 0;
58909  return DRFLAC_AT_END;
58910  }
58911  crc = drflac_crc8(crc, utf8[0], 8);
58912  if ((utf8[0] & 0x80) == 0) {
58913  *pNumberOut = utf8[0];
58914  *pCRCOut = crc;
58915  return DRFLAC_SUCCESS;
58916  }
58917  if ((utf8[0] & 0xE0) == 0xC0) {
58918  byteCount = 2;
58919  } else if ((utf8[0] & 0xF0) == 0xE0) {
58920  byteCount = 3;
58921  } else if ((utf8[0] & 0xF8) == 0xF0) {
58922  byteCount = 4;
58923  } else if ((utf8[0] & 0xFC) == 0xF8) {
58924  byteCount = 5;
58925  } else if ((utf8[0] & 0xFE) == 0xFC) {
58926  byteCount = 6;
58927  } else if ((utf8[0] & 0xFF) == 0xFE) {
58928  byteCount = 7;
58929  } else {
58930  *pNumberOut = 0;
58931  return DRFLAC_CRC_MISMATCH;
58932  }
58933  DRFLAC_ASSERT(byteCount > 1);
58934  result = (drflac_uint64)(utf8[0] & (0xFF >> (byteCount + 1)));
58935  for (i = 1; i < byteCount; ++i) {
58936  if (!drflac__read_uint8(bs, 8, utf8 + i)) {
58937  *pNumberOut = 0;
58938  return DRFLAC_AT_END;
58939  }
58940  crc = drflac_crc8(crc, utf8[i], 8);
58941  result = (result << 6) | (utf8[i] & 0x3F);
58942  }
58943  *pNumberOut = result;
58944  *pCRCOut = crc;
58945  return DRFLAC_SUCCESS;
58946 }
58947 static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_32(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
58948 {
58949  drflac_int32 prediction = 0;
58950  DRFLAC_ASSERT(order <= 32);
58951  switch (order)
58952  {
58953  case 32: prediction += coefficients[31] * pDecodedSamples[-32];
58954  case 31: prediction += coefficients[30] * pDecodedSamples[-31];
58955  case 30: prediction += coefficients[29] * pDecodedSamples[-30];
58956  case 29: prediction += coefficients[28] * pDecodedSamples[-29];
58957  case 28: prediction += coefficients[27] * pDecodedSamples[-28];
58958  case 27: prediction += coefficients[26] * pDecodedSamples[-27];
58959  case 26: prediction += coefficients[25] * pDecodedSamples[-26];
58960  case 25: prediction += coefficients[24] * pDecodedSamples[-25];
58961  case 24: prediction += coefficients[23] * pDecodedSamples[-24];
58962  case 23: prediction += coefficients[22] * pDecodedSamples[-23];
58963  case 22: prediction += coefficients[21] * pDecodedSamples[-22];
58964  case 21: prediction += coefficients[20] * pDecodedSamples[-21];
58965  case 20: prediction += coefficients[19] * pDecodedSamples[-20];
58966  case 19: prediction += coefficients[18] * pDecodedSamples[-19];
58967  case 18: prediction += coefficients[17] * pDecodedSamples[-18];
58968  case 17: prediction += coefficients[16] * pDecodedSamples[-17];
58969  case 16: prediction += coefficients[15] * pDecodedSamples[-16];
58970  case 15: prediction += coefficients[14] * pDecodedSamples[-15];
58971  case 14: prediction += coefficients[13] * pDecodedSamples[-14];
58972  case 13: prediction += coefficients[12] * pDecodedSamples[-13];
58973  case 12: prediction += coefficients[11] * pDecodedSamples[-12];
58974  case 11: prediction += coefficients[10] * pDecodedSamples[-11];
58975  case 10: prediction += coefficients[ 9] * pDecodedSamples[-10];
58976  case 9: prediction += coefficients[ 8] * pDecodedSamples[- 9];
58977  case 8: prediction += coefficients[ 7] * pDecodedSamples[- 8];
58978  case 7: prediction += coefficients[ 6] * pDecodedSamples[- 7];
58979  case 6: prediction += coefficients[ 5] * pDecodedSamples[- 6];
58980  case 5: prediction += coefficients[ 4] * pDecodedSamples[- 5];
58981  case 4: prediction += coefficients[ 3] * pDecodedSamples[- 4];
58982  case 3: prediction += coefficients[ 2] * pDecodedSamples[- 3];
58983  case 2: prediction += coefficients[ 1] * pDecodedSamples[- 2];
58984  case 1: prediction += coefficients[ 0] * pDecodedSamples[- 1];
58985  }
58986  return (drflac_int32)(prediction >> shift);
58987 }
58988 static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_64(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
58989 {
58990  drflac_int64 prediction;
58991  DRFLAC_ASSERT(order <= 32);
58992 #ifndef DRFLAC_64BIT
58993  if (order == 8)
58994  {
58995  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
58996  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
58997  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
58998  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
58999  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59000  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59001  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
59002  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
59003  }
59004  else if (order == 7)
59005  {
59006  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59007  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59008  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59009  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59010  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59011  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59012  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
59013  }
59014  else if (order == 3)
59015  {
59016  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59017  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59018  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59019  }
59020  else if (order == 6)
59021  {
59022  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59023  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59024  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59025  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59026  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59027  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59028  }
59029  else if (order == 5)
59030  {
59031  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59032  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59033  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59034  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59035  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59036  }
59037  else if (order == 4)
59038  {
59039  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59040  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59041  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59042  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59043  }
59044  else if (order == 12)
59045  {
59046  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59047  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59048  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59049  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59050  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59051  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59052  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
59053  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
59054  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
59055  prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
59056  prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
59057  prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12];
59058  }
59059  else if (order == 2)
59060  {
59061  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59062  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59063  }
59064  else if (order == 1)
59065  {
59066  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59067  }
59068  else if (order == 10)
59069  {
59070  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59071  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59072  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59073  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59074  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59075  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59076  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
59077  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
59078  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
59079  prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
59080  }
59081  else if (order == 9)
59082  {
59083  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59084  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59085  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59086  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59087  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59088  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59089  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
59090  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
59091  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
59092  }
59093  else if (order == 11)
59094  {
59095  prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
59096  prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
59097  prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
59098  prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
59099  prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
59100  prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
59101  prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
59102  prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
59103  prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
59104  prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
59105  prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
59106  }
59107  else
59108  {
59109  int j;
59110  prediction = 0;
59111  for (j = 0; j < (int)order; ++j) {
59112  prediction += coefficients[j] * (drflac_int64)pDecodedSamples[-j-1];
59113  }
59114  }
59115 #endif
59116 #ifdef DRFLAC_64BIT
59117  prediction = 0;
59118  switch (order)
59119  {
59120  case 32: prediction += coefficients[31] * (drflac_int64)pDecodedSamples[-32];
59121  case 31: prediction += coefficients[30] * (drflac_int64)pDecodedSamples[-31];
59122  case 30: prediction += coefficients[29] * (drflac_int64)pDecodedSamples[-30];
59123  case 29: prediction += coefficients[28] * (drflac_int64)pDecodedSamples[-29];
59124  case 28: prediction += coefficients[27] * (drflac_int64)pDecodedSamples[-28];
59125  case 27: prediction += coefficients[26] * (drflac_int64)pDecodedSamples[-27];
59126  case 26: prediction += coefficients[25] * (drflac_int64)pDecodedSamples[-26];
59127  case 25: prediction += coefficients[24] * (drflac_int64)pDecodedSamples[-25];
59128  case 24: prediction += coefficients[23] * (drflac_int64)pDecodedSamples[-24];
59129  case 23: prediction += coefficients[22] * (drflac_int64)pDecodedSamples[-23];
59130  case 22: prediction += coefficients[21] * (drflac_int64)pDecodedSamples[-22];
59131  case 21: prediction += coefficients[20] * (drflac_int64)pDecodedSamples[-21];
59132  case 20: prediction += coefficients[19] * (drflac_int64)pDecodedSamples[-20];
59133  case 19: prediction += coefficients[18] * (drflac_int64)pDecodedSamples[-19];
59134  case 18: prediction += coefficients[17] * (drflac_int64)pDecodedSamples[-18];
59135  case 17: prediction += coefficients[16] * (drflac_int64)pDecodedSamples[-17];
59136  case 16: prediction += coefficients[15] * (drflac_int64)pDecodedSamples[-16];
59137  case 15: prediction += coefficients[14] * (drflac_int64)pDecodedSamples[-15];
59138  case 14: prediction += coefficients[13] * (drflac_int64)pDecodedSamples[-14];
59139  case 13: prediction += coefficients[12] * (drflac_int64)pDecodedSamples[-13];
59140  case 12: prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12];
59141  case 11: prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
59142  case 10: prediction += coefficients[ 9] * (drflac_int64)pDecodedSamples[-10];
59143  case 9: prediction += coefficients[ 8] * (drflac_int64)pDecodedSamples[- 9];
59144  case 8: prediction += coefficients[ 7] * (drflac_int64)pDecodedSamples[- 8];
59145  case 7: prediction += coefficients[ 6] * (drflac_int64)pDecodedSamples[- 7];
59146  case 6: prediction += coefficients[ 5] * (drflac_int64)pDecodedSamples[- 6];
59147  case 5: prediction += coefficients[ 4] * (drflac_int64)pDecodedSamples[- 5];
59148  case 4: prediction += coefficients[ 3] * (drflac_int64)pDecodedSamples[- 4];
59149  case 3: prediction += coefficients[ 2] * (drflac_int64)pDecodedSamples[- 3];
59150  case 2: prediction += coefficients[ 1] * (drflac_int64)pDecodedSamples[- 2];
59151  case 1: prediction += coefficients[ 0] * (drflac_int64)pDecodedSamples[- 1];
59152  }
59153 #endif
59154  return (drflac_int32)(prediction >> shift);
59155 }
59156 #if 0
59157 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)
59158 {
59159  drflac_uint32 i;
59160  DRFLAC_ASSERT(bs != NULL);
59161  DRFLAC_ASSERT(pSamplesOut != NULL);
59162  for (i = 0; i < count; ++i) {
59163  drflac_uint32 zeroCounter = 0;
59164  for (;;) {
59165  drflac_uint8 bit;
59166  if (!drflac__read_uint8(bs, 1, &bit)) {
59167  return DRFLAC_FALSE;
59168  }
59169  if (bit == 0) {
59170  zeroCounter += 1;
59171  } else {
59172  break;
59173  }
59174  }
59175  drflac_uint32 decodedRice;
59176  if (riceParam > 0) {
59177  if (!drflac__read_uint32(bs, riceParam, &decodedRice)) {
59178  return DRFLAC_FALSE;
59179  }
59180  } else {
59181  decodedRice = 0;
59182  }
59183  decodedRice |= (zeroCounter << riceParam);
59184  if ((decodedRice & 0x01)) {
59185  decodedRice = ~(decodedRice >> 1);
59186  } else {
59187  decodedRice = (decodedRice >> 1);
59188  }
59189  if (bitsPerSample+shift >= 32) {
59190  pSamplesOut[i] = decodedRice + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
59191  } else {
59192  pSamplesOut[i] = decodedRice + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i);
59193  }
59194  }
59195  return DRFLAC_TRUE;
59196 }
59197 #endif
59198 #if 0
59199 static drflac_bool32 drflac__read_rice_parts__reference(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
59200 {
59201  drflac_uint32 zeroCounter = 0;
59202  drflac_uint32 decodedRice;
59203  for (;;) {
59204  drflac_uint8 bit;
59205  if (!drflac__read_uint8(bs, 1, &bit)) {
59206  return DRFLAC_FALSE;
59207  }
59208  if (bit == 0) {
59209  zeroCounter += 1;
59210  } else {
59211  break;
59212  }
59213  }
59214  if (riceParam > 0) {
59215  if (!drflac__read_uint32(bs, riceParam, &decodedRice)) {
59216  return DRFLAC_FALSE;
59217  }
59218  } else {
59219  decodedRice = 0;
59220  }
59221  *pZeroCounterOut = zeroCounter;
59222  *pRiceParamPartOut = decodedRice;
59223  return DRFLAC_TRUE;
59224 }
59225 #endif
59226 #if 0
59227 static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
59228 {
59229  drflac_cache_t riceParamMask;
59230  drflac_uint32 zeroCounter;
59231  drflac_uint32 setBitOffsetPlus1;
59232  drflac_uint32 riceParamPart;
59233  drflac_uint32 riceLength;
59234  DRFLAC_ASSERT(riceParam > 0);
59235  riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam);
59236  zeroCounter = 0;
59237  while (bs->cache == 0) {
59238  zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
59239  if (!drflac__reload_cache(bs)) {
59240  return DRFLAC_FALSE;
59241  }
59242  }
59243  setBitOffsetPlus1 = drflac__clz(bs->cache);
59244  zeroCounter += setBitOffsetPlus1;
59245  setBitOffsetPlus1 += 1;
59246  riceLength = setBitOffsetPlus1 + riceParam;
59247  if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
59248  riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceLength));
59249  bs->consumedBits += riceLength;
59250  bs->cache <<= riceLength;
59251  } else {
59252  drflac_uint32 bitCountLo;
59253  drflac_cache_t resultHi;
59254  bs->consumedBits += riceLength;
59255  bs->cache <<= setBitOffsetPlus1 & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1);
59256  bitCountLo = bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs);
59257  resultHi = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, riceParam);
59258  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
59259 #ifndef DR_FLAC_NO_CRC
59261 #endif
59263  bs->consumedBits = 0;
59264 #ifndef DR_FLAC_NO_CRC
59265  bs->crc16Cache = bs->cache;
59266 #endif
59267  } else {
59268  if (!drflac__reload_cache(bs)) {
59269  return DRFLAC_FALSE;
59270  }
59271  }
59272  riceParamPart = (drflac_uint32)(resultHi | DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, bitCountLo));
59273  bs->consumedBits += bitCountLo;
59274  bs->cache <<= bitCountLo;
59275  }
59276  pZeroCounterOut[0] = zeroCounter;
59277  pRiceParamPartOut[0] = riceParamPart;
59278  return DRFLAC_TRUE;
59279 }
59280 #endif
59281 static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts_x1(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
59282 {
59283  drflac_uint32 riceParamPlus1 = riceParam + 1;
59284  drflac_uint32 riceParamPlus1Shift = DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceParamPlus1);
59285  drflac_uint32 riceParamPlus1MaxConsumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParamPlus1;
59286  drflac_cache_t bs_cache = bs->cache;
59287  drflac_uint32 bs_consumedBits = bs->consumedBits;
59288  drflac_uint32 lzcount = drflac__clz(bs_cache);
59289  if (lzcount < sizeof(bs_cache)*8) {
59290  pZeroCounterOut[0] = lzcount;
59291  extract_rice_param_part:
59292  bs_cache <<= lzcount;
59293  bs_consumedBits += lzcount;
59294  if (bs_consumedBits <= riceParamPlus1MaxConsumedBits) {
59295  pRiceParamPartOut[0] = (drflac_uint32)(bs_cache >> riceParamPlus1Shift);
59296  bs_cache <<= riceParamPlus1;
59297  bs_consumedBits += riceParamPlus1;
59298  } else {
59299  drflac_uint32 riceParamPartHi;
59300  drflac_uint32 riceParamPartLo;
59301  drflac_uint32 riceParamPartLoBitCount;
59302  riceParamPartHi = (drflac_uint32)(bs_cache >> riceParamPlus1Shift);
59303  riceParamPartLoBitCount = bs_consumedBits - riceParamPlus1MaxConsumedBits;
59304  DRFLAC_ASSERT(riceParamPartLoBitCount > 0 && riceParamPartLoBitCount < 32);
59305  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
59306  #ifndef DR_FLAC_NO_CRC
59308  #endif
59309  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
59310  bs_consumedBits = riceParamPartLoBitCount;
59311  #ifndef DR_FLAC_NO_CRC
59312  bs->crc16Cache = bs_cache;
59313  #endif
59314  } else {
59315  if (!drflac__reload_cache(bs)) {
59316  return DRFLAC_FALSE;
59317  }
59318  bs_cache = bs->cache;
59319  bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
59320  }
59321  riceParamPartLo = (drflac_uint32)(bs_cache >> (DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceParamPartLoBitCount)));
59322  pRiceParamPartOut[0] = riceParamPartHi | riceParamPartLo;
59323  bs_cache <<= riceParamPartLoBitCount;
59324  }
59325  } else {
59326  drflac_uint32 zeroCounter = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BITS(bs) - bs_consumedBits);
59327  for (;;) {
59328  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
59329  #ifndef DR_FLAC_NO_CRC
59331  #endif
59332  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
59333  bs_consumedBits = 0;
59334  #ifndef DR_FLAC_NO_CRC
59335  bs->crc16Cache = bs_cache;
59336  #endif
59337  } else {
59338  if (!drflac__reload_cache(bs)) {
59339  return DRFLAC_FALSE;
59340  }
59341  bs_cache = bs->cache;
59342  bs_consumedBits = bs->consumedBits;
59343  }
59344  lzcount = drflac__clz(bs_cache);
59345  zeroCounter += lzcount;
59346  if (lzcount < sizeof(bs_cache)*8) {
59347  break;
59348  }
59349  }
59350  pZeroCounterOut[0] = zeroCounter;
59351  goto extract_rice_param_part;
59352  }
59353  bs->cache = bs_cache;
59354  bs->consumedBits = bs_consumedBits;
59355  return DRFLAC_TRUE;
59356 }
59358 {
59359  drflac_uint32 riceParamPlus1 = riceParam + 1;
59360  drflac_uint32 riceParamPlus1MaxConsumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParamPlus1;
59361  drflac_cache_t bs_cache = bs->cache;
59362  drflac_uint32 bs_consumedBits = bs->consumedBits;
59363  drflac_uint32 lzcount = drflac__clz(bs_cache);
59364  if (lzcount < sizeof(bs_cache)*8) {
59365  extract_rice_param_part:
59366  bs_cache <<= lzcount;
59367  bs_consumedBits += lzcount;
59368  if (bs_consumedBits <= riceParamPlus1MaxConsumedBits) {
59369  bs_cache <<= riceParamPlus1;
59370  bs_consumedBits += riceParamPlus1;
59371  } else {
59372  drflac_uint32 riceParamPartLoBitCount = bs_consumedBits - riceParamPlus1MaxConsumedBits;
59373  DRFLAC_ASSERT(riceParamPartLoBitCount > 0 && riceParamPartLoBitCount < 32);
59374  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
59375  #ifndef DR_FLAC_NO_CRC
59377  #endif
59378  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
59379  bs_consumedBits = riceParamPartLoBitCount;
59380  #ifndef DR_FLAC_NO_CRC
59381  bs->crc16Cache = bs_cache;
59382  #endif
59383  } else {
59384  if (!drflac__reload_cache(bs)) {
59385  return DRFLAC_FALSE;
59386  }
59387  bs_cache = bs->cache;
59388  bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
59389  }
59390  bs_cache <<= riceParamPartLoBitCount;
59391  }
59392  } else {
59393  for (;;) {
59394  if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
59395  #ifndef DR_FLAC_NO_CRC
59397  #endif
59398  bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
59399  bs_consumedBits = 0;
59400  #ifndef DR_FLAC_NO_CRC
59401  bs->crc16Cache = bs_cache;
59402  #endif
59403  } else {
59404  if (!drflac__reload_cache(bs)) {
59405  return DRFLAC_FALSE;
59406  }
59407  bs_cache = bs->cache;
59408  bs_consumedBits = bs->consumedBits;
59409  }
59410  lzcount = drflac__clz(bs_cache);
59411  if (lzcount < sizeof(bs_cache)*8) {
59412  break;
59413  }
59414  }
59415  goto extract_rice_param_part;
59416  }
59417  bs->cache = bs_cache;
59418  bs->consumedBits = bs_consumedBits;
59419  return DRFLAC_TRUE;
59420 }
59422 {
59423  drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
59424  drflac_uint32 zeroCountPart0;
59425  drflac_uint32 riceParamPart0;
59426  drflac_uint32 riceParamMask;
59427  drflac_uint32 i;
59428  DRFLAC_ASSERT(bs != NULL);
59429  DRFLAC_ASSERT(pSamplesOut != NULL);
59430  (void)bitsPerSample;
59431  (void)order;
59432  (void)shift;
59433  (void)coefficients;
59434  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
59435  i = 0;
59436  while (i < count) {
59437  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0)) {
59438  return DRFLAC_FALSE;
59439  }
59440  riceParamPart0 &= riceParamMask;
59441  riceParamPart0 |= (zeroCountPart0 << riceParam);
59442  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
59443  pSamplesOut[i] = riceParamPart0;
59444  i += 1;
59445  }
59446  return DRFLAC_TRUE;
59447 }
59449 {
59450  drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
59451  drflac_uint32 zeroCountPart0 = 0;
59452  drflac_uint32 zeroCountPart1 = 0;
59453  drflac_uint32 zeroCountPart2 = 0;
59454  drflac_uint32 zeroCountPart3 = 0;
59455  drflac_uint32 riceParamPart0 = 0;
59456  drflac_uint32 riceParamPart1 = 0;
59457  drflac_uint32 riceParamPart2 = 0;
59458  drflac_uint32 riceParamPart3 = 0;
59459  drflac_uint32 riceParamMask;
59460  const drflac_int32* pSamplesOutEnd;
59461  drflac_uint32 i;
59462  DRFLAC_ASSERT(bs != NULL);
59463  DRFLAC_ASSERT(pSamplesOut != NULL);
59464  if (order == 0) {
59465  return drflac__decode_samples_with_residual__rice__scalar_zeroorder(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
59466  }
59467  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
59468  pSamplesOutEnd = pSamplesOut + (count & ~3);
59469  if (bitsPerSample+shift > 32) {
59470  while (pSamplesOut < pSamplesOutEnd) {
59471  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0) ||
59472  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart1, &riceParamPart1) ||
59473  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart2, &riceParamPart2) ||
59474  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart3, &riceParamPart3)) {
59475  return DRFLAC_FALSE;
59476  }
59477  riceParamPart0 &= riceParamMask;
59478  riceParamPart1 &= riceParamMask;
59479  riceParamPart2 &= riceParamMask;
59480  riceParamPart3 &= riceParamMask;
59481  riceParamPart0 |= (zeroCountPart0 << riceParam);
59482  riceParamPart1 |= (zeroCountPart1 << riceParam);
59483  riceParamPart2 |= (zeroCountPart2 << riceParam);
59484  riceParamPart3 |= (zeroCountPart3 << riceParam);
59485  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
59486  riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
59487  riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
59488  riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
59489  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
59490  pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 1);
59491  pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 2);
59492  pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 3);
59493  pSamplesOut += 4;
59494  }
59495  } else {
59496  while (pSamplesOut < pSamplesOutEnd) {
59497  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0) ||
59498  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart1, &riceParamPart1) ||
59499  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart2, &riceParamPart2) ||
59500  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart3, &riceParamPart3)) {
59501  return DRFLAC_FALSE;
59502  }
59503  riceParamPart0 &= riceParamMask;
59504  riceParamPart1 &= riceParamMask;
59505  riceParamPart2 &= riceParamMask;
59506  riceParamPart3 &= riceParamMask;
59507  riceParamPart0 |= (zeroCountPart0 << riceParam);
59508  riceParamPart1 |= (zeroCountPart1 << riceParam);
59509  riceParamPart2 |= (zeroCountPart2 << riceParam);
59510  riceParamPart3 |= (zeroCountPart3 << riceParam);
59511  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
59512  riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
59513  riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
59514  riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
59515  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
59516  pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 1);
59517  pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 2);
59518  pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 3);
59519  pSamplesOut += 4;
59520  }
59521  }
59522  i = (count & ~3);
59523  while (i < count) {
59524  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0)) {
59525  return DRFLAC_FALSE;
59526  }
59527  riceParamPart0 &= riceParamMask;
59528  riceParamPart0 |= (zeroCountPart0 << riceParam);
59529  riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
59530  if (bitsPerSample+shift > 32) {
59531  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
59532  } else {
59533  pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
59534  }
59535  i += 1;
59536  pSamplesOut += 1;
59537  }
59538  return DRFLAC_TRUE;
59539 }
59540 #if defined(DRFLAC_SUPPORT_SSE2)
59541 static DRFLAC_INLINE __m128i drflac__mm_packs_interleaved_epi32(__m128i a, __m128i b)
59542 {
59543  __m128i r;
59544  r = _mm_packs_epi32(a, b);
59545  r = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 1, 2, 0));
59546  r = _mm_shufflehi_epi16(r, _MM_SHUFFLE(3, 1, 2, 0));
59547  r = _mm_shufflelo_epi16(r, _MM_SHUFFLE(3, 1, 2, 0));
59548  return r;
59549 }
59550 #endif
59551 #if defined(DRFLAC_SUPPORT_SSE41)
59552 static DRFLAC_INLINE __m128i drflac__mm_not_si128(__m128i a)
59553 {
59554  return _mm_xor_si128(a, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
59555 }
59556 static DRFLAC_INLINE __m128i drflac__mm_hadd_epi32(__m128i x)
59557 {
59558  __m128i x64 = _mm_add_epi32(x, _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)));
59559  __m128i x32 = _mm_shufflelo_epi16(x64, _MM_SHUFFLE(1, 0, 3, 2));
59560  return _mm_add_epi32(x64, x32);
59561 }
59562 static DRFLAC_INLINE __m128i drflac__mm_hadd_epi64(__m128i x)
59563 {
59564  return _mm_add_epi64(x, _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)));
59565 }
59566 static DRFLAC_INLINE __m128i drflac__mm_srai_epi64(__m128i x, int count)
59567 {
59568  __m128i lo = _mm_srli_epi64(x, count);
59569  __m128i hi = _mm_srai_epi32(x, count);
59570  hi = _mm_and_si128(hi, _mm_set_epi32(0xFFFFFFFF, 0, 0xFFFFFFFF, 0));
59571  return _mm_or_si128(lo, hi);
59572 }
59573 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)
59574 {
59575  int i;
59576  drflac_uint32 riceParamMask;
59577  drflac_int32* pDecodedSamples = pSamplesOut;
59578  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
59579  drflac_uint32 zeroCountParts0 = 0;
59580  drflac_uint32 zeroCountParts1 = 0;
59581  drflac_uint32 zeroCountParts2 = 0;
59582  drflac_uint32 zeroCountParts3 = 0;
59583  drflac_uint32 riceParamParts0 = 0;
59584  drflac_uint32 riceParamParts1 = 0;
59585  drflac_uint32 riceParamParts2 = 0;
59586  drflac_uint32 riceParamParts3 = 0;
59587  __m128i coefficients128_0;
59588  __m128i coefficients128_4;
59589  __m128i coefficients128_8;
59590  __m128i samples128_0;
59591  __m128i samples128_4;
59592  __m128i samples128_8;
59593  __m128i riceParamMask128;
59594  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
59595  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
59596  riceParamMask128 = _mm_set1_epi32(riceParamMask);
59597  coefficients128_0 = _mm_setzero_si128();
59598  coefficients128_4 = _mm_setzero_si128();
59599  coefficients128_8 = _mm_setzero_si128();
59600  samples128_0 = _mm_setzero_si128();
59601  samples128_4 = _mm_setzero_si128();
59602  samples128_8 = _mm_setzero_si128();
59603 #if 1
59604  {
59605  int runningOrder = order;
59606  if (runningOrder >= 4) {
59607  coefficients128_0 = _mm_loadu_si128((const __m128i*)(coefficients + 0));
59608  samples128_0 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 4));
59609  runningOrder -= 4;
59610  } else {
59611  switch (runningOrder) {
59612  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;
59613  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;
59614  case 1: coefficients128_0 = _mm_set_epi32(0, 0, 0, coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], 0, 0, 0); break;
59615  }
59616  runningOrder = 0;
59617  }
59618  if (runningOrder >= 4) {
59619  coefficients128_4 = _mm_loadu_si128((const __m128i*)(coefficients + 4));
59620  samples128_4 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 8));
59621  runningOrder -= 4;
59622  } else {
59623  switch (runningOrder) {
59624  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;
59625  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;
59626  case 1: coefficients128_4 = _mm_set_epi32(0, 0, 0, coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], 0, 0, 0); break;
59627  }
59628  runningOrder = 0;
59629  }
59630  if (runningOrder == 4) {
59631  coefficients128_8 = _mm_loadu_si128((const __m128i*)(coefficients + 8));
59632  samples128_8 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 12));
59633  runningOrder -= 4;
59634  } else {
59635  switch (runningOrder) {
59636  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;
59637  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;
59638  case 1: coefficients128_8 = _mm_set_epi32(0, 0, 0, coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], 0, 0, 0); break;
59639  }
59640  runningOrder = 0;
59641  }
59642  coefficients128_0 = _mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(0, 1, 2, 3));
59643  coefficients128_4 = _mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(0, 1, 2, 3));
59644  coefficients128_8 = _mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(0, 1, 2, 3));
59645  }
59646 #else
59647  switch (order)
59648  {
59649  case 12: ((drflac_int32*)&coefficients128_8)[0] = coefficients[11]; ((drflac_int32*)&samples128_8)[0] = pDecodedSamples[-12];
59650  case 11: ((drflac_int32*)&coefficients128_8)[1] = coefficients[10]; ((drflac_int32*)&samples128_8)[1] = pDecodedSamples[-11];
59651  case 10: ((drflac_int32*)&coefficients128_8)[2] = coefficients[ 9]; ((drflac_int32*)&samples128_8)[2] = pDecodedSamples[-10];
59652  case 9: ((drflac_int32*)&coefficients128_8)[3] = coefficients[ 8]; ((drflac_int32*)&samples128_8)[3] = pDecodedSamples[- 9];
59653  case 8: ((drflac_int32*)&coefficients128_4)[0] = coefficients[ 7]; ((drflac_int32*)&samples128_4)[0] = pDecodedSamples[- 8];
59654  case 7: ((drflac_int32*)&coefficients128_4)[1] = coefficients[ 6]; ((drflac_int32*)&samples128_4)[1] = pDecodedSamples[- 7];
59655  case 6: ((drflac_int32*)&coefficients128_4)[2] = coefficients[ 5]; ((drflac_int32*)&samples128_4)[2] = pDecodedSamples[- 6];
59656  case 5: ((drflac_int32*)&coefficients128_4)[3] = coefficients[ 4]; ((drflac_int32*)&samples128_4)[3] = pDecodedSamples[- 5];
59657  case 4: ((drflac_int32*)&coefficients128_0)[0] = coefficients[ 3]; ((drflac_int32*)&samples128_0)[0] = pDecodedSamples[- 4];
59658  case 3: ((drflac_int32*)&coefficients128_0)[1] = coefficients[ 2]; ((drflac_int32*)&samples128_0)[1] = pDecodedSamples[- 3];
59659  case 2: ((drflac_int32*)&coefficients128_0)[2] = coefficients[ 1]; ((drflac_int32*)&samples128_0)[2] = pDecodedSamples[- 2];
59660  case 1: ((drflac_int32*)&coefficients128_0)[3] = coefficients[ 0]; ((drflac_int32*)&samples128_0)[3] = pDecodedSamples[- 1];
59661  }
59662 #endif
59663  while (pDecodedSamples < pDecodedSamplesEnd) {
59664  __m128i prediction128;
59665  __m128i zeroCountPart128;
59666  __m128i riceParamPart128;
59667  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0) ||
59668  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts1, &riceParamParts1) ||
59669  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts2, &riceParamParts2) ||
59670  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts3, &riceParamParts3)) {
59671  return DRFLAC_FALSE;
59672  }
59673  zeroCountPart128 = _mm_set_epi32(zeroCountParts3, zeroCountParts2, zeroCountParts1, zeroCountParts0);
59674  riceParamPart128 = _mm_set_epi32(riceParamParts3, riceParamParts2, riceParamParts1, riceParamParts0);
59675  riceParamPart128 = _mm_and_si128(riceParamPart128, riceParamMask128);
59676  riceParamPart128 = _mm_or_si128(riceParamPart128, _mm_slli_epi32(zeroCountPart128, riceParam));
59677  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)));
59678  if (order <= 4) {
59679  for (i = 0; i < 4; i += 1) {
59680  prediction128 = _mm_mullo_epi32(coefficients128_0, samples128_0);
59681  prediction128 = drflac__mm_hadd_epi32(prediction128);
59682  prediction128 = _mm_srai_epi32(prediction128, shift);
59683  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
59684  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
59685  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
59686  }
59687  } else if (order <= 8) {
59688  for (i = 0; i < 4; i += 1) {
59689  prediction128 = _mm_mullo_epi32(coefficients128_4, samples128_4);
59690  prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_0, samples128_0));
59691  prediction128 = drflac__mm_hadd_epi32(prediction128);
59692  prediction128 = _mm_srai_epi32(prediction128, shift);
59693  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
59694  samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
59695  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
59696  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
59697  }
59698  } else {
59699  for (i = 0; i < 4; i += 1) {
59700  prediction128 = _mm_mullo_epi32(coefficients128_8, samples128_8);
59701  prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_4, samples128_4));
59702  prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_0, samples128_0));
59703  prediction128 = drflac__mm_hadd_epi32(prediction128);
59704  prediction128 = _mm_srai_epi32(prediction128, shift);
59705  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
59706  samples128_8 = _mm_alignr_epi8(samples128_4, samples128_8, 4);
59707  samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
59708  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
59709  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
59710  }
59711  }
59712  _mm_storeu_si128((__m128i*)pDecodedSamples, samples128_0);
59713  pDecodedSamples += 4;
59714  }
59715  i = (count & ~3);
59716  while (i < (int)count) {
59717  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0)) {
59718  return DRFLAC_FALSE;
59719  }
59720  riceParamParts0 &= riceParamMask;
59721  riceParamParts0 |= (zeroCountParts0 << riceParam);
59722  riceParamParts0 = (riceParamParts0 >> 1) ^ t[riceParamParts0 & 0x01];
59723  pDecodedSamples[0] = riceParamParts0 + drflac__calculate_prediction_32(order, shift, coefficients, pDecodedSamples);
59724  i += 1;
59725  pDecodedSamples += 1;
59726  }
59727  return DRFLAC_TRUE;
59728 }
59729 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)
59730 {
59731  int i;
59732  drflac_uint32 riceParamMask;
59733  drflac_int32* pDecodedSamples = pSamplesOut;
59734  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
59735  drflac_uint32 zeroCountParts0 = 0;
59736  drflac_uint32 zeroCountParts1 = 0;
59737  drflac_uint32 zeroCountParts2 = 0;
59738  drflac_uint32 zeroCountParts3 = 0;
59739  drflac_uint32 riceParamParts0 = 0;
59740  drflac_uint32 riceParamParts1 = 0;
59741  drflac_uint32 riceParamParts2 = 0;
59742  drflac_uint32 riceParamParts3 = 0;
59743  __m128i coefficients128_0;
59744  __m128i coefficients128_4;
59745  __m128i coefficients128_8;
59746  __m128i samples128_0;
59747  __m128i samples128_4;
59748  __m128i samples128_8;
59749  __m128i prediction128;
59750  __m128i riceParamMask128;
59751  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
59752  DRFLAC_ASSERT(order <= 12);
59753  riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
59754  riceParamMask128 = _mm_set1_epi32(riceParamMask);
59755  prediction128 = _mm_setzero_si128();
59756  coefficients128_0 = _mm_setzero_si128();
59757  coefficients128_4 = _mm_setzero_si128();
59758  coefficients128_8 = _mm_setzero_si128();
59759  samples128_0 = _mm_setzero_si128();
59760  samples128_4 = _mm_setzero_si128();
59761  samples128_8 = _mm_setzero_si128();
59762 #if 1
59763  {
59764  int runningOrder = order;
59765  if (runningOrder >= 4) {
59766  coefficients128_0 = _mm_loadu_si128((const __m128i*)(coefficients + 0));
59767  samples128_0 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 4));
59768  runningOrder -= 4;
59769  } else {
59770  switch (runningOrder) {
59771  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;
59772  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;
59773  case 1: coefficients128_0 = _mm_set_epi32(0, 0, 0, coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], 0, 0, 0); break;
59774  }
59775  runningOrder = 0;
59776  }
59777  if (runningOrder >= 4) {
59778  coefficients128_4 = _mm_loadu_si128((const __m128i*)(coefficients + 4));
59779  samples128_4 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 8));
59780  runningOrder -= 4;
59781  } else {
59782  switch (runningOrder) {
59783  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;
59784  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;
59785  case 1: coefficients128_4 = _mm_set_epi32(0, 0, 0, coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], 0, 0, 0); break;
59786  }
59787  runningOrder = 0;
59788  }
59789  if (runningOrder == 4) {
59790  coefficients128_8 = _mm_loadu_si128((const __m128i*)(coefficients + 8));
59791  samples128_8 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 12));
59792  runningOrder -= 4;
59793  } else {
59794  switch (runningOrder) {
59795  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;
59796  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;
59797  case 1: coefficients128_8 = _mm_set_epi32(0, 0, 0, coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], 0, 0, 0); break;
59798  }
59799  runningOrder = 0;
59800  }
59801  coefficients128_0 = _mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(0, 1, 2, 3));
59802  coefficients128_4 = _mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(0, 1, 2, 3));
59803  coefficients128_8 = _mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(0, 1, 2, 3));
59804  }
59805 #else
59806  switch (order)
59807  {
59808  case 12: ((drflac_int32*)&coefficients128_8)[0] = coefficients[11]; ((drflac_int32*)&samples128_8)[0] = pDecodedSamples[-12];
59809  case 11: ((drflac_int32*)&coefficients128_8)[1] = coefficients[10]; ((drflac_int32*)&samples128_8)[1] = pDecodedSamples[-11];
59810  case 10: ((drflac_int32*)&coefficients128_8)[2] = coefficients[ 9]; ((drflac_int32*)&samples128_8)[2] = pDecodedSamples[-10];
59811  case 9: ((drflac_int32*)&coefficients128_8)[3] = coefficients[ 8]; ((drflac_int32*)&samples128_8)[3] = pDecodedSamples[- 9];
59812  case 8: ((drflac_int32*)&coefficients128_4)[0] = coefficients[ 7]; ((drflac_int32*)&samples128_4)[0] = pDecodedSamples[- 8];
59813  case 7: ((drflac_int32*)&coefficients128_4)[1] = coefficients[ 6]; ((drflac_int32*)&samples128_4)[1] = pDecodedSamples[- 7];
59814  case 6: ((drflac_int32*)&coefficients128_4)[2] = coefficients[ 5]; ((drflac_int32*)&samples128_4)[2] = pDecodedSamples[- 6];
59815  case 5: ((drflac_int32*)&coefficients128_4)[3] = coefficients[ 4]; ((drflac_int32*)&samples128_4)[3] = pDecodedSamples[- 5];
59816  case 4: ((drflac_int32*)&coefficients128_0)[0] = coefficients[ 3]; ((drflac_int32*)&samples128_0)[0] = pDecodedSamples[- 4];
59817  case 3: ((drflac_int32*)&coefficients128_0)[1] = coefficients[ 2]; ((drflac_int32*)&samples128_0)[1] = pDecodedSamples[- 3];
59818  case 2: ((drflac_int32*)&coefficients128_0)[2] = coefficients[ 1]; ((drflac_int32*)&samples128_0)[2] = pDecodedSamples[- 2];
59819  case 1: ((drflac_int32*)&coefficients128_0)[3] = coefficients[ 0]; ((drflac_int32*)&samples128_0)[3] = pDecodedSamples[- 1];
59820  }
59821 #endif
59822  while (pDecodedSamples < pDecodedSamplesEnd) {
59823  __m128i zeroCountPart128;
59824  __m128i riceParamPart128;
59825  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0) ||
59826  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts1, &riceParamParts1) ||
59827  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts2, &riceParamParts2) ||
59828  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts3, &riceParamParts3)) {
59829  return DRFLAC_FALSE;
59830  }
59831  zeroCountPart128 = _mm_set_epi32(zeroCountParts3, zeroCountParts2, zeroCountParts1, zeroCountParts0);
59832  riceParamPart128 = _mm_set_epi32(riceParamParts3, riceParamParts2, riceParamParts1, riceParamParts0);
59833  riceParamPart128 = _mm_and_si128(riceParamPart128, riceParamMask128);
59834  riceParamPart128 = _mm_or_si128(riceParamPart128, _mm_slli_epi32(zeroCountPart128, riceParam));
59835  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)));
59836  for (i = 0; i < 4; i += 1) {
59837  prediction128 = _mm_xor_si128(prediction128, prediction128);
59838  switch (order)
59839  {
59840  case 12:
59841  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))));
59842  case 10:
59843  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))));
59844  case 8:
59845  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))));
59846  case 6:
59847  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))));
59848  case 4:
59849  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))));
59850  case 2:
59851  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))));
59852  }
59853  prediction128 = drflac__mm_hadd_epi64(prediction128);
59854  prediction128 = drflac__mm_srai_epi64(prediction128, shift);
59855  prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
59856  samples128_8 = _mm_alignr_epi8(samples128_4, samples128_8, 4);
59857  samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
59858  samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
59859  riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
59860  }
59861  _mm_storeu_si128((__m128i*)pDecodedSamples, samples128_0);
59862  pDecodedSamples += 4;
59863  }
59864  i = (count & ~3);
59865  while (i < (int)count) {
59866  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0)) {
59867  return DRFLAC_FALSE;
59868  }
59869  riceParamParts0 &= riceParamMask;
59870  riceParamParts0 |= (zeroCountParts0 << riceParam);
59871  riceParamParts0 = (riceParamParts0 >> 1) ^ t[riceParamParts0 & 0x01];
59872  pDecodedSamples[0] = riceParamParts0 + drflac__calculate_prediction_64(order, shift, coefficients, pDecodedSamples);
59873  i += 1;
59874  pDecodedSamples += 1;
59875  }
59876  return DRFLAC_TRUE;
59877 }
59878 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)
59879 {
59880  DRFLAC_ASSERT(bs != NULL);
59881  DRFLAC_ASSERT(pSamplesOut != NULL);
59882  if (order > 0 && order <= 12) {
59883  if (bitsPerSample+shift > 32) {
59884  return drflac__decode_samples_with_residual__rice__sse41_64(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
59885  } else {
59886  return drflac__decode_samples_with_residual__rice__sse41_32(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
59887  }
59888  } else {
59889  return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
59890  }
59891 }
59892 #endif
59893 #if defined(DRFLAC_SUPPORT_NEON)
59894 static DRFLAC_INLINE void drflac__vst2q_s32(drflac_int32* p, int32x4x2_t x)
59895 {
59896  vst1q_s32(p+0, x.val[0]);
59897  vst1q_s32(p+4, x.val[1]);
59898 }
59899 static DRFLAC_INLINE void drflac__vst2q_u32(drflac_uint32* p, uint32x4x2_t x)
59900 {
59901  vst1q_u32(p+0, x.val[0]);
59902  vst1q_u32(p+4, x.val[1]);
59903 }
59904 static DRFLAC_INLINE void drflac__vst2q_f32(float* p, float32x4x2_t x)
59905 {
59906  vst1q_f32(p+0, x.val[0]);
59907  vst1q_f32(p+4, x.val[1]);
59908 }
59909 static DRFLAC_INLINE void drflac__vst2q_s16(drflac_int16* p, int16x4x2_t x)
59910 {
59911  vst1q_s16(p, vcombine_s16(x.val[0], x.val[1]));
59912 }
59913 static DRFLAC_INLINE void drflac__vst2q_u16(drflac_uint16* p, uint16x4x2_t x)
59914 {
59915  vst1q_u16(p, vcombine_u16(x.val[0], x.val[1]));
59916 }
59917 static DRFLAC_INLINE int32x4_t drflac__vdupq_n_s32x4(drflac_int32 x3, drflac_int32 x2, drflac_int32 x1, drflac_int32 x0)
59918 {
59919  drflac_int32 x[4];
59920  x[3] = x3;
59921  x[2] = x2;
59922  x[1] = x1;
59923  x[0] = x0;
59924  return vld1q_s32(x);
59925 }
59926 static DRFLAC_INLINE int32x4_t drflac__valignrq_s32_1(int32x4_t a, int32x4_t b)
59927 {
59928  return vextq_s32(b, a, 1);
59929 }
59930 static DRFLAC_INLINE uint32x4_t drflac__valignrq_u32_1(uint32x4_t a, uint32x4_t b)
59931 {
59932  return vextq_u32(b, a, 1);
59933 }
59934 static DRFLAC_INLINE int32x2_t drflac__vhaddq_s32(int32x4_t x)
59935 {
59936  int32x2_t r = vadd_s32(vget_high_s32(x), vget_low_s32(x));
59937  return vpadd_s32(r, r);
59938 }
59939 static DRFLAC_INLINE int64x1_t drflac__vhaddq_s64(int64x2_t x)
59940 {
59941  return vadd_s64(vget_high_s64(x), vget_low_s64(x));
59942 }
59943 static DRFLAC_INLINE int32x4_t drflac__vrevq_s32(int32x4_t x)
59944 {
59945  return vrev64q_s32(vcombine_s32(vget_high_s32(x), vget_low_s32(x)));
59946 }
59947 static DRFLAC_INLINE int32x4_t drflac__vnotq_s32(int32x4_t x)
59948 {
59949  return veorq_s32(x, vdupq_n_s32(0xFFFFFFFF));
59950 }
59951 static DRFLAC_INLINE uint32x4_t drflac__vnotq_u32(uint32x4_t x)
59952 {
59953  return veorq_u32(x, vdupq_n_u32(0xFFFFFFFF));
59954 }
59955 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)
59956 {
59957  int i;
59958  drflac_uint32 riceParamMask;
59959  drflac_int32* pDecodedSamples = pSamplesOut;
59960  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
59961  drflac_uint32 zeroCountParts[4];
59962  drflac_uint32 riceParamParts[4];
59963  int32x4_t coefficients128_0;
59964  int32x4_t coefficients128_4;
59965  int32x4_t coefficients128_8;
59966  int32x4_t samples128_0;
59967  int32x4_t samples128_4;
59968  int32x4_t samples128_8;
59969  uint32x4_t riceParamMask128;
59970  int32x4_t riceParam128;
59971  int32x2_t shift64;
59972  uint32x4_t one128;
59973  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
59974  riceParamMask = ~((~0UL) << riceParam);
59975  riceParamMask128 = vdupq_n_u32(riceParamMask);
59976  riceParam128 = vdupq_n_s32(riceParam);
59977  shift64 = vdup_n_s32(-shift);
59978  one128 = vdupq_n_u32(1);
59979  {
59980  int runningOrder = order;
59981  drflac_int32 tempC[4] = {0, 0, 0, 0};
59982  drflac_int32 tempS[4] = {0, 0, 0, 0};
59983  if (runningOrder >= 4) {
59984  coefficients128_0 = vld1q_s32(coefficients + 0);
59985  samples128_0 = vld1q_s32(pSamplesOut - 4);
59986  runningOrder -= 4;
59987  } else {
59988  switch (runningOrder) {
59989  case 3: tempC[2] = coefficients[2]; tempS[1] = pSamplesOut[-3];
59990  case 2: tempC[1] = coefficients[1]; tempS[2] = pSamplesOut[-2];
59991  case 1: tempC[0] = coefficients[0]; tempS[3] = pSamplesOut[-1];
59992  }
59993  coefficients128_0 = vld1q_s32(tempC);
59994  samples128_0 = vld1q_s32(tempS);
59995  runningOrder = 0;
59996  }
59997  if (runningOrder >= 4) {
59998  coefficients128_4 = vld1q_s32(coefficients + 4);
59999  samples128_4 = vld1q_s32(pSamplesOut - 8);
60000  runningOrder -= 4;
60001  } else {
60002  switch (runningOrder) {
60003  case 3: tempC[2] = coefficients[6]; tempS[1] = pSamplesOut[-7];
60004  case 2: tempC[1] = coefficients[5]; tempS[2] = pSamplesOut[-6];
60005  case 1: tempC[0] = coefficients[4]; tempS[3] = pSamplesOut[-5];
60006  }
60007  coefficients128_4 = vld1q_s32(tempC);
60008  samples128_4 = vld1q_s32(tempS);
60009  runningOrder = 0;
60010  }
60011  if (runningOrder == 4) {
60012  coefficients128_8 = vld1q_s32(coefficients + 8);
60013  samples128_8 = vld1q_s32(pSamplesOut - 12);
60014  runningOrder -= 4;
60015  } else {
60016  switch (runningOrder) {
60017  case 3: tempC[2] = coefficients[10]; tempS[1] = pSamplesOut[-11];
60018  case 2: tempC[1] = coefficients[ 9]; tempS[2] = pSamplesOut[-10];
60019  case 1: tempC[0] = coefficients[ 8]; tempS[3] = pSamplesOut[- 9];
60020  }
60021  coefficients128_8 = vld1q_s32(tempC);
60022  samples128_8 = vld1q_s32(tempS);
60023  runningOrder = 0;
60024  }
60025  coefficients128_0 = drflac__vrevq_s32(coefficients128_0);
60026  coefficients128_4 = drflac__vrevq_s32(coefficients128_4);
60027  coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
60028  }
60029  while (pDecodedSamples < pDecodedSamplesEnd) {
60030  int32x4_t prediction128;
60031  int32x2_t prediction64;
60032  uint32x4_t zeroCountPart128;
60033  uint32x4_t riceParamPart128;
60034  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
60035  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
60036  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
60037  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
60038  return DRFLAC_FALSE;
60039  }
60040  zeroCountPart128 = vld1q_u32(zeroCountParts);
60041  riceParamPart128 = vld1q_u32(riceParamParts);
60042  riceParamPart128 = vandq_u32(riceParamPart128, riceParamMask128);
60043  riceParamPart128 = vorrq_u32(riceParamPart128, vshlq_u32(zeroCountPart128, riceParam128));
60044  riceParamPart128 = veorq_u32(vshrq_n_u32(riceParamPart128, 1), vaddq_u32(drflac__vnotq_u32(vandq_u32(riceParamPart128, one128)), one128));
60045  if (order <= 4) {
60046  for (i = 0; i < 4; i += 1) {
60047  prediction128 = vmulq_s32(coefficients128_0, samples128_0);
60048  prediction64 = drflac__vhaddq_s32(prediction128);
60049  prediction64 = vshl_s32(prediction64, shift64);
60050  prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
60051  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
60052  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
60053  }
60054  } else if (order <= 8) {
60055  for (i = 0; i < 4; i += 1) {
60056  prediction128 = vmulq_s32(coefficients128_4, samples128_4);
60057  prediction128 = vmlaq_s32(prediction128, coefficients128_0, samples128_0);
60058  prediction64 = drflac__vhaddq_s32(prediction128);
60059  prediction64 = vshl_s32(prediction64, shift64);
60060  prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
60061  samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
60062  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
60063  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
60064  }
60065  } else {
60066  for (i = 0; i < 4; i += 1) {
60067  prediction128 = vmulq_s32(coefficients128_8, samples128_8);
60068  prediction128 = vmlaq_s32(prediction128, coefficients128_4, samples128_4);
60069  prediction128 = vmlaq_s32(prediction128, coefficients128_0, samples128_0);
60070  prediction64 = drflac__vhaddq_s32(prediction128);
60071  prediction64 = vshl_s32(prediction64, shift64);
60072  prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
60073  samples128_8 = drflac__valignrq_s32_1(samples128_4, samples128_8);
60074  samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
60075  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
60076  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
60077  }
60078  }
60079  vst1q_s32(pDecodedSamples, samples128_0);
60080  pDecodedSamples += 4;
60081  }
60082  i = (count & ~3);
60083  while (i < (int)count) {
60084  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0])) {
60085  return DRFLAC_FALSE;
60086  }
60087  riceParamParts[0] &= riceParamMask;
60088  riceParamParts[0] |= (zeroCountParts[0] << riceParam);
60089  riceParamParts[0] = (riceParamParts[0] >> 1) ^ t[riceParamParts[0] & 0x01];
60090  pDecodedSamples[0] = riceParamParts[0] + drflac__calculate_prediction_32(order, shift, coefficients, pDecodedSamples);
60091  i += 1;
60092  pDecodedSamples += 1;
60093  }
60094  return DRFLAC_TRUE;
60095 }
60096 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)
60097 {
60098  int i;
60099  drflac_uint32 riceParamMask;
60100  drflac_int32* pDecodedSamples = pSamplesOut;
60101  drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
60102  drflac_uint32 zeroCountParts[4];
60103  drflac_uint32 riceParamParts[4];
60104  int32x4_t coefficients128_0;
60105  int32x4_t coefficients128_4;
60106  int32x4_t coefficients128_8;
60107  int32x4_t samples128_0;
60108  int32x4_t samples128_4;
60109  int32x4_t samples128_8;
60110  uint32x4_t riceParamMask128;
60111  int32x4_t riceParam128;
60112  int64x1_t shift64;
60113  uint32x4_t one128;
60114  const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
60115  riceParamMask = ~((~0UL) << riceParam);
60116  riceParamMask128 = vdupq_n_u32(riceParamMask);
60117  riceParam128 = vdupq_n_s32(riceParam);
60118  shift64 = vdup_n_s64(-shift);
60119  one128 = vdupq_n_u32(1);
60120  {
60121  int runningOrder = order;
60122  drflac_int32 tempC[4] = {0, 0, 0, 0};
60123  drflac_int32 tempS[4] = {0, 0, 0, 0};
60124  if (runningOrder >= 4) {
60125  coefficients128_0 = vld1q_s32(coefficients + 0);
60126  samples128_0 = vld1q_s32(pSamplesOut - 4);
60127  runningOrder -= 4;
60128  } else {
60129  switch (runningOrder) {
60130  case 3: tempC[2] = coefficients[2]; tempS[1] = pSamplesOut[-3];
60131  case 2: tempC[1] = coefficients[1]; tempS[2] = pSamplesOut[-2];
60132  case 1: tempC[0] = coefficients[0]; tempS[3] = pSamplesOut[-1];
60133  }
60134  coefficients128_0 = vld1q_s32(tempC);
60135  samples128_0 = vld1q_s32(tempS);
60136  runningOrder = 0;
60137  }
60138  if (runningOrder >= 4) {
60139  coefficients128_4 = vld1q_s32(coefficients + 4);
60140  samples128_4 = vld1q_s32(pSamplesOut - 8);
60141  runningOrder -= 4;
60142  } else {
60143  switch (runningOrder) {
60144  case 3: tempC[2] = coefficients[6]; tempS[1] = pSamplesOut[-7];
60145  case 2: tempC[1] = coefficients[5]; tempS[2] = pSamplesOut[-6];
60146  case 1: tempC[0] = coefficients[4]; tempS[3] = pSamplesOut[-5];
60147  }
60148  coefficients128_4 = vld1q_s32(tempC);
60149  samples128_4 = vld1q_s32(tempS);
60150  runningOrder = 0;
60151  }
60152  if (runningOrder == 4) {
60153  coefficients128_8 = vld1q_s32(coefficients + 8);
60154  samples128_8 = vld1q_s32(pSamplesOut - 12);
60155  runningOrder -= 4;
60156  } else {
60157  switch (runningOrder) {
60158  case 3: tempC[2] = coefficients[10]; tempS[1] = pSamplesOut[-11];
60159  case 2: tempC[1] = coefficients[ 9]; tempS[2] = pSamplesOut[-10];
60160  case 1: tempC[0] = coefficients[ 8]; tempS[3] = pSamplesOut[- 9];
60161  }
60162  coefficients128_8 = vld1q_s32(tempC);
60163  samples128_8 = vld1q_s32(tempS);
60164  runningOrder = 0;
60165  }
60166  coefficients128_0 = drflac__vrevq_s32(coefficients128_0);
60167  coefficients128_4 = drflac__vrevq_s32(coefficients128_4);
60168  coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
60169  }
60170  while (pDecodedSamples < pDecodedSamplesEnd) {
60171  int64x2_t prediction128;
60172  uint32x4_t zeroCountPart128;
60173  uint32x4_t riceParamPart128;
60174  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
60175  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
60176  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
60177  !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
60178  return DRFLAC_FALSE;
60179  }
60180  zeroCountPart128 = vld1q_u32(zeroCountParts);
60181  riceParamPart128 = vld1q_u32(riceParamParts);
60182  riceParamPart128 = vandq_u32(riceParamPart128, riceParamMask128);
60183  riceParamPart128 = vorrq_u32(riceParamPart128, vshlq_u32(zeroCountPart128, riceParam128));
60184  riceParamPart128 = veorq_u32(vshrq_n_u32(riceParamPart128, 1), vaddq_u32(drflac__vnotq_u32(vandq_u32(riceParamPart128, one128)), one128));
60185  for (i = 0; i < 4; i += 1) {
60186  int64x1_t prediction64;
60187  prediction128 = veorq_s64(prediction128, prediction128);
60188  switch (order)
60189  {
60190  case 12:
60191  case 11: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_8), vget_low_s32(samples128_8)));
60192  case 10:
60193  case 9: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_8), vget_high_s32(samples128_8)));
60194  case 8:
60195  case 7: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_4), vget_low_s32(samples128_4)));
60196  case 6:
60197  case 5: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_4), vget_high_s32(samples128_4)));
60198  case 4:
60199  case 3: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_0), vget_low_s32(samples128_0)));
60200  case 2:
60201  case 1: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_0), vget_high_s32(samples128_0)));
60202  }
60203  prediction64 = drflac__vhaddq_s64(prediction128);
60204  prediction64 = vshl_s64(prediction64, shift64);
60205  prediction64 = vadd_s64(prediction64, vdup_n_s64(vgetq_lane_u32(riceParamPart128, 0)));
60206  samples128_8 = drflac__valignrq_s32_1(samples128_4, samples128_8);
60207  samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
60208  samples128_0 = drflac__valignrq_s32_1(vcombine_s32(vreinterpret_s32_s64(prediction64), vdup_n_s32(0)), samples128_0);
60209  riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
60210  }
60211  vst1q_s32(pDecodedSamples, samples128_0);
60212  pDecodedSamples += 4;
60213  }
60214  i = (count & ~3);
60215  while (i < (int)count) {
60216  if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0])) {
60217  return DRFLAC_FALSE;
60218  }
60219  riceParamParts[0] &= riceParamMask;
60220  riceParamParts[0] |= (zeroCountParts[0] << riceParam);
60221  riceParamParts[0] = (riceParamParts[0] >> 1) ^ t[riceParamParts[0] & 0x01];
60222  pDecodedSamples[0] = riceParamParts[0] + drflac__calculate_prediction_64(order, shift, coefficients, pDecodedSamples);
60223  i += 1;
60224  pDecodedSamples += 1;
60225  }
60226  return DRFLAC_TRUE;
60227 }
60228 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)
60229 {
60230  DRFLAC_ASSERT(bs != NULL);
60231  DRFLAC_ASSERT(pSamplesOut != NULL);
60232  if (order > 0 && order <= 12) {
60233  if (bitsPerSample+shift > 32) {
60234  return drflac__decode_samples_with_residual__rice__neon_64(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
60235  } else {
60236  return drflac__decode_samples_with_residual__rice__neon_32(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
60237  }
60238  } else {
60239  return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
60240  }
60241 }
60242 #endif
60243 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)
60244 {
60245 #if defined(DRFLAC_SUPPORT_SSE41)
60246  if (drflac__gIsSSE41Supported) {
60247  return drflac__decode_samples_with_residual__rice__sse41(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
60248  } else
60249 #elif defined(DRFLAC_SUPPORT_NEON)
60251  return drflac__decode_samples_with_residual__rice__neon(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
60252  } else
60253 #endif
60254  {
60255  #if 0
60256  return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
60257  #else
60258  return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
60259  #endif
60260  }
60261 }
60263 {
60264  drflac_uint32 i;
60265  DRFLAC_ASSERT(bs != NULL);
60266  for (i = 0; i < count; ++i) {
60267  if (!drflac__seek_rice_parts(bs, riceParam)) {
60268  return DRFLAC_FALSE;
60269  }
60270  }
60271  return DRFLAC_TRUE;
60272 }
60273 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)
60274 {
60275  drflac_uint32 i;
60276  DRFLAC_ASSERT(bs != NULL);
60277  DRFLAC_ASSERT(unencodedBitsPerSample <= 31);
60278  DRFLAC_ASSERT(pSamplesOut != NULL);
60279  for (i = 0; i < count; ++i) {
60280  if (unencodedBitsPerSample > 0) {
60281  if (!drflac__read_int32(bs, unencodedBitsPerSample, pSamplesOut + i)) {
60282  return DRFLAC_FALSE;
60283  }
60284  } else {
60285  pSamplesOut[i] = 0;
60286  }
60287  if (bitsPerSample >= 24) {
60288  pSamplesOut[i] += drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
60289  } else {
60290  pSamplesOut[i] += drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i);
60291  }
60292  }
60293  return DRFLAC_TRUE;
60294 }
60295 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)
60296 {
60297  drflac_uint8 residualMethod;
60298  drflac_uint8 partitionOrder;
60299  drflac_uint32 samplesInPartition;
60300  drflac_uint32 partitionsRemaining;
60301  DRFLAC_ASSERT(bs != NULL);
60302  DRFLAC_ASSERT(blockSize != 0);
60303  DRFLAC_ASSERT(pDecodedSamples != NULL);
60304  if (!drflac__read_uint8(bs, 2, &residualMethod)) {
60305  return DRFLAC_FALSE;
60306  }
60308  return DRFLAC_FALSE;
60309  }
60310  pDecodedSamples += order;
60311  if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
60312  return DRFLAC_FALSE;
60313  }
60314  if (partitionOrder > 8) {
60315  return DRFLAC_FALSE;
60316  }
60317  if ((blockSize / (1 << partitionOrder)) < order) {
60318  return DRFLAC_FALSE;
60319  }
60320  samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
60321  partitionsRemaining = (1 << partitionOrder);
60322  for (;;) {
60323  drflac_uint8 riceParam = 0;
60324  if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) {
60325  if (!drflac__read_uint8(bs, 4, &riceParam)) {
60326  return DRFLAC_FALSE;
60327  }
60328  if (riceParam == 15) {
60329  riceParam = 0xFF;
60330  }
60331  } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
60332  if (!drflac__read_uint8(bs, 5, &riceParam)) {
60333  return DRFLAC_FALSE;
60334  }
60335  if (riceParam == 31) {
60336  riceParam = 0xFF;
60337  }
60338  }
60339  if (riceParam != 0xFF) {
60340  if (!drflac__decode_samples_with_residual__rice(bs, bitsPerSample, samplesInPartition, riceParam, order, shift, coefficients, pDecodedSamples)) {
60341  return DRFLAC_FALSE;
60342  }
60343  } else {
60344  drflac_uint8 unencodedBitsPerSample = 0;
60345  if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) {
60346  return DRFLAC_FALSE;
60347  }
60348  if (!drflac__decode_samples_with_residual__unencoded(bs, bitsPerSample, samplesInPartition, unencodedBitsPerSample, order, shift, coefficients, pDecodedSamples)) {
60349  return DRFLAC_FALSE;
60350  }
60351  }
60352  pDecodedSamples += samplesInPartition;
60353  if (partitionsRemaining == 1) {
60354  break;
60355  }
60356  partitionsRemaining -= 1;
60357  if (partitionOrder != 0) {
60358  samplesInPartition = blockSize / (1 << partitionOrder);
60359  }
60360  }
60361  return DRFLAC_TRUE;
60362 }
60364 {
60365  drflac_uint8 residualMethod;
60366  drflac_uint8 partitionOrder;
60367  drflac_uint32 samplesInPartition;
60368  drflac_uint32 partitionsRemaining;
60369  DRFLAC_ASSERT(bs != NULL);
60370  DRFLAC_ASSERT(blockSize != 0);
60371  if (!drflac__read_uint8(bs, 2, &residualMethod)) {
60372  return DRFLAC_FALSE;
60373  }
60375  return DRFLAC_FALSE;
60376  }
60377  if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
60378  return DRFLAC_FALSE;
60379  }
60380  if (partitionOrder > 8) {
60381  return DRFLAC_FALSE;
60382  }
60383  if ((blockSize / (1 << partitionOrder)) <= order) {
60384  return DRFLAC_FALSE;
60385  }
60386  samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
60387  partitionsRemaining = (1 << partitionOrder);
60388  for (;;)
60389  {
60390  drflac_uint8 riceParam = 0;
60391  if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) {
60392  if (!drflac__read_uint8(bs, 4, &riceParam)) {
60393  return DRFLAC_FALSE;
60394  }
60395  if (riceParam == 15) {
60396  riceParam = 0xFF;
60397  }
60398  } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
60399  if (!drflac__read_uint8(bs, 5, &riceParam)) {
60400  return DRFLAC_FALSE;
60401  }
60402  if (riceParam == 31) {
60403  riceParam = 0xFF;
60404  }
60405  }
60406  if (riceParam != 0xFF) {
60407  if (!drflac__read_and_seek_residual__rice(bs, samplesInPartition, riceParam)) {
60408  return DRFLAC_FALSE;
60409  }
60410  } else {
60411  drflac_uint8 unencodedBitsPerSample = 0;
60412  if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) {
60413  return DRFLAC_FALSE;
60414  }
60415  if (!drflac__seek_bits(bs, unencodedBitsPerSample * samplesInPartition)) {
60416  return DRFLAC_FALSE;
60417  }
60418  }
60419  if (partitionsRemaining == 1) {
60420  break;
60421  }
60422  partitionsRemaining -= 1;
60423  samplesInPartition = blockSize / (1 << partitionOrder);
60424  }
60425  return DRFLAC_TRUE;
60426 }
60427 static drflac_bool32 drflac__decode_samples__constant(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32* pDecodedSamples)
60428 {
60429  drflac_uint32 i;
60430  drflac_int32 sample;
60431  if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
60432  return DRFLAC_FALSE;
60433  }
60434  for (i = 0; i < blockSize; ++i) {
60435  pDecodedSamples[i] = sample;
60436  }
60437  return DRFLAC_TRUE;
60438 }
60439 static drflac_bool32 drflac__decode_samples__verbatim(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32* pDecodedSamples)
60440 {
60441  drflac_uint32 i;
60442  for (i = 0; i < blockSize; ++i) {
60443  drflac_int32 sample;
60444  if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
60445  return DRFLAC_FALSE;
60446  }
60447  pDecodedSamples[i] = sample;
60448  }
60449  return DRFLAC_TRUE;
60450 }
60451 static drflac_bool32 drflac__decode_samples__fixed(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples)
60452 {
60453  drflac_uint32 i;
60454  static drflac_int32 lpcCoefficientsTable[5][4] = {
60455  {0, 0, 0, 0},
60456  {1, 0, 0, 0},
60457  {2, -1, 0, 0},
60458  {3, -3, 1, 0},
60459  {4, -6, 4, -1}
60460  };
60461  for (i = 0; i < lpcOrder; ++i) {
60462  drflac_int32 sample;
60463  if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
60464  return DRFLAC_FALSE;
60465  }
60466  pDecodedSamples[i] = sample;
60467  }
60468  if (!drflac__decode_samples_with_residual(bs, subframeBitsPerSample, blockSize, lpcOrder, 0, lpcCoefficientsTable[lpcOrder], pDecodedSamples)) {
60469  return DRFLAC_FALSE;
60470  }
60471  return DRFLAC_TRUE;
60472 }
60473 static drflac_bool32 drflac__decode_samples__lpc(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples)
60474 {
60475  drflac_uint8 i;
60476  drflac_uint8 lpcPrecision;
60477  drflac_int8 lpcShift;
60478  drflac_int32 coefficients[32];
60479  for (i = 0; i < lpcOrder; ++i) {
60480  drflac_int32 sample;
60481  if (!drflac__read_int32(bs, bitsPerSample, &sample)) {
60482  return DRFLAC_FALSE;
60483  }
60484  pDecodedSamples[i] = sample;
60485  }
60486  if (!drflac__read_uint8(bs, 4, &lpcPrecision)) {
60487  return DRFLAC_FALSE;
60488  }
60489  if (lpcPrecision == 15) {
60490  return DRFLAC_FALSE;
60491  }
60492  lpcPrecision += 1;
60493  if (!drflac__read_int8(bs, 5, &lpcShift)) {
60494  return DRFLAC_FALSE;
60495  }
60496  if (lpcShift < 0) {
60497  return DRFLAC_FALSE;
60498  }
60499  DRFLAC_ZERO_MEMORY(coefficients, sizeof(coefficients));
60500  for (i = 0; i < lpcOrder; ++i) {
60501  if (!drflac__read_int32(bs, lpcPrecision, coefficients + i)) {
60502  return DRFLAC_FALSE;
60503  }
60504  }
60505  if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, lpcShift, coefficients, pDecodedSamples)) {
60506  return DRFLAC_FALSE;
60507  }
60508  return DRFLAC_TRUE;
60509 }
60511 {
60512  const drflac_uint32 sampleRateTable[12] = {0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
60513  const drflac_uint8 bitsPerSampleTable[8] = {0, 8, 12, (drflac_uint8)-1, 16, 20, 24, (drflac_uint8)-1};
60514  DRFLAC_ASSERT(bs != NULL);
60515  DRFLAC_ASSERT(header != NULL);
60516  for (;;) {
60517  drflac_uint8 crc8 = 0xCE;
60518  drflac_uint8 reserved = 0;
60519  drflac_uint8 blockingStrategy = 0;
60520  drflac_uint8 blockSize = 0;
60521  drflac_uint8 sampleRate = 0;
60522  drflac_uint8 channelAssignment = 0;
60523  drflac_uint8 bitsPerSample = 0;
60524  drflac_bool32 isVariableBlockSize;
60526  return DRFLAC_FALSE;
60527  }
60528  if (!drflac__read_uint8(bs, 1, &reserved)) {
60529  return DRFLAC_FALSE;
60530  }
60531  if (reserved == 1) {
60532  continue;
60533  }
60534  crc8 = drflac_crc8(crc8, reserved, 1);
60535  if (!drflac__read_uint8(bs, 1, &blockingStrategy)) {
60536  return DRFLAC_FALSE;
60537  }
60538  crc8 = drflac_crc8(crc8, blockingStrategy, 1);
60539  if (!drflac__read_uint8(bs, 4, &blockSize)) {
60540  return DRFLAC_FALSE;
60541  }
60542  if (blockSize == 0) {
60543  continue;
60544  }
60545  crc8 = drflac_crc8(crc8, blockSize, 4);
60546  if (!drflac__read_uint8(bs, 4, &sampleRate)) {
60547  return DRFLAC_FALSE;
60548  }
60549  crc8 = drflac_crc8(crc8, sampleRate, 4);
60550  if (!drflac__read_uint8(bs, 4, &channelAssignment)) {
60551  return DRFLAC_FALSE;
60552  }
60553  if (channelAssignment > 10) {
60554  continue;
60555  }
60556  crc8 = drflac_crc8(crc8, channelAssignment, 4);
60557  if (!drflac__read_uint8(bs, 3, &bitsPerSample)) {
60558  return DRFLAC_FALSE;
60559  }
60560  if (bitsPerSample == 3 || bitsPerSample == 7) {
60561  continue;
60562  }
60563  crc8 = drflac_crc8(crc8, bitsPerSample, 3);
60564  if (!drflac__read_uint8(bs, 1, &reserved)) {
60565  return DRFLAC_FALSE;
60566  }
60567  if (reserved == 1) {
60568  continue;
60569  }
60570  crc8 = drflac_crc8(crc8, reserved, 1);
60571  isVariableBlockSize = blockingStrategy == 1;
60572  if (isVariableBlockSize) {
60573  drflac_uint64 pcmFrameNumber;
60574  drflac_result result = drflac__read_utf8_coded_number(bs, &pcmFrameNumber, &crc8);
60575  if (result != DRFLAC_SUCCESS) {
60576  if (result == DRFLAC_AT_END) {
60577  return DRFLAC_FALSE;
60578  } else {
60579  continue;
60580  }
60581  }
60582  header->flacFrameNumber = 0;
60583  header->pcmFrameNumber = pcmFrameNumber;
60584  } else {
60585  drflac_uint64 flacFrameNumber = 0;
60586  drflac_result result = drflac__read_utf8_coded_number(bs, &flacFrameNumber, &crc8);
60587  if (result != DRFLAC_SUCCESS) {
60588  if (result == DRFLAC_AT_END) {
60589  return DRFLAC_FALSE;
60590  } else {
60591  continue;
60592  }
60593  }
60594  header->flacFrameNumber = (drflac_uint32)flacFrameNumber;
60595  header->pcmFrameNumber = 0;
60596  }
60597  DRFLAC_ASSERT(blockSize > 0);
60598  if (blockSize == 1) {
60599  header->blockSizeInPCMFrames = 192;
60600  } else if (blockSize <= 5) {
60601  DRFLAC_ASSERT(blockSize >= 2);
60602  header->blockSizeInPCMFrames = 576 * (1 << (blockSize - 2));
60603  } else if (blockSize == 6) {
60604  if (!drflac__read_uint16(bs, 8, &header->blockSizeInPCMFrames)) {
60605  return DRFLAC_FALSE;
60606  }
60607  crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 8);
60608  header->blockSizeInPCMFrames += 1;
60609  } else if (blockSize == 7) {
60610  if (!drflac__read_uint16(bs, 16, &header->blockSizeInPCMFrames)) {
60611  return DRFLAC_FALSE;
60612  }
60613  crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 16);
60614  header->blockSizeInPCMFrames += 1;
60615  } else {
60616  DRFLAC_ASSERT(blockSize >= 8);
60617  header->blockSizeInPCMFrames = 256 * (1 << (blockSize - 8));
60618  }
60619  if (sampleRate <= 11) {
60620  header->sampleRate = sampleRateTable[sampleRate];
60621  } else if (sampleRate == 12) {
60622  if (!drflac__read_uint32(bs, 8, &header->sampleRate)) {
60623  return DRFLAC_FALSE;
60624  }
60625  crc8 = drflac_crc8(crc8, header->sampleRate, 8);
60626  header->sampleRate *= 1000;
60627  } else if (sampleRate == 13) {
60628  if (!drflac__read_uint32(bs, 16, &header->sampleRate)) {
60629  return DRFLAC_FALSE;
60630  }
60631  crc8 = drflac_crc8(crc8, header->sampleRate, 16);
60632  } else if (sampleRate == 14) {
60633  if (!drflac__read_uint32(bs, 16, &header->sampleRate)) {
60634  return DRFLAC_FALSE;
60635  }
60636  crc8 = drflac_crc8(crc8, header->sampleRate, 16);
60637  header->sampleRate *= 10;
60638  } else {
60639  continue;
60640  }
60641  header->channelAssignment = channelAssignment;
60642  header->bitsPerSample = bitsPerSampleTable[bitsPerSample];
60643  if (header->bitsPerSample == 0) {
60644  header->bitsPerSample = streaminfoBitsPerSample;
60645  }
60646  if (!drflac__read_uint8(bs, 8, &header->crc8)) {
60647  return DRFLAC_FALSE;
60648  }
60649 #ifndef DR_FLAC_NO_CRC
60650  if (header->crc8 != crc8) {
60651  continue;
60652  }
60653 #endif
60654  return DRFLAC_TRUE;
60655  }
60656 }
60658 {
60660  int type;
60661  if (!drflac__read_uint8(bs, 8, &header)) {
60662  return DRFLAC_FALSE;
60663  }
60664  if ((header & 0x80) != 0) {
60665  return DRFLAC_FALSE;
60666  }
60667  type = (header & 0x7E) >> 1;
60668  if (type == 0) {
60670  } else if (type == 1) {
60672  } else {
60673  if ((type & 0x20) != 0) {
60674  pSubframe->subframeType = DRFLAC_SUBFRAME_LPC;
60675  pSubframe->lpcOrder = (drflac_uint8)(type & 0x1F) + 1;
60676  } else if ((type & 0x08) != 0) {
60677  pSubframe->subframeType = DRFLAC_SUBFRAME_FIXED;
60678  pSubframe->lpcOrder = (drflac_uint8)(type & 0x07);
60679  if (pSubframe->lpcOrder > 4) {
60681  pSubframe->lpcOrder = 0;
60682  }
60683  } else {
60685  }
60686  }
60687  if (pSubframe->subframeType == DRFLAC_SUBFRAME_RESERVED) {
60688  return DRFLAC_FALSE;
60689  }
60690  pSubframe->wastedBitsPerSample = 0;
60691  if ((header & 0x01) == 1) {
60692  unsigned int wastedBitsPerSample;
60693  if (!drflac__seek_past_next_set_bit(bs, &wastedBitsPerSample)) {
60694  return DRFLAC_FALSE;
60695  }
60696  pSubframe->wastedBitsPerSample = (drflac_uint8)wastedBitsPerSample + 1;
60697  }
60698  return DRFLAC_TRUE;
60699 }
60700 static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex, drflac_int32* pDecodedSamplesOut)
60701 {
60702  drflac_subframe* pSubframe;
60703  drflac_uint32 subframeBitsPerSample;
60704  DRFLAC_ASSERT(bs != NULL);
60705  DRFLAC_ASSERT(frame != NULL);
60706  pSubframe = frame->subframes + subframeIndex;
60707  if (!drflac__read_subframe_header(bs, pSubframe)) {
60708  return DRFLAC_FALSE;
60709  }
60710  subframeBitsPerSample = frame->header.bitsPerSample;
60712  subframeBitsPerSample += 1;
60713  } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) {
60714  subframeBitsPerSample += 1;
60715  }
60716  if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
60717  return DRFLAC_FALSE;
60718  }
60719  subframeBitsPerSample -= pSubframe->wastedBitsPerSample;
60720  pSubframe->pSamplesS32 = pDecodedSamplesOut;
60721  switch (pSubframe->subframeType)
60722  {
60724  {
60725  drflac__decode_samples__constant(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
60726  } break;
60728  {
60729  drflac__decode_samples__verbatim(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
60730  } break;
60731  case DRFLAC_SUBFRAME_FIXED:
60732  {
60733  drflac__decode_samples__fixed(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
60734  } break;
60735  case DRFLAC_SUBFRAME_LPC:
60736  {
60737  drflac__decode_samples__lpc(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
60738  } break;
60739  default: return DRFLAC_FALSE;
60740  }
60741  return DRFLAC_TRUE;
60742 }
60743 static drflac_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex)
60744 {
60745  drflac_subframe* pSubframe;
60746  drflac_uint32 subframeBitsPerSample;
60747  DRFLAC_ASSERT(bs != NULL);
60748  DRFLAC_ASSERT(frame != NULL);
60749  pSubframe = frame->subframes + subframeIndex;
60750  if (!drflac__read_subframe_header(bs, pSubframe)) {
60751  return DRFLAC_FALSE;
60752  }
60753  subframeBitsPerSample = frame->header.bitsPerSample;
60755  subframeBitsPerSample += 1;
60756  } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) {
60757  subframeBitsPerSample += 1;
60758  }
60759  if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
60760  return DRFLAC_FALSE;
60761  }
60762  subframeBitsPerSample -= pSubframe->wastedBitsPerSample;
60763  pSubframe->pSamplesS32 = NULL;
60764  switch (pSubframe->subframeType)
60765  {
60767  {
60768  if (!drflac__seek_bits(bs, subframeBitsPerSample)) {
60769  return DRFLAC_FALSE;
60770  }
60771  } break;
60773  {
60774  unsigned int bitsToSeek = frame->header.blockSizeInPCMFrames * subframeBitsPerSample;
60775  if (!drflac__seek_bits(bs, bitsToSeek)) {
60776  return DRFLAC_FALSE;
60777  }
60778  } break;
60779  case DRFLAC_SUBFRAME_FIXED:
60780  {
60781  unsigned int bitsToSeek = pSubframe->lpcOrder * subframeBitsPerSample;
60782  if (!drflac__seek_bits(bs, bitsToSeek)) {
60783  return DRFLAC_FALSE;
60784  }
60785  if (!drflac__read_and_seek_residual(bs, frame->header.blockSizeInPCMFrames, pSubframe->lpcOrder)) {
60786  return DRFLAC_FALSE;
60787  }
60788  } break;
60789  case DRFLAC_SUBFRAME_LPC:
60790  {
60791  drflac_uint8 lpcPrecision;
60792  unsigned int bitsToSeek = pSubframe->lpcOrder * subframeBitsPerSample;
60793  if (!drflac__seek_bits(bs, bitsToSeek)) {
60794  return DRFLAC_FALSE;
60795  }
60796  if (!drflac__read_uint8(bs, 4, &lpcPrecision)) {
60797  return DRFLAC_FALSE;
60798  }
60799  if (lpcPrecision == 15) {
60800  return DRFLAC_FALSE;
60801  }
60802  lpcPrecision += 1;
60803  bitsToSeek = (pSubframe->lpcOrder * lpcPrecision) + 5;
60804  if (!drflac__seek_bits(bs, bitsToSeek)) {
60805  return DRFLAC_FALSE;
60806  }
60807  if (!drflac__read_and_seek_residual(bs, frame->header.blockSizeInPCMFrames, pSubframe->lpcOrder)) {
60808  return DRFLAC_FALSE;
60809  }
60810  } break;
60811  default: return DRFLAC_FALSE;
60812  }
60813  return DRFLAC_TRUE;
60814 }
60816 {
60817  drflac_uint8 lookup[] = {1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2};
60818  DRFLAC_ASSERT(channelAssignment <= 10);
60819  return lookup[channelAssignment];
60820 }
60822 {
60823  int channelCount;
60824  int i;
60825  drflac_uint8 paddingSizeInBits;
60826  drflac_uint16 desiredCRC16;
60827 #ifndef DR_FLAC_NO_CRC
60828  drflac_uint16 actualCRC16;
60829 #endif
60832  return DRFLAC_ERROR;
60833  }
60835  if (channelCount != (int)pFlac->channels) {
60836  return DRFLAC_ERROR;
60837  }
60838  for (i = 0; i < channelCount; ++i) {
60839  if (!drflac__decode_subframe(&pFlac->bs, &pFlac->currentFLACFrame, i, pFlac->pDecodedSamples + (pFlac->currentFLACFrame.header.blockSizeInPCMFrames * i))) {
60840  return DRFLAC_ERROR;
60841  }
60842  }
60843  paddingSizeInBits = (drflac_uint8)(DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7);
60844  if (paddingSizeInBits > 0) {
60845  drflac_uint8 padding = 0;
60846  if (!drflac__read_uint8(&pFlac->bs, paddingSizeInBits, &padding)) {
60847  return DRFLAC_AT_END;
60848  }
60849  }
60850 #ifndef DR_FLAC_NO_CRC
60851  actualCRC16 = drflac__flush_crc16(&pFlac->bs);
60852 #endif
60853  if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) {
60854  return DRFLAC_AT_END;
60855  }
60856 #ifndef DR_FLAC_NO_CRC
60857  if (actualCRC16 != desiredCRC16) {
60858  return DRFLAC_CRC_MISMATCH;
60859  }
60860 #endif
60862  return DRFLAC_SUCCESS;
60863 }
60865 {
60866  int channelCount;
60867  int i;
60868  drflac_uint16 desiredCRC16;
60869 #ifndef DR_FLAC_NO_CRC
60870  drflac_uint16 actualCRC16;
60871 #endif
60873  for (i = 0; i < channelCount; ++i) {
60874  if (!drflac__seek_subframe(&pFlac->bs, &pFlac->currentFLACFrame, i)) {
60875  return DRFLAC_ERROR;
60876  }
60877  }
60878  if (!drflac__seek_bits(&pFlac->bs, DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7)) {
60879  return DRFLAC_ERROR;
60880  }
60881 #ifndef DR_FLAC_NO_CRC
60882  actualCRC16 = drflac__flush_crc16(&pFlac->bs);
60883 #endif
60884  if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) {
60885  return DRFLAC_AT_END;
60886  }
60887 #ifndef DR_FLAC_NO_CRC
60888  if (actualCRC16 != desiredCRC16) {
60889  return DRFLAC_CRC_MISMATCH;
60890  }
60891 #endif
60892  return DRFLAC_SUCCESS;
60893 }
60895 {
60896  DRFLAC_ASSERT(pFlac != NULL);
60897  for (;;) {
60898  drflac_result result;
60900  return DRFLAC_FALSE;
60901  }
60902  result = drflac__decode_flac_frame(pFlac);
60903  if (result != DRFLAC_SUCCESS) {
60904  if (result == DRFLAC_CRC_MISMATCH) {
60905  continue;
60906  } else {
60907  return DRFLAC_FALSE;
60908  }
60909  }
60910  return DRFLAC_TRUE;
60911  }
60912 }
60913 static void drflac__get_pcm_frame_range_of_current_flac_frame(drflac* pFlac, drflac_uint64* pFirstPCMFrame, drflac_uint64* pLastPCMFrame)
60914 {
60915  drflac_uint64 firstPCMFrame;
60916  drflac_uint64 lastPCMFrame;
60917  DRFLAC_ASSERT(pFlac != NULL);
60918  firstPCMFrame = pFlac->currentFLACFrame.header.pcmFrameNumber;
60919  if (firstPCMFrame == 0) {
60921  }
60922  lastPCMFrame = firstPCMFrame + pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
60923  if (lastPCMFrame > 0) {
60924  lastPCMFrame -= 1;
60925  }
60926  if (pFirstPCMFrame) {
60927  *pFirstPCMFrame = firstPCMFrame;
60928  }
60929  if (pLastPCMFrame) {
60930  *pLastPCMFrame = lastPCMFrame;
60931  }
60932 }
60934 {
60935  drflac_bool32 result;
60936  DRFLAC_ASSERT(pFlac != NULL);
60937  result = drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes);
60938  DRFLAC_ZERO_MEMORY(&pFlac->currentFLACFrame, sizeof(pFlac->currentFLACFrame));
60939  pFlac->currentPCMFrame = 0;
60940  return result;
60941 }
60943 {
60944  DRFLAC_ASSERT(pFlac != NULL);
60945  return drflac__seek_flac_frame(pFlac);
60946 }
60948 {
60949  drflac_uint64 pcmFramesRead = 0;
60950  while (pcmFramesToSeek > 0) {
60951  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
60953  break;
60954  }
60955  } else {
60956  if (pFlac->currentFLACFrame.pcmFramesRemaining > pcmFramesToSeek) {
60957  pcmFramesRead += pcmFramesToSeek;
60958  pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)pcmFramesToSeek;
60959  pcmFramesToSeek = 0;
60960  } else {
60961  pcmFramesRead += pFlac->currentFLACFrame.pcmFramesRemaining;
60962  pcmFramesToSeek -= pFlac->currentFLACFrame.pcmFramesRemaining;
60964  }
60965  }
60966  }
60967  pFlac->currentPCMFrame += pcmFramesRead;
60968  return pcmFramesRead;
60969 }
60971 {
60972  drflac_bool32 isMidFrame = DRFLAC_FALSE;
60973  drflac_uint64 runningPCMFrameCount;
60974  DRFLAC_ASSERT(pFlac != NULL);
60975  if (pcmFrameIndex >= pFlac->currentPCMFrame) {
60976  runningPCMFrameCount = pFlac->currentPCMFrame;
60977  if (pFlac->currentPCMFrame == 0 && pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
60979  return DRFLAC_FALSE;
60980  }
60981  } else {
60982  isMidFrame = DRFLAC_TRUE;
60983  }
60984  } else {
60985  runningPCMFrameCount = 0;
60986  if (!drflac__seek_to_first_frame(pFlac)) {
60987  return DRFLAC_FALSE;
60988  }
60990  return DRFLAC_FALSE;
60991  }
60992  }
60993  for (;;) {
60994  drflac_uint64 pcmFrameCountInThisFLACFrame;
60995  drflac_uint64 firstPCMFrameInFLACFrame = 0;
60996  drflac_uint64 lastPCMFrameInFLACFrame = 0;
60997  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
60998  pcmFrameCountInThisFLACFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
60999  if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFLACFrame)) {
61000  drflac_uint64 pcmFramesToDecode = pcmFrameIndex - runningPCMFrameCount;
61001  if (!isMidFrame) {
61002  drflac_result result = drflac__decode_flac_frame(pFlac);
61003  if (result == DRFLAC_SUCCESS) {
61004  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
61005  } else {
61006  if (result == DRFLAC_CRC_MISMATCH) {
61007  goto next_iteration;
61008  } else {
61009  return DRFLAC_FALSE;
61010  }
61011  }
61012  } else {
61013  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
61014  }
61015  } else {
61016  if (!isMidFrame) {
61018  if (result == DRFLAC_SUCCESS) {
61019  runningPCMFrameCount += pcmFrameCountInThisFLACFrame;
61020  } else {
61021  if (result == DRFLAC_CRC_MISMATCH) {
61022  goto next_iteration;
61023  } else {
61024  return DRFLAC_FALSE;
61025  }
61026  }
61027  } else {
61028  runningPCMFrameCount += pFlac->currentFLACFrame.pcmFramesRemaining;
61030  isMidFrame = DRFLAC_FALSE;
61031  }
61032  if (pcmFrameIndex == pFlac->totalPCMFrameCount && runningPCMFrameCount == pFlac->totalPCMFrameCount) {
61033  return DRFLAC_TRUE;
61034  }
61035  }
61036  next_iteration:
61038  return DRFLAC_FALSE;
61039  }
61040  }
61041 }
61042 #if !defined(DR_FLAC_NO_CRC)
61043 #define DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO 0.6f
61044 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)
61045 {
61046  DRFLAC_ASSERT(pFlac != NULL);
61047  DRFLAC_ASSERT(pLastSuccessfulSeekOffset != NULL);
61048  DRFLAC_ASSERT(targetByte >= rangeLo);
61049  DRFLAC_ASSERT(targetByte <= rangeHi);
61050  *pLastSuccessfulSeekOffset = pFlac->firstFLACFramePosInBytes;
61051  for (;;) {
61052  drflac_uint64 lastTargetByte = targetByte;
61053  if (!drflac__seek_to_byte(&pFlac->bs, targetByte)) {
61054  if (targetByte == 0) {
61056  return DRFLAC_FALSE;
61057  }
61058  targetByte = rangeLo + ((rangeHi - rangeLo)/2);
61059  rangeHi = targetByte;
61060  } else {
61061  DRFLAC_ZERO_MEMORY(&pFlac->currentFLACFrame, sizeof(pFlac->currentFLACFrame));
61062 #if 1
61064  targetByte = rangeLo + ((rangeHi - rangeLo)/2);
61065  rangeHi = targetByte;
61066  } else {
61067  break;
61068  }
61069 #else
61071  targetByte = rangeLo + ((rangeHi - rangeLo)/2);
61072  rangeHi = targetByte;
61073  } else {
61074  break;
61075  }
61076 #endif
61077  }
61078  if(targetByte == lastTargetByte) {
61079  return DRFLAC_FALSE;
61080  }
61081  }
61083  DRFLAC_ASSERT(targetByte <= rangeHi);
61084  *pLastSuccessfulSeekOffset = targetByte;
61085  return DRFLAC_TRUE;
61086 }
61088 {
61089 #if 0
61090  if (drflac__decode_flac_frame(pFlac) != DRFLAC_SUCCESS) {
61092  return DRFLAC_FALSE;
61093  }
61094  }
61095 #endif
61096  return drflac__seek_forward_by_pcm_frames(pFlac, offset) == offset;
61097 }
61099 {
61100  drflac_uint64 targetByte;
61101  drflac_uint64 pcmRangeLo = pFlac->totalPCMFrameCount;
61102  drflac_uint64 pcmRangeHi = 0;
61103  drflac_uint64 lastSuccessfulSeekOffset = (drflac_uint64)-1;
61104  drflac_uint64 closestSeekOffsetBeforeTargetPCMFrame = byteRangeLo;
61105  drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
61106  targetByte = byteRangeLo + (drflac_uint64)(((drflac_int64)((pcmFrameIndex - pFlac->currentPCMFrame) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO);
61107  if (targetByte > byteRangeHi) {
61108  targetByte = byteRangeHi;
61109  }
61110  for (;;) {
61111  if (drflac__seek_to_approximate_flac_frame_to_byte(pFlac, targetByte, byteRangeLo, byteRangeHi, &lastSuccessfulSeekOffset)) {
61112  drflac_uint64 newPCMRangeLo;
61113  drflac_uint64 newPCMRangeHi;
61114  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &newPCMRangeLo, &newPCMRangeHi);
61115  if (pcmRangeLo == newPCMRangeLo) {
61116  if (!drflac__seek_to_approximate_flac_frame_to_byte(pFlac, closestSeekOffsetBeforeTargetPCMFrame, closestSeekOffsetBeforeTargetPCMFrame, byteRangeHi, &lastSuccessfulSeekOffset)) {
61117  break;
61118  }
61120  return DRFLAC_TRUE;
61121  } else {
61122  break;
61123  }
61124  }
61125  pcmRangeLo = newPCMRangeLo;
61126  pcmRangeHi = newPCMRangeHi;
61127  if (pcmRangeLo <= pcmFrameIndex && pcmRangeHi >= pcmFrameIndex) {
61128  if (drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(pFlac, pcmFrameIndex - pFlac->currentPCMFrame) ) {
61129  return DRFLAC_TRUE;
61130  } else {
61131  break;
61132  }
61133  } else {
61134  const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
61135  if (pcmRangeLo > pcmFrameIndex) {
61136  byteRangeHi = lastSuccessfulSeekOffset;
61137  if (byteRangeLo > byteRangeHi) {
61138  byteRangeLo = byteRangeHi;
61139  }
61140  targetByte = byteRangeLo + ((byteRangeHi - byteRangeLo) / 2);
61141  if (targetByte < byteRangeLo) {
61142  targetByte = byteRangeLo;
61143  }
61144  } else {
61145  if ((pcmFrameIndex - pcmRangeLo) < seekForwardThreshold) {
61147  return DRFLAC_TRUE;
61148  } else {
61149  break;
61150  }
61151  } else {
61152  byteRangeLo = lastSuccessfulSeekOffset;
61153  if (byteRangeHi < byteRangeLo) {
61154  byteRangeHi = byteRangeLo;
61155  }
61156  targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio);
61157  if (targetByte > byteRangeHi) {
61158  targetByte = byteRangeHi;
61159  }
61160  if (closestSeekOffsetBeforeTargetPCMFrame < lastSuccessfulSeekOffset) {
61161  closestSeekOffsetBeforeTargetPCMFrame = lastSuccessfulSeekOffset;
61162  }
61163  }
61164  }
61165  }
61166  } else {
61167  break;
61168  }
61169  }
61171  return DRFLAC_FALSE;
61172 }
61174 {
61175  drflac_uint64 byteRangeLo;
61176  drflac_uint64 byteRangeHi;
61177  drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
61178  if (drflac__seek_to_first_frame(pFlac) == DRFLAC_FALSE) {
61179  return DRFLAC_FALSE;
61180  }
61181  if (pcmFrameIndex < seekForwardThreshold) {
61182  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFrameIndex) == pcmFrameIndex;
61183  }
61184  byteRangeLo = pFlac->firstFLACFramePosInBytes;
61185  byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)((drflac_int64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample)/8.0f);
61186  return drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi);
61187 }
61188 #endif
61190 {
61191  drflac_uint32 iClosestSeekpoint = 0;
61192  drflac_bool32 isMidFrame = DRFLAC_FALSE;
61193  drflac_uint64 runningPCMFrameCount;
61194  drflac_uint32 iSeekpoint;
61195  DRFLAC_ASSERT(pFlac != NULL);
61196  if (pFlac->pSeekpoints == NULL || pFlac->seekpointCount == 0) {
61197  return DRFLAC_FALSE;
61198  }
61199  for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
61200  if (pFlac->pSeekpoints[iSeekpoint].firstPCMFrame >= pcmFrameIndex) {
61201  break;
61202  }
61203  iClosestSeekpoint = iSeekpoint;
61204  }
61205  if (pFlac->pSeekpoints[iClosestSeekpoint].pcmFrameCount == 0 || pFlac->pSeekpoints[iClosestSeekpoint].pcmFrameCount > pFlac->maxBlockSizeInPCMFrames) {
61206  return DRFLAC_FALSE;
61207  }
61208  if (pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame > pFlac->totalPCMFrameCount && pFlac->totalPCMFrameCount > 0) {
61209  return DRFLAC_FALSE;
61210  }
61211 #if !defined(DR_FLAC_NO_CRC)
61212  if (pFlac->totalPCMFrameCount > 0) {
61213  drflac_uint64 byteRangeLo;
61214  drflac_uint64 byteRangeHi;
61215  byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)((drflac_int64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample)/8.0f);
61216  byteRangeLo = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset;
61217  if (iClosestSeekpoint < pFlac->seekpointCount-1) {
61218  drflac_uint32 iNextSeekpoint = iClosestSeekpoint + 1;
61219  if (pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset >= pFlac->pSeekpoints[iNextSeekpoint].flacFrameOffset || pFlac->pSeekpoints[iNextSeekpoint].pcmFrameCount == 0) {
61220  return DRFLAC_FALSE;
61221  }
61222  if (pFlac->pSeekpoints[iNextSeekpoint].firstPCMFrame != (((drflac_uint64)0xFFFFFFFF << 32) | 0xFFFFFFFF)) {
61223  byteRangeHi = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iNextSeekpoint].flacFrameOffset - 1;
61224  }
61225  }
61226  if (drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset)) {
61227  if (drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
61228  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &pFlac->currentPCMFrame, NULL);
61229  if (drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi)) {
61230  return DRFLAC_TRUE;
61231  }
61232  }
61233  }
61234  }
61235 #endif
61236  if (pcmFrameIndex >= pFlac->currentPCMFrame && pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame <= pFlac->currentPCMFrame) {
61237  runningPCMFrameCount = pFlac->currentPCMFrame;
61238  if (pFlac->currentPCMFrame == 0 && pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
61239  if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
61240  return DRFLAC_FALSE;
61241  }
61242  } else {
61243  isMidFrame = DRFLAC_TRUE;
61244  }
61245  } else {
61246  runningPCMFrameCount = pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame;
61247  if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset)) {
61248  return DRFLAC_FALSE;
61249  }
61251  return DRFLAC_FALSE;
61252  }
61253  }
61254  for (;;) {
61255  drflac_uint64 pcmFrameCountInThisFLACFrame;
61256  drflac_uint64 firstPCMFrameInFLACFrame = 0;
61257  drflac_uint64 lastPCMFrameInFLACFrame = 0;
61258  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
61259  pcmFrameCountInThisFLACFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
61260  if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFLACFrame)) {
61261  drflac_uint64 pcmFramesToDecode = pcmFrameIndex - runningPCMFrameCount;
61262  if (!isMidFrame) {
61263  drflac_result result = drflac__decode_flac_frame(pFlac);
61264  if (result == DRFLAC_SUCCESS) {
61265  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
61266  } else {
61267  if (result == DRFLAC_CRC_MISMATCH) {
61268  goto next_iteration;
61269  } else {
61270  return DRFLAC_FALSE;
61271  }
61272  }
61273  } else {
61274  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
61275  }
61276  } else {
61277  if (!isMidFrame) {
61279  if (result == DRFLAC_SUCCESS) {
61280  runningPCMFrameCount += pcmFrameCountInThisFLACFrame;
61281  } else {
61282  if (result == DRFLAC_CRC_MISMATCH) {
61283  goto next_iteration;
61284  } else {
61285  return DRFLAC_FALSE;
61286  }
61287  }
61288  } else {
61289  runningPCMFrameCount += pFlac->currentFLACFrame.pcmFramesRemaining;
61291  isMidFrame = DRFLAC_FALSE;
61292  }
61293  if (pcmFrameIndex == pFlac->totalPCMFrameCount && runningPCMFrameCount == pFlac->totalPCMFrameCount) {
61294  return DRFLAC_TRUE;
61295  }
61296  }
61297  next_iteration:
61299  return DRFLAC_FALSE;
61300  }
61301  }
61302 }
61303 #ifndef DR_FLAC_NO_OGG
61304 typedef struct
61305 {
61306  drflac_uint8 capturePattern[4];
61307  drflac_uint8 structureVersion;
61308  drflac_uint8 headerType;
61309  drflac_uint64 granulePosition;
61310  drflac_uint32 serialNumber;
61311  drflac_uint32 sequenceNumber;
61312  drflac_uint32 checksum;
61313  drflac_uint8 segmentCount;
61314  drflac_uint8 segmentTable[255];
61316 #endif
61317 typedef struct
61318 {
61319  drflac_read_proc onRead;
61320  drflac_seek_proc onSeek;
61321  drflac_meta_proc onMeta;
61322  drflac_container container;
61323  void* pUserData;
61324  void* pUserDataMD;
61325  drflac_uint32 sampleRate;
61326  drflac_uint8 channels;
61327  drflac_uint8 bitsPerSample;
61328  drflac_uint64 totalPCMFrameCount;
61329  drflac_uint16 maxBlockSizeInPCMFrames;
61330  drflac_uint64 runningFilePos;
61331  drflac_bool32 hasStreamInfoBlock;
61332  drflac_bool32 hasMetadataBlocks;
61333  drflac_bs bs;
61334  drflac_frame_header firstFrameHeader;
61335 #ifndef DR_FLAC_NO_OGG
61336  drflac_uint32 oggSerial;
61337  drflac_uint64 oggFirstBytePos;
61338  drflac_ogg_page_header oggBosHeader;
61339 #endif
61341 static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize)
61342 {
61343  blockHeader = drflac__be2host_32(blockHeader);
61344  *isLastBlock = (drflac_uint8)((blockHeader & 0x80000000UL) >> 31);
61345  *blockType = (drflac_uint8)((blockHeader & 0x7F000000UL) >> 24);
61346  *blockSize = (blockHeader & 0x00FFFFFFUL);
61347 }
61348 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)
61349 {
61350  drflac_uint32 blockHeader;
61351  *blockSize = 0;
61352  if (onRead(pUserData, &blockHeader, 4) != 4) {
61353  return DRFLAC_FALSE;
61354  }
61355  drflac__decode_block_header(blockHeader, isLastBlock, blockType, blockSize);
61356  return DRFLAC_TRUE;
61357 }
61358 static drflac_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo)
61359 {
61360  drflac_uint32 blockSizes;
61361  drflac_uint64 frameSizes = 0;
61362  drflac_uint64 importantProps;
61363  drflac_uint8 md5[16];
61364  if (onRead(pUserData, &blockSizes, 4) != 4) {
61365  return DRFLAC_FALSE;
61366  }
61367  if (onRead(pUserData, &frameSizes, 6) != 6) {
61368  return DRFLAC_FALSE;
61369  }
61370  if (onRead(pUserData, &importantProps, 8) != 8) {
61371  return DRFLAC_FALSE;
61372  }
61373  if (onRead(pUserData, md5, sizeof(md5)) != sizeof(md5)) {
61374  return DRFLAC_FALSE;
61375  }
61376  blockSizes = drflac__be2host_32(blockSizes);
61377  frameSizes = drflac__be2host_64(frameSizes);
61378  importantProps = drflac__be2host_64(importantProps);
61379  pStreamInfo->minBlockSizeInPCMFrames = (drflac_uint16)((blockSizes & 0xFFFF0000) >> 16);
61380  pStreamInfo->maxBlockSizeInPCMFrames = (drflac_uint16) (blockSizes & 0x0000FFFF);
61381  pStreamInfo->minFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 24)) >> 40);
61382  pStreamInfo->maxFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 0)) >> 16);
61383  pStreamInfo->sampleRate = (drflac_uint32)((importantProps & (((drflac_uint64)0x000FFFFF << 16) << 28)) >> 44);
61384  pStreamInfo->channels = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000000E << 16) << 24)) >> 41) + 1;
61385  pStreamInfo->bitsPerSample = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000001F << 16) << 20)) >> 36) + 1;
61386  pStreamInfo->totalPCMFrameCount = ((importantProps & ((((drflac_uint64)0x0000000F << 16) << 16) | 0xFFFFFFFF)));
61387  DRFLAC_COPY_MEMORY(pStreamInfo->md5, md5, sizeof(md5));
61388  return DRFLAC_TRUE;
61389 }
61390 static void* drflac__malloc_default(size_t sz, void* pUserData)
61391 {
61392  (void)pUserData;
61393  return DRFLAC_MALLOC(sz);
61394 }
61395 static void* drflac__realloc_default(void* p, size_t sz, void* pUserData)
61396 {
61397  (void)pUserData;
61398  return DRFLAC_REALLOC(p, sz);
61399 }
61400 static void drflac__free_default(void* p, void* pUserData)
61401 {
61402  (void)pUserData;
61403  DRFLAC_FREE(p);
61404 }
61405 static void* drflac__malloc_from_callbacks(size_t sz, const drflac_allocation_callbacks* pAllocationCallbacks)
61406 {
61407  if (pAllocationCallbacks == NULL) {
61408  return NULL;
61409  }
61410  if (pAllocationCallbacks->onMalloc != NULL) {
61411  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
61412  }
61413  if (pAllocationCallbacks->onRealloc != NULL) {
61414  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
61415  }
61416  return NULL;
61417 }
61418 static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drflac_allocation_callbacks* pAllocationCallbacks)
61419 {
61420  if (pAllocationCallbacks == NULL) {
61421  return NULL;
61422  }
61423  if (pAllocationCallbacks->onRealloc != NULL) {
61424  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
61425  }
61426  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
61427  void* p2;
61428  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
61429  if (p2 == NULL) {
61430  return NULL;
61431  }
61432  if (p != NULL) {
61433  DRFLAC_COPY_MEMORY(p2, p, szOld);
61434  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
61435  }
61436  return p2;
61437  }
61438  return NULL;
61439 }
61440 static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
61441 {
61442  if (p == NULL || pAllocationCallbacks == NULL) {
61443  return;
61444  }
61445  if (pAllocationCallbacks->onFree != NULL) {
61446  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
61447  }
61448 }
61449 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)
61450 {
61451  drflac_uint64 runningFilePos = 42;
61452  drflac_uint64 seektablePos = 0;
61453  drflac_uint32 seektableSize = 0;
61454  for (;;) {
61455  drflac_metadata metadata;
61456  drflac_uint8 isLastBlock = 0;
61457  drflac_uint8 blockType;
61458  drflac_uint32 blockSize;
61459  if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
61460  return DRFLAC_FALSE;
61461  }
61462  runningFilePos += 4;
61463  metadata.type = blockType;
61464  metadata.pRawData = NULL;
61465  metadata.rawDataSize = 0;
61466  switch (blockType)
61467  {
61469  {
61470  if (blockSize < 4) {
61471  return DRFLAC_FALSE;
61472  }
61473  if (onMeta) {
61474  void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
61475  if (pRawData == NULL) {
61476  return DRFLAC_FALSE;
61477  }
61478  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
61479  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61480  return DRFLAC_FALSE;
61481  }
61482  metadata.pRawData = pRawData;
61483  metadata.rawDataSize = blockSize;
61484  metadata.data.application.id = drflac__be2host_32(*(drflac_uint32*)pRawData);
61485  metadata.data.application.pData = (const void*)((drflac_uint8*)pRawData + sizeof(drflac_uint32));
61486  metadata.data.application.dataSize = blockSize - sizeof(drflac_uint32);
61487  onMeta(pUserDataMD, &metadata);
61488  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61489  }
61490  } break;
61492  {
61493  seektablePos = runningFilePos;
61494  seektableSize = blockSize;
61495  if (onMeta) {
61496  drflac_uint32 iSeekpoint;
61497  void* pRawData;
61498  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
61499  if (pRawData == NULL) {
61500  return DRFLAC_FALSE;
61501  }
61502  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
61503  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61504  return DRFLAC_FALSE;
61505  }
61506  metadata.pRawData = pRawData;
61507  metadata.rawDataSize = blockSize;
61508  metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
61509  metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
61510  for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
61511  drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
61512  pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
61513  pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
61514  pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
61515  }
61516  onMeta(pUserDataMD, &metadata);
61517  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61518  }
61519  } break;
61521  {
61522  if (blockSize < 8) {
61523  return DRFLAC_FALSE;
61524  }
61525  if (onMeta) {
61526  void* pRawData;
61527  const char* pRunningData;
61528  const char* pRunningDataEnd;
61529  drflac_uint32 i;
61530  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
61531  if (pRawData == NULL) {
61532  return DRFLAC_FALSE;
61533  }
61534  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
61535  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61536  return DRFLAC_FALSE;
61537  }
61538  metadata.pRawData = pRawData;
61539  metadata.rawDataSize = blockSize;
61540  pRunningData = (const char*)pRawData;
61541  pRunningDataEnd = (const char*)pRawData + blockSize;
61542  metadata.data.vorbis_comment.vendorLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61543  if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) {
61544  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61545  return DRFLAC_FALSE;
61546  }
61547  metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
61548  metadata.data.vorbis_comment.commentCount = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61549  if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) {
61550  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61551  return DRFLAC_FALSE;
61552  }
61553  metadata.data.vorbis_comment.pComments = pRunningData;
61554  for (i = 0; i < metadata.data.vorbis_comment.commentCount; ++i) {
61555  drflac_uint32 commentLength;
61556  if (pRunningDataEnd - pRunningData < 4) {
61557  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61558  return DRFLAC_FALSE;
61559  }
61560  commentLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61561  if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) {
61562  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61563  return DRFLAC_FALSE;
61564  }
61565  pRunningData += commentLength;
61566  }
61567  onMeta(pUserDataMD, &metadata);
61568  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61569  }
61570  } break;
61572  {
61573  if (blockSize < 396) {
61574  return DRFLAC_FALSE;
61575  }
61576  if (onMeta) {
61577  void* pRawData;
61578  const char* pRunningData;
61579  const char* pRunningDataEnd;
61580  drflac_uint8 iTrack;
61581  drflac_uint8 iIndex;
61582  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
61583  if (pRawData == NULL) {
61584  return DRFLAC_FALSE;
61585  }
61586  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
61587  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61588  return DRFLAC_FALSE;
61589  }
61590  metadata.pRawData = pRawData;
61591  metadata.rawDataSize = blockSize;
61592  pRunningData = (const char*)pRawData;
61593  pRunningDataEnd = (const char*)pRawData + blockSize;
61594  DRFLAC_COPY_MEMORY(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
61595  metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
61596  metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
61597  metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
61598  metadata.data.cuesheet.pTrackData = pRunningData;
61599  for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
61600  drflac_uint8 indexCount;
61601  drflac_uint32 indexPointSize;
61602  if (pRunningDataEnd - pRunningData < 36) {
61603  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61604  return DRFLAC_FALSE;
61605  }
61606  pRunningData += 35;
61607  indexCount = pRunningData[0]; pRunningData += 1;
61608  indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
61609  if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
61610  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61611  return DRFLAC_FALSE;
61612  }
61613  for (iIndex = 0; iIndex < indexCount; ++iIndex) {
61615  pRunningData += sizeof(drflac_cuesheet_track_index);
61616  pTrack->offset = drflac__be2host_64(pTrack->offset);
61617  }
61618  }
61619  onMeta(pUserDataMD, &metadata);
61620  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61621  }
61622  } break;
61624  {
61625  if (blockSize < 32) {
61626  return DRFLAC_FALSE;
61627  }
61628  if (onMeta) {
61629  void* pRawData;
61630  const char* pRunningData;
61631  const char* pRunningDataEnd;
61632  pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
61633  if (pRawData == NULL) {
61634  return DRFLAC_FALSE;
61635  }
61636  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
61637  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61638  return DRFLAC_FALSE;
61639  }
61640  metadata.pRawData = pRawData;
61641  metadata.rawDataSize = blockSize;
61642  pRunningData = (const char*)pRawData;
61643  pRunningDataEnd = (const char*)pRawData + blockSize;
61644  metadata.data.picture.type = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61645  metadata.data.picture.mimeLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61646  if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) {
61647  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61648  return DRFLAC_FALSE;
61649  }
61650  metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
61651  metadata.data.picture.descriptionLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61652  if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) {
61653  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61654  return DRFLAC_FALSE;
61655  }
61656  metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
61657  metadata.data.picture.width = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61658  metadata.data.picture.height = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61659  metadata.data.picture.colorDepth = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61660  metadata.data.picture.indexColorCount = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61661  metadata.data.picture.pictureDataSize = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
61662  metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
61663  if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) {
61664  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61665  return DRFLAC_FALSE;
61666  }
61667  onMeta(pUserDataMD, &metadata);
61668  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61669  }
61670  } break;
61672  {
61673  if (onMeta) {
61674  metadata.data.padding.unused = 0;
61675  if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
61676  isLastBlock = DRFLAC_TRUE;
61677  } else {
61678  onMeta(pUserDataMD, &metadata);
61679  }
61680  }
61681  } break;
61683  {
61684  if (onMeta) {
61685  if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
61686  isLastBlock = DRFLAC_TRUE;
61687  }
61688  }
61689  } break;
61690  default:
61691  {
61692  if (onMeta) {
61693  void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
61694  if (pRawData == NULL) {
61695  return DRFLAC_FALSE;
61696  }
61697  if (onRead(pUserData, pRawData, blockSize) != blockSize) {
61698  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61699  return DRFLAC_FALSE;
61700  }
61701  metadata.pRawData = pRawData;
61702  metadata.rawDataSize = blockSize;
61703  onMeta(pUserDataMD, &metadata);
61704  drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
61705  }
61706  } break;
61707  }
61708  if (onMeta == NULL && blockSize > 0) {
61709  if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
61710  isLastBlock = DRFLAC_TRUE;
61711  }
61712  }
61713  runningFilePos += blockSize;
61714  if (isLastBlock) {
61715  break;
61716  }
61717  }
61718  *pSeektablePos = seektablePos;
61719  *pSeektableSize = seektableSize;
61720  *pFirstFramePos = runningFilePos;
61721  return DRFLAC_TRUE;
61722 }
61723 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)
61724 {
61725  drflac_uint8 isLastBlock;
61726  drflac_uint8 blockType;
61727  drflac_uint32 blockSize;
61728  (void)onSeek;
61730  if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
61731  return DRFLAC_FALSE;
61732  }
61733  if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
61734  if (!relaxed) {
61735  return DRFLAC_FALSE;
61736  } else {
61739  if (!drflac__read_next_flac_frame_header(&pInit->bs, 0, &pInit->firstFrameHeader)) {
61740  return DRFLAC_FALSE;
61741  }
61742  if (pInit->firstFrameHeader.bitsPerSample == 0) {
61743  return DRFLAC_FALSE;
61744  }
61745  pInit->sampleRate = pInit->firstFrameHeader.sampleRate;
61748  pInit->maxBlockSizeInPCMFrames = 65535;
61749  return DRFLAC_TRUE;
61750  }
61751  } else {
61752  drflac_streaminfo streaminfo;
61753  if (!drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
61754  return DRFLAC_FALSE;
61755  }
61757  pInit->sampleRate = streaminfo.sampleRate;
61758  pInit->channels = streaminfo.channels;
61759  pInit->bitsPerSample = streaminfo.bitsPerSample;
61760  pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
61762  pInit->hasMetadataBlocks = !isLastBlock;
61763  if (onMeta) {
61764  drflac_metadata metadata;
61766  metadata.pRawData = NULL;
61767  metadata.rawDataSize = 0;
61768  metadata.data.streaminfo = streaminfo;
61769  onMeta(pUserDataMD, &metadata);
61770  }
61771  return DRFLAC_TRUE;
61772  }
61773 }
61774 #ifndef DR_FLAC_NO_OGG
61775 #define DRFLAC_OGG_MAX_PAGE_SIZE 65307
61776 #define DRFLAC_OGG_CAPTURE_PATTERN_CRC32 1605413199
61777 typedef enum
61778 {
61782 #ifndef DR_FLAC_NO_CRC
61784  0x00000000L, 0x04C11DB7L, 0x09823B6EL, 0x0D4326D9L,
61785  0x130476DCL, 0x17C56B6BL, 0x1A864DB2L, 0x1E475005L,
61786  0x2608EDB8L, 0x22C9F00FL, 0x2F8AD6D6L, 0x2B4BCB61L,
61787  0x350C9B64L, 0x31CD86D3L, 0x3C8EA00AL, 0x384FBDBDL,
61788  0x4C11DB70L, 0x48D0C6C7L, 0x4593E01EL, 0x4152FDA9L,
61789  0x5F15ADACL, 0x5BD4B01BL, 0x569796C2L, 0x52568B75L,
61790  0x6A1936C8L, 0x6ED82B7FL, 0x639B0DA6L, 0x675A1011L,
61791  0x791D4014L, 0x7DDC5DA3L, 0x709F7B7AL, 0x745E66CDL,
61792  0x9823B6E0L, 0x9CE2AB57L, 0x91A18D8EL, 0x95609039L,
61793  0x8B27C03CL, 0x8FE6DD8BL, 0x82A5FB52L, 0x8664E6E5L,
61794  0xBE2B5B58L, 0xBAEA46EFL, 0xB7A96036L, 0xB3687D81L,
61795  0xAD2F2D84L, 0xA9EE3033L, 0xA4AD16EAL, 0xA06C0B5DL,
61796  0xD4326D90L, 0xD0F37027L, 0xDDB056FEL, 0xD9714B49L,
61797  0xC7361B4CL, 0xC3F706FBL, 0xCEB42022L, 0xCA753D95L,
61798  0xF23A8028L, 0xF6FB9D9FL, 0xFBB8BB46L, 0xFF79A6F1L,
61799  0xE13EF6F4L, 0xE5FFEB43L, 0xE8BCCD9AL, 0xEC7DD02DL,
61800  0x34867077L, 0x30476DC0L, 0x3D044B19L, 0x39C556AEL,
61801  0x278206ABL, 0x23431B1CL, 0x2E003DC5L, 0x2AC12072L,
61802  0x128E9DCFL, 0x164F8078L, 0x1B0CA6A1L, 0x1FCDBB16L,
61803  0x018AEB13L, 0x054BF6A4L, 0x0808D07DL, 0x0CC9CDCAL,
61804  0x7897AB07L, 0x7C56B6B0L, 0x71159069L, 0x75D48DDEL,
61805  0x6B93DDDBL, 0x6F52C06CL, 0x6211E6B5L, 0x66D0FB02L,
61806  0x5E9F46BFL, 0x5A5E5B08L, 0x571D7DD1L, 0x53DC6066L,
61807  0x4D9B3063L, 0x495A2DD4L, 0x44190B0DL, 0x40D816BAL,
61808  0xACA5C697L, 0xA864DB20L, 0xA527FDF9L, 0xA1E6E04EL,
61809  0xBFA1B04BL, 0xBB60ADFCL, 0xB6238B25L, 0xB2E29692L,
61810  0x8AAD2B2FL, 0x8E6C3698L, 0x832F1041L, 0x87EE0DF6L,
61811  0x99A95DF3L, 0x9D684044L, 0x902B669DL, 0x94EA7B2AL,
61812  0xE0B41DE7L, 0xE4750050L, 0xE9362689L, 0xEDF73B3EL,
61813  0xF3B06B3BL, 0xF771768CL, 0xFA325055L, 0xFEF34DE2L,
61814  0xC6BCF05FL, 0xC27DEDE8L, 0xCF3ECB31L, 0xCBFFD686L,
61815  0xD5B88683L, 0xD1799B34L, 0xDC3ABDEDL, 0xD8FBA05AL,
61816  0x690CE0EEL, 0x6DCDFD59L, 0x608EDB80L, 0x644FC637L,
61817  0x7A089632L, 0x7EC98B85L, 0x738AAD5CL, 0x774BB0EBL,
61818  0x4F040D56L, 0x4BC510E1L, 0x46863638L, 0x42472B8FL,
61819  0x5C007B8AL, 0x58C1663DL, 0x558240E4L, 0x51435D53L,
61820  0x251D3B9EL, 0x21DC2629L, 0x2C9F00F0L, 0x285E1D47L,
61821  0x36194D42L, 0x32D850F5L, 0x3F9B762CL, 0x3B5A6B9BL,
61822  0x0315D626L, 0x07D4CB91L, 0x0A97ED48L, 0x0E56F0FFL,
61823  0x1011A0FAL, 0x14D0BD4DL, 0x19939B94L, 0x1D528623L,
61824  0xF12F560EL, 0xF5EE4BB9L, 0xF8AD6D60L, 0xFC6C70D7L,
61825  0xE22B20D2L, 0xE6EA3D65L, 0xEBA91BBCL, 0xEF68060BL,
61826  0xD727BBB6L, 0xD3E6A601L, 0xDEA580D8L, 0xDA649D6FL,
61827  0xC423CD6AL, 0xC0E2D0DDL, 0xCDA1F604L, 0xC960EBB3L,
61828  0xBD3E8D7EL, 0xB9FF90C9L, 0xB4BCB610L, 0xB07DABA7L,
61829  0xAE3AFBA2L, 0xAAFBE615L, 0xA7B8C0CCL, 0xA379DD7BL,
61830  0x9B3660C6L, 0x9FF77D71L, 0x92B45BA8L, 0x9675461FL,
61831  0x8832161AL, 0x8CF30BADL, 0x81B02D74L, 0x857130C3L,
61832  0x5D8A9099L, 0x594B8D2EL, 0x5408ABF7L, 0x50C9B640L,
61833  0x4E8EE645L, 0x4A4FFBF2L, 0x470CDD2BL, 0x43CDC09CL,
61834  0x7B827D21L, 0x7F436096L, 0x7200464FL, 0x76C15BF8L,
61835  0x68860BFDL, 0x6C47164AL, 0x61043093L, 0x65C52D24L,
61836  0x119B4BE9L, 0x155A565EL, 0x18197087L, 0x1CD86D30L,
61837  0x029F3D35L, 0x065E2082L, 0x0B1D065BL, 0x0FDC1BECL,
61838  0x3793A651L, 0x3352BBE6L, 0x3E119D3FL, 0x3AD08088L,
61839  0x2497D08DL, 0x2056CD3AL, 0x2D15EBE3L, 0x29D4F654L,
61840  0xC5A92679L, 0xC1683BCEL, 0xCC2B1D17L, 0xC8EA00A0L,
61841  0xD6AD50A5L, 0xD26C4D12L, 0xDF2F6BCBL, 0xDBEE767CL,
61842  0xE3A1CBC1L, 0xE760D676L, 0xEA23F0AFL, 0xEEE2ED18L,
61843  0xF0A5BD1DL, 0xF464A0AAL, 0xF9278673L, 0xFDE69BC4L,
61844  0x89B8FD09L, 0x8D79E0BEL, 0x803AC667L, 0x84FBDBD0L,
61845  0x9ABC8BD5L, 0x9E7D9662L, 0x933EB0BBL, 0x97FFAD0CL,
61846  0xAFB010B1L, 0xAB710D06L, 0xA6322BDFL, 0xA2F33668L,
61847  0xBCB4666DL, 0xB8757BDAL, 0xB5365D03L, 0xB1F740B4L
61848 };
61849 #endif
61851 {
61852 #ifndef DR_FLAC_NO_CRC
61853  return (crc32 << 8) ^ drflac__crc32_table[(drflac_uint8)((crc32 >> 24) & 0xFF) ^ data];
61854 #else
61855  (void)data;
61856  return crc32;
61857 #endif
61858 }
61859 #if 0
61860 static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint32(drflac_uint32 crc32, drflac_uint32 data)
61861 {
61862  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 24) & 0xFF));
61863  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 16) & 0xFF));
61864  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 8) & 0xFF));
61865  crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 0) & 0xFF));
61866  return crc32;
61867 }
61868 static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint64(drflac_uint32 crc32, drflac_uint64 data)
61869 {
61870  crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 32) & 0xFFFFFFFF));
61871  crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 0) & 0xFFFFFFFF));
61872  return crc32;
61873 }
61874 #endif
61876 {
61877  drflac_uint32 i;
61878  for (i = 0; i < dataSize; ++i) {
61879  crc32 = drflac_crc32_byte(crc32, pData[i]);
61880  }
61881  return crc32;
61882 }
61884 {
61885  return pattern[0] == 'O' && pattern[1] == 'g' && pattern[2] == 'g' && pattern[3] == 'S';
61886 }
61888 {
61889  return 27 + pHeader->segmentCount;
61890 }
61892 {
61893  drflac_uint32 pageBodySize = 0;
61894  int i;
61895  for (i = 0; i < pHeader->segmentCount; ++i) {
61896  pageBodySize += pHeader->segmentTable[i];
61897  }
61898  return pageBodySize;
61899 }
61901 {
61902  drflac_uint8 data[23];
61903  drflac_uint32 i;
61905  if (onRead(pUserData, data, 23) != 23) {
61906  return DRFLAC_AT_END;
61907  }
61908  *pBytesRead += 23;
61909  pHeader->capturePattern[0] = 'O';
61910  pHeader->capturePattern[1] = 'g';
61911  pHeader->capturePattern[2] = 'g';
61912  pHeader->capturePattern[3] = 'S';
61913  pHeader->structureVersion = data[0];
61914  pHeader->headerType = data[1];
61915  DRFLAC_COPY_MEMORY(&pHeader->granulePosition, &data[ 2], 8);
61916  DRFLAC_COPY_MEMORY(&pHeader->serialNumber, &data[10], 4);
61917  DRFLAC_COPY_MEMORY(&pHeader->sequenceNumber, &data[14], 4);
61918  DRFLAC_COPY_MEMORY(&pHeader->checksum, &data[18], 4);
61919  pHeader->segmentCount = data[22];
61920  data[18] = 0;
61921  data[19] = 0;
61922  data[20] = 0;
61923  data[21] = 0;
61924  for (i = 0; i < 23; ++i) {
61925  *pCRC32 = drflac_crc32_byte(*pCRC32, data[i]);
61926  }
61927  if (onRead(pUserData, pHeader->segmentTable, pHeader->segmentCount) != pHeader->segmentCount) {
61928  return DRFLAC_AT_END;
61929  }
61930  *pBytesRead += pHeader->segmentCount;
61931  for (i = 0; i < pHeader->segmentCount; ++i) {
61932  *pCRC32 = drflac_crc32_byte(*pCRC32, pHeader->segmentTable[i]);
61933  }
61934  return DRFLAC_SUCCESS;
61935 }
61936 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)
61937 {
61938  drflac_uint8 id[4];
61939  *pBytesRead = 0;
61940  if (onRead(pUserData, id, 4) != 4) {
61941  return DRFLAC_AT_END;
61942  }
61943  *pBytesRead += 4;
61944  for (;;) {
61946  drflac_result result;
61948  result = drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, pHeader, pBytesRead, pCRC32);
61949  if (result == DRFLAC_SUCCESS) {
61950  return DRFLAC_SUCCESS;
61951  } else {
61952  if (result == DRFLAC_CRC_MISMATCH) {
61953  continue;
61954  } else {
61955  return result;
61956  }
61957  }
61958  } else {
61959  id[0] = id[1];
61960  id[1] = id[2];
61961  id[2] = id[3];
61962  if (onRead(pUserData, &id[3], 1) != 1) {
61963  return DRFLAC_AT_END;
61964  }
61965  *pBytesRead += 1;
61966  }
61967  }
61968 }
61969 typedef struct
61970 {
61971  drflac_read_proc onRead;
61972  drflac_seek_proc onSeek;
61973  void* pUserData;
61974  drflac_uint64 currentBytePos;
61975  drflac_uint64 firstBytePos;
61976  drflac_uint32 serialNumber;
61977  drflac_ogg_page_header bosPageHeader;
61978  drflac_ogg_page_header currentPageHeader;
61979  drflac_uint32 bytesRemainingInPage;
61980  drflac_uint32 pageDataSize;
61981  drflac_uint8 pageData[DRFLAC_OGG_MAX_PAGE_SIZE];
61982 } drflac_oggbs;
61983 static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut, size_t bytesToRead)
61984 {
61985  size_t bytesActuallyRead = oggbs->onRead(oggbs->pUserData, bufferOut, bytesToRead);
61986  oggbs->currentBytePos += bytesActuallyRead;
61987  return bytesActuallyRead;
61988 }
61990 {
61991  if (origin == drflac_seek_origin_start) {
61992  if (offset <= 0x7FFFFFFF) {
61993  if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
61994  return DRFLAC_FALSE;
61995  }
61996  oggbs->currentBytePos = offset;
61997  return DRFLAC_TRUE;
61998  } else {
61999  if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
62000  return DRFLAC_FALSE;
62001  }
62002  oggbs->currentBytePos = offset;
62003  return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
62004  }
62005  } else {
62006  while (offset > 0x7FFFFFFF) {
62007  if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
62008  return DRFLAC_FALSE;
62009  }
62010  oggbs->currentBytePos += 0x7FFFFFFF;
62011  offset -= 0x7FFFFFFF;
62012  }
62013  if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) {
62014  return DRFLAC_FALSE;
62015  }
62016  oggbs->currentBytePos += offset;
62017  return DRFLAC_TRUE;
62018  }
62019 }
62021 {
62023  for (;;) {
62024  drflac_uint32 crc32 = 0;
62025  drflac_uint32 bytesRead;
62026  drflac_uint32 pageBodySize;
62027 #ifndef DR_FLAC_NO_CRC
62028  drflac_uint32 actualCRC32;
62029 #endif
62030  if (drflac_ogg__read_page_header(oggbs->onRead, oggbs->pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
62031  return DRFLAC_FALSE;
62032  }
62033  oggbs->currentBytePos += bytesRead;
62034  pageBodySize = drflac_ogg__get_page_body_size(&header);
62035  if (pageBodySize > DRFLAC_OGG_MAX_PAGE_SIZE) {
62036  continue;
62037  }
62038  if (header.serialNumber != oggbs->serialNumber) {
62039  if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) {
62040  return DRFLAC_FALSE;
62041  }
62042  continue;
62043  }
62044  if (drflac_oggbs__read_physical(oggbs, oggbs->pageData, pageBodySize) != pageBodySize) {
62045  return DRFLAC_FALSE;
62046  }
62047  oggbs->pageDataSize = pageBodySize;
62048 #ifndef DR_FLAC_NO_CRC
62049  actualCRC32 = drflac_crc32_buffer(crc32, oggbs->pageData, oggbs->pageDataSize);
62050  if (actualCRC32 != header.checksum) {
62051  if (recoveryMethod == drflac_ogg_recover_on_crc_mismatch) {
62052  continue;
62053  } else {
62055  return DRFLAC_FALSE;
62056  }
62057  }
62058 #else
62059  (void)recoveryMethod;
62060 #endif
62061  oggbs->currentPageHeader = header;
62062  oggbs->bytesRemainingInPage = pageBodySize;
62063  return DRFLAC_TRUE;
62064  }
62065 }
62066 #if 0
62067 static drflac_uint8 drflac_oggbs__get_current_segment_index(drflac_oggbs* oggbs, drflac_uint8* pBytesRemainingInSeg)
62068 {
62069  drflac_uint32 bytesConsumedInPage = drflac_ogg__get_page_body_size(&oggbs->currentPageHeader) - oggbs->bytesRemainingInPage;
62070  drflac_uint8 iSeg = 0;
62071  drflac_uint32 iByte = 0;
62072  while (iByte < bytesConsumedInPage) {
62073  drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg];
62074  if (iByte + segmentSize > bytesConsumedInPage) {
62075  break;
62076  } else {
62077  iSeg += 1;
62078  iByte += segmentSize;
62079  }
62080  }
62081  *pBytesRemainingInSeg = oggbs->currentPageHeader.segmentTable[iSeg] - (drflac_uint8)(bytesConsumedInPage - iByte);
62082  return iSeg;
62083 }
62084 static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs)
62085 {
62086  for (;;) {
62087  drflac_bool32 atEndOfPage = DRFLAC_FALSE;
62088  drflac_uint8 bytesRemainingInSeg;
62089  drflac_uint8 iFirstSeg = drflac_oggbs__get_current_segment_index(oggbs, &bytesRemainingInSeg);
62090  drflac_uint32 bytesToEndOfPacketOrPage = bytesRemainingInSeg;
62091  for (drflac_uint8 iSeg = iFirstSeg; iSeg < oggbs->currentPageHeader.segmentCount; ++iSeg) {
62092  drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg];
62093  if (segmentSize < 255) {
62094  if (iSeg == oggbs->currentPageHeader.segmentCount-1) {
62095  atEndOfPage = DRFLAC_TRUE;
62096  }
62097  break;
62098  }
62099  bytesToEndOfPacketOrPage += segmentSize;
62100  }
62101  drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current);
62102  oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
62103  if (atEndOfPage) {
62104  if (!drflac_oggbs__goto_next_page(oggbs)) {
62105  return DRFLAC_FALSE;
62106  }
62107  if ((oggbs->currentPageHeader.headerType & 0x01) == 0) {
62108  return DRFLAC_TRUE;
62109  }
62110  } else {
62111  return DRFLAC_TRUE;
62112  }
62113  }
62114 }
62115 static drflac_bool32 drflac_oggbs__seek_to_next_frame(drflac_oggbs* oggbs)
62116 {
62117  return drflac_oggbs__seek_to_next_packet(oggbs);
62118 }
62119 #endif
62120 static size_t drflac__on_read_ogg(void* pUserData, void* bufferOut, size_t bytesToRead)
62121 {
62122  drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
62123  drflac_uint8* pRunningBufferOut = (drflac_uint8*)bufferOut;
62124  size_t bytesRead = 0;
62125  DRFLAC_ASSERT(oggbs != NULL);
62126  DRFLAC_ASSERT(pRunningBufferOut != NULL);
62127  while (bytesRead < bytesToRead) {
62128  size_t bytesRemainingToRead = bytesToRead - bytesRead;
62129  if (oggbs->bytesRemainingInPage >= bytesRemainingToRead) {
62130  DRFLAC_COPY_MEMORY(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), bytesRemainingToRead);
62131  bytesRead += bytesRemainingToRead;
62132  oggbs->bytesRemainingInPage -= (drflac_uint32)bytesRemainingToRead;
62133  break;
62134  }
62135  if (oggbs->bytesRemainingInPage > 0) {
62136  DRFLAC_COPY_MEMORY(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), oggbs->bytesRemainingInPage);
62137  bytesRead += oggbs->bytesRemainingInPage;
62138  pRunningBufferOut += oggbs->bytesRemainingInPage;
62139  oggbs->bytesRemainingInPage = 0;
62140  }
62141  DRFLAC_ASSERT(bytesRemainingToRead > 0);
62143  break;
62144  }
62145  }
62146  return bytesRead;
62147 }
62148 static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_origin origin)
62149 {
62150  drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
62151  int bytesSeeked = 0;
62152  DRFLAC_ASSERT(oggbs != NULL);
62153  DRFLAC_ASSERT(offset >= 0);
62154  if (origin == drflac_seek_origin_start) {
62156  return DRFLAC_FALSE;
62157  }
62159  return DRFLAC_FALSE;
62160  }
62161  return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current);
62162  }
62164  while (bytesSeeked < offset) {
62165  int bytesRemainingToSeek = offset - bytesSeeked;
62166  DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
62167  if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
62168  bytesSeeked += bytesRemainingToSeek;
62169  (void)bytesSeeked;
62170  oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
62171  break;
62172  }
62173  if (oggbs->bytesRemainingInPage > 0) {
62174  bytesSeeked += (int)oggbs->bytesRemainingInPage;
62175  oggbs->bytesRemainingInPage = 0;
62176  }
62177  DRFLAC_ASSERT(bytesRemainingToSeek > 0);
62179  return DRFLAC_FALSE;
62180  }
62181  }
62182  return DRFLAC_TRUE;
62183 }
62185 {
62186  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
62187  drflac_uint64 originalBytePos;
62188  drflac_uint64 runningGranulePosition;
62189  drflac_uint64 runningFrameBytePos;
62190  drflac_uint64 runningPCMFrameCount;
62191  DRFLAC_ASSERT(oggbs != NULL);
62192  originalBytePos = oggbs->currentBytePos;
62193  if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes)) {
62194  return DRFLAC_FALSE;
62195  }
62196  oggbs->bytesRemainingInPage = 0;
62197  runningGranulePosition = 0;
62198  for (;;) {
62200  drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start);
62201  return DRFLAC_FALSE;
62202  }
62203  runningFrameBytePos = oggbs->currentBytePos - drflac_ogg__get_page_header_size(&oggbs->currentPageHeader) - oggbs->pageDataSize;
62204  if (oggbs->currentPageHeader.granulePosition >= pcmFrameIndex) {
62205  break;
62206  }
62207  if ((oggbs->currentPageHeader.headerType & 0x01) == 0) {
62208  if (oggbs->currentPageHeader.segmentTable[0] >= 2) {
62209  drflac_uint8 firstBytesInPage[2];
62210  firstBytesInPage[0] = oggbs->pageData[0];
62211  firstBytesInPage[1] = oggbs->pageData[1];
62212  if ((firstBytesInPage[0] == 0xFF) && (firstBytesInPage[1] & 0xFC) == 0xF8) {
62213  runningGranulePosition = oggbs->currentPageHeader.granulePosition;
62214  }
62215  continue;
62216  }
62217  }
62218  }
62219  if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) {
62220  return DRFLAC_FALSE;
62221  }
62223  return DRFLAC_FALSE;
62224  }
62225  runningPCMFrameCount = runningGranulePosition;
62226  for (;;) {
62227  drflac_uint64 firstPCMFrameInFLACFrame = 0;
62228  drflac_uint64 lastPCMFrameInFLACFrame = 0;
62229  drflac_uint64 pcmFrameCountInThisFrame;
62231  return DRFLAC_FALSE;
62232  }
62233  drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
62234  pcmFrameCountInThisFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
62235  if (pcmFrameIndex == pFlac->totalPCMFrameCount && (runningPCMFrameCount + pcmFrameCountInThisFrame) == pFlac->totalPCMFrameCount) {
62236  drflac_result result = drflac__decode_flac_frame(pFlac);
62237  if (result == DRFLAC_SUCCESS) {
62238  pFlac->currentPCMFrame = pcmFrameIndex;
62240  return DRFLAC_TRUE;
62241  } else {
62242  return DRFLAC_FALSE;
62243  }
62244  }
62245  if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFrame)) {
62246  drflac_result result = drflac__decode_flac_frame(pFlac);
62247  if (result == DRFLAC_SUCCESS) {
62248  drflac_uint64 pcmFramesToDecode = (size_t)(pcmFrameIndex - runningPCMFrameCount);
62249  if (pcmFramesToDecode == 0) {
62250  return DRFLAC_TRUE;
62251  }
62252  pFlac->currentPCMFrame = runningPCMFrameCount;
62253  return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
62254  } else {
62255  if (result == DRFLAC_CRC_MISMATCH) {
62256  continue;
62257  } else {
62258  return DRFLAC_FALSE;
62259  }
62260  }
62261  } else {
62263  if (result == DRFLAC_SUCCESS) {
62264  runningPCMFrameCount += pcmFrameCountInThisFrame;
62265  } else {
62266  if (result == DRFLAC_CRC_MISMATCH) {
62267  continue;
62268  } else {
62269  return DRFLAC_FALSE;
62270  }
62271  }
62272  }
62273  }
62274 }
62275 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)
62276 {
62279  drflac_uint32 bytesRead = 0;
62280  (void)relaxed;
62282  pInit->oggFirstBytePos = 0;
62283  if (drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
62284  return DRFLAC_FALSE;
62285  }
62286  pInit->runningFilePos += bytesRead;
62287  for (;;) {
62288  int pageBodySize;
62289  if ((header.headerType & 0x02) == 0) {
62290  return DRFLAC_FALSE;
62291  }
62292  pageBodySize = drflac_ogg__get_page_body_size(&header);
62293  if (pageBodySize == 51) {
62294  drflac_uint32 bytesRemainingInPage = pageBodySize;
62295  drflac_uint8 packetType;
62296  if (onRead(pUserData, &packetType, 1) != 1) {
62297  return DRFLAC_FALSE;
62298  }
62299  bytesRemainingInPage -= 1;
62300  if (packetType == 0x7F) {
62301  drflac_uint8 sig[4];
62302  if (onRead(pUserData, sig, 4) != 4) {
62303  return DRFLAC_FALSE;
62304  }
62305  bytesRemainingInPage -= 4;
62306  if (sig[0] == 'F' && sig[1] == 'L' && sig[2] == 'A' && sig[3] == 'C') {
62307  drflac_uint8 mappingVersion[2];
62308  if (onRead(pUserData, mappingVersion, 2) != 2) {
62309  return DRFLAC_FALSE;
62310  }
62311  if (mappingVersion[0] != 1) {
62312  return DRFLAC_FALSE;
62313  }
62314  if (!onSeek(pUserData, 2, drflac_seek_origin_current)) {
62315  return DRFLAC_FALSE;
62316  }
62317  if (onRead(pUserData, sig, 4) != 4) {
62318  return DRFLAC_FALSE;
62319  }
62320  if (sig[0] == 'f' && sig[1] == 'L' && sig[2] == 'a' && sig[3] == 'C') {
62321  drflac_streaminfo streaminfo;
62322  drflac_uint8 isLastBlock;
62323  drflac_uint8 blockType;
62324  drflac_uint32 blockSize;
62325  if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
62326  return DRFLAC_FALSE;
62327  }
62328  if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
62329  return DRFLAC_FALSE;
62330  }
62331  if (drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
62333  pInit->sampleRate = streaminfo.sampleRate;
62334  pInit->channels = streaminfo.channels;
62335  pInit->bitsPerSample = streaminfo.bitsPerSample;
62336  pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
62338  pInit->hasMetadataBlocks = !isLastBlock;
62339  if (onMeta) {
62340  drflac_metadata metadata;
62342  metadata.pRawData = NULL;
62343  metadata.rawDataSize = 0;
62344  metadata.data.streaminfo = streaminfo;
62345  onMeta(pUserDataMD, &metadata);
62346  }
62347  pInit->runningFilePos += pageBodySize;
62348  pInit->oggFirstBytePos = pInit->runningFilePos - 79;
62349  pInit->oggSerial = header.serialNumber;
62350  pInit->oggBosHeader = header;
62351  break;
62352  } else {
62353  return DRFLAC_FALSE;
62354  }
62355  } else {
62356  return DRFLAC_FALSE;
62357  }
62358  } else {
62359  if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
62360  return DRFLAC_FALSE;
62361  }
62362  }
62363  } else {
62364  if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
62365  return DRFLAC_FALSE;
62366  }
62367  }
62368  } else {
62369  if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) {
62370  return DRFLAC_FALSE;
62371  }
62372  }
62373  pInit->runningFilePos += pageBodySize;
62374  if (drflac_ogg__read_page_header(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
62375  return DRFLAC_FALSE;
62376  }
62377  pInit->runningFilePos += bytesRead;
62378  }
62379  pInit->hasMetadataBlocks = DRFLAC_TRUE;
62380  return DRFLAC_TRUE;
62381 }
62382 #endif
62383 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)
62384 {
62385  drflac_bool32 relaxed;
62386  drflac_uint8 id[4];
62387  if (pInit == NULL || onRead == NULL || onSeek == NULL) {
62388  return DRFLAC_FALSE;
62389  }
62390  DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
62391  pInit->onRead = onRead;
62392  pInit->onSeek = onSeek;
62393  pInit->onMeta = onMeta;
62394  pInit->container = container;
62395  pInit->pUserData = pUserData;
62396  pInit->pUserDataMD = pUserDataMD;
62397  pInit->bs.onRead = onRead;
62398  pInit->bs.onSeek = onSeek;
62399  pInit->bs.pUserData = pUserData;
62400  drflac__reset_cache(&pInit->bs);
62401  relaxed = container != drflac_container_unknown;
62402  for (;;) {
62403  if (onRead(pUserData, id, 4) != 4) {
62404  return DRFLAC_FALSE;
62405  }
62406  pInit->runningFilePos += 4;
62407  if (id[0] == 'I' && id[1] == 'D' && id[2] == '3') {
62408  drflac_uint8 header[6];
62409  drflac_uint8 flags;
62410  drflac_uint32 headerSize;
62411  if (onRead(pUserData, header, 6) != 6) {
62412  return DRFLAC_FALSE;
62413  }
62414  pInit->runningFilePos += 6;
62415  flags = header[1];
62416  DRFLAC_COPY_MEMORY(&headerSize, header+2, 4);
62417  headerSize = drflac__unsynchsafe_32(drflac__be2host_32(headerSize));
62418  if (flags & 0x10) {
62419  headerSize += 10;
62420  }
62421  if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
62422  return DRFLAC_FALSE;
62423  }
62424  pInit->runningFilePos += headerSize;
62425  } else {
62426  break;
62427  }
62428  }
62429  if (id[0] == 'f' && id[1] == 'L' && id[2] == 'a' && id[3] == 'C') {
62430  return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
62431  }
62432 #ifndef DR_FLAC_NO_OGG
62433  if (id[0] == 'O' && id[1] == 'g' && id[2] == 'g' && id[3] == 'S') {
62434  return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
62435  }
62436 #endif
62437  if (relaxed) {
62438  if (container == drflac_container_native) {
62439  return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
62440  }
62441 #ifndef DR_FLAC_NO_OGG
62442  if (container == drflac_container_ogg) {
62443  return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
62444  }
62445 #endif
62446  }
62447  return DRFLAC_FALSE;
62448 }
62449 static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
62450 {
62451  DRFLAC_ASSERT(pFlac != NULL);
62452  DRFLAC_ASSERT(pInit != NULL);
62453  DRFLAC_ZERO_MEMORY(pFlac, sizeof(*pFlac));
62454  pFlac->bs = pInit->bs;
62455  pFlac->onMeta = pInit->onMeta;
62456  pFlac->pUserDataMD = pInit->pUserDataMD;
62458  pFlac->sampleRate = pInit->sampleRate;
62459  pFlac->channels = (drflac_uint8)pInit->channels;
62460  pFlac->bitsPerSample = (drflac_uint8)pInit->bitsPerSample;
62461  pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount;
62462  pFlac->container = pInit->container;
62463 }
62464 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)
62465 {
62467  drflac_uint32 allocationSize;
62468  drflac_uint32 wholeSIMDVectorCountPerChannel;
62469  drflac_uint32 decodedSamplesAllocationSize;
62470 #ifndef DR_FLAC_NO_OGG
62471  drflac_oggbs oggbs;
62472 #endif
62473  drflac_uint64 firstFramePos;
62474  drflac_uint64 seektablePos;
62475  drflac_uint32 seektableSize;
62476  drflac_allocation_callbacks allocationCallbacks;
62477  drflac* pFlac;
62479  if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
62480  return NULL;
62481  }
62482  if (pAllocationCallbacks != NULL) {
62483  allocationCallbacks = *pAllocationCallbacks;
62484  if (allocationCallbacks.onFree == NULL || (allocationCallbacks.onMalloc == NULL && allocationCallbacks.onRealloc == NULL)) {
62485  return NULL;
62486  }
62487  } else {
62488  allocationCallbacks.pUserData = NULL;
62489  allocationCallbacks.onMalloc = drflac__malloc_default;
62490  allocationCallbacks.onRealloc = drflac__realloc_default;
62491  allocationCallbacks.onFree = drflac__free_default;
62492  }
62493  allocationSize = sizeof(drflac);
62494  if ((init.maxBlockSizeInPCMFrames % (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) == 0) {
62495  wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32)));
62496  } else {
62497  wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) + 1;
62498  }
62499  decodedSamplesAllocationSize = wholeSIMDVectorCountPerChannel * DRFLAC_MAX_SIMD_VECTOR_SIZE * init.channels;
62500  allocationSize += decodedSamplesAllocationSize;
62501  allocationSize += DRFLAC_MAX_SIMD_VECTOR_SIZE;
62502 #ifndef DR_FLAC_NO_OGG
62503  if (init.container == drflac_container_ogg) {
62504  allocationSize += sizeof(drflac_oggbs);
62505  }
62506  DRFLAC_ZERO_MEMORY(&oggbs, sizeof(oggbs));
62507  if (init.container == drflac_container_ogg) {
62508  oggbs.onRead = onRead;
62509  oggbs.onSeek = onSeek;
62510  oggbs.pUserData = pUserData;
62511  oggbs.currentBytePos = init.oggFirstBytePos;
62512  oggbs.firstBytePos = init.oggFirstBytePos;
62513  oggbs.serialNumber = init.oggSerial;
62514  oggbs.bosPageHeader = init.oggBosHeader;
62515  oggbs.bytesRemainingInPage = 0;
62516  }
62517 #endif
62518  firstFramePos = 42;
62519  seektablePos = 0;
62520  seektableSize = 0;
62521  if (init.hasMetadataBlocks) {
62522  drflac_read_proc onReadOverride = onRead;
62523  drflac_seek_proc onSeekOverride = onSeek;
62524  void* pUserDataOverride = pUserData;
62525 #ifndef DR_FLAC_NO_OGG
62526  if (init.container == drflac_container_ogg) {
62527  onReadOverride = drflac__on_read_ogg;
62528  onSeekOverride = drflac__on_seek_ogg;
62529  pUserDataOverride = (void*)&oggbs;
62530  }
62531 #endif
62532  if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
62533  return NULL;
62534  }
62535  allocationSize += seektableSize;
62536  }
62537  pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
62538  if (pFlac == NULL) {
62539  return NULL;
62540  }
62541  drflac__init_from_info(pFlac, &init);
62542  pFlac->allocationCallbacks = allocationCallbacks;
62544 #ifndef DR_FLAC_NO_OGG
62545  if (init.container == drflac_container_ogg) {
62546  drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + seektableSize);
62547  *pInternalOggbs = oggbs;
62548  pFlac->bs.onRead = drflac__on_read_ogg;
62549  pFlac->bs.onSeek = drflac__on_seek_ogg;
62550  pFlac->bs.pUserData = (void*)pInternalOggbs;
62551  pFlac->_oggbs = (void*)pInternalOggbs;
62552  }
62553 #endif
62554  pFlac->firstFLACFramePosInBytes = firstFramePos;
62555 #ifndef DR_FLAC_NO_OGG
62556  if (init.container == drflac_container_ogg)
62557  {
62558  pFlac->pSeekpoints = NULL;
62559  pFlac->seekpointCount = 0;
62560  }
62561  else
62562 #endif
62563  {
62564  if (seektablePos != 0) {
62565  pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
62566  pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
62567  DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
62568  DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
62569  if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
62570  if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
62571  drflac_uint32 iSeekpoint;
62572  for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
62573  pFlac->pSeekpoints[iSeekpoint].firstPCMFrame = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
62574  pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
62575  pFlac->pSeekpoints[iSeekpoint].pcmFrameCount = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
62576  }
62577  } else {
62578  pFlac->pSeekpoints = NULL;
62579  pFlac->seekpointCount = 0;
62580  }
62581  if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
62582  drflac__free_from_callbacks(pFlac, &allocationCallbacks);
62583  return NULL;
62584  }
62585  } else {
62586  pFlac->pSeekpoints = NULL;
62587  pFlac->seekpointCount = 0;
62588  }
62589  }
62590  }
62591  if (!init.hasStreamInfoBlock) {
62592  pFlac->currentFLACFrame.header = init.firstFrameHeader;
62593  for (;;) {
62594  drflac_result result = drflac__decode_flac_frame(pFlac);
62595  if (result == DRFLAC_SUCCESS) {
62596  break;
62597  } else {
62598  if (result == DRFLAC_CRC_MISMATCH) {
62600  drflac__free_from_callbacks(pFlac, &allocationCallbacks);
62601  return NULL;
62602  }
62603  continue;
62604  } else {
62605  drflac__free_from_callbacks(pFlac, &allocationCallbacks);
62606  return NULL;
62607  }
62608  }
62609  }
62610  }
62611  return pFlac;
62612 }
62613 #ifndef DR_FLAC_NO_STDIO
62614 #include <stdio.h>
62615 #include <wchar.h>
62616 #include <errno.h>
62618 {
62619  switch (e)
62620  {
62621  case 0: return DRFLAC_SUCCESS;
62622  #ifdef EPERM
62623  case EPERM: return DRFLAC_INVALID_OPERATION;
62624  #endif
62625  #ifdef ENOENT
62626  case ENOENT: return DRFLAC_DOES_NOT_EXIST;
62627  #endif
62628  #ifdef ESRCH
62629  case ESRCH: return DRFLAC_DOES_NOT_EXIST;
62630  #endif
62631  #ifdef EINTR
62632  case EINTR: return DRFLAC_INTERRUPT;
62633  #endif
62634  #ifdef EIO
62635  case EIO: return DRFLAC_IO_ERROR;
62636  #endif
62637  #ifdef ENXIO
62638  case ENXIO: return DRFLAC_DOES_NOT_EXIST;
62639  #endif
62640  #ifdef E2BIG
62641  case E2BIG: return DRFLAC_INVALID_ARGS;
62642  #endif
62643  #ifdef ENOEXEC
62644  case ENOEXEC: return DRFLAC_INVALID_FILE;
62645  #endif
62646  #ifdef EBADF
62647  case EBADF: return DRFLAC_INVALID_FILE;
62648  #endif
62649  #ifdef ECHILD
62650  case ECHILD: return DRFLAC_ERROR;
62651  #endif
62652  #ifdef EAGAIN
62653  case EAGAIN: return DRFLAC_UNAVAILABLE;
62654  #endif
62655  #ifdef ENOMEM
62656  case ENOMEM: return DRFLAC_OUT_OF_MEMORY;
62657  #endif
62658  #ifdef EACCES
62659  case EACCES: return DRFLAC_ACCESS_DENIED;
62660  #endif
62661  #ifdef EFAULT
62662  case EFAULT: return DRFLAC_BAD_ADDRESS;
62663  #endif
62664  #ifdef ENOTBLK
62665  case ENOTBLK: return DRFLAC_ERROR;
62666  #endif
62667  #ifdef EBUSY
62668  case EBUSY: return DRFLAC_BUSY;
62669  #endif
62670  #ifdef EEXIST
62671  case EEXIST: return DRFLAC_ALREADY_EXISTS;
62672  #endif
62673  #ifdef EXDEV
62674  case EXDEV: return DRFLAC_ERROR;
62675  #endif
62676  #ifdef ENODEV
62677  case ENODEV: return DRFLAC_DOES_NOT_EXIST;
62678  #endif
62679  #ifdef ENOTDIR
62680  case ENOTDIR: return DRFLAC_NOT_DIRECTORY;
62681  #endif
62682  #ifdef EISDIR
62683  case EISDIR: return DRFLAC_IS_DIRECTORY;
62684  #endif
62685  #ifdef EINVAL
62686  case EINVAL: return DRFLAC_INVALID_ARGS;
62687  #endif
62688  #ifdef ENFILE
62689  case ENFILE: return DRFLAC_TOO_MANY_OPEN_FILES;
62690  #endif
62691  #ifdef EMFILE
62692  case EMFILE: return DRFLAC_TOO_MANY_OPEN_FILES;
62693  #endif
62694  #ifdef ENOTTY
62695  case ENOTTY: return DRFLAC_INVALID_OPERATION;
62696  #endif
62697  #ifdef ETXTBSY
62698  case ETXTBSY: return DRFLAC_BUSY;
62699  #endif
62700  #ifdef EFBIG
62701  case EFBIG: return DRFLAC_TOO_BIG;
62702  #endif
62703  #ifdef ENOSPC
62704  case ENOSPC: return DRFLAC_NO_SPACE;
62705  #endif
62706  #ifdef ESPIPE
62707  case ESPIPE: return DRFLAC_BAD_SEEK;
62708  #endif
62709  #ifdef EROFS
62710  case EROFS: return DRFLAC_ACCESS_DENIED;
62711  #endif
62712  #ifdef EMLINK
62713  case EMLINK: return DRFLAC_TOO_MANY_LINKS;
62714  #endif
62715  #ifdef EPIPE
62716  case EPIPE: return DRFLAC_BAD_PIPE;
62717  #endif
62718  #ifdef EDOM
62719  case EDOM: return DRFLAC_OUT_OF_RANGE;
62720  #endif
62721  #ifdef ERANGE
62722  case ERANGE: return DRFLAC_OUT_OF_RANGE;
62723  #endif
62724  #ifdef EDEADLK
62725  case EDEADLK: return DRFLAC_DEADLOCK;
62726  #endif
62727  #ifdef ENAMETOOLONG
62728  case ENAMETOOLONG: return DRFLAC_PATH_TOO_LONG;
62729  #endif
62730  #ifdef ENOLCK
62731  case ENOLCK: return DRFLAC_ERROR;
62732  #endif
62733  #ifdef ENOSYS
62734  case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
62735  #endif
62736  #ifdef ENOTEMPTY
62737  case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
62738  #endif
62739  #ifdef ELOOP
62740  case ELOOP: return DRFLAC_TOO_MANY_LINKS;
62741  #endif
62742  #ifdef ENOMSG
62743  case ENOMSG: return DRFLAC_NO_MESSAGE;
62744  #endif
62745  #ifdef EIDRM
62746  case EIDRM: return DRFLAC_ERROR;
62747  #endif
62748  #ifdef ECHRNG
62749  case ECHRNG: return DRFLAC_ERROR;
62750  #endif
62751  #ifdef EL2NSYNC
62752  case EL2NSYNC: return DRFLAC_ERROR;
62753  #endif
62754  #ifdef EL3HLT
62755  case EL3HLT: return DRFLAC_ERROR;
62756  #endif
62757  #ifdef EL3RST
62758  case EL3RST: return DRFLAC_ERROR;
62759  #endif
62760  #ifdef ELNRNG
62761  case ELNRNG: return DRFLAC_OUT_OF_RANGE;
62762  #endif
62763  #ifdef EUNATCH
62764  case EUNATCH: return DRFLAC_ERROR;
62765  #endif
62766  #ifdef ENOCSI
62767  case ENOCSI: return DRFLAC_ERROR;
62768  #endif
62769  #ifdef EL2HLT
62770  case EL2HLT: return DRFLAC_ERROR;
62771  #endif
62772  #ifdef EBADE
62773  case EBADE: return DRFLAC_ERROR;
62774  #endif
62775  #ifdef EBADR
62776  case EBADR: return DRFLAC_ERROR;
62777  #endif
62778  #ifdef EXFULL
62779  case EXFULL: return DRFLAC_ERROR;
62780  #endif
62781  #ifdef ENOANO
62782  case ENOANO: return DRFLAC_ERROR;
62783  #endif
62784  #ifdef EBADRQC
62785  case EBADRQC: return DRFLAC_ERROR;
62786  #endif
62787  #ifdef EBADSLT
62788  case EBADSLT: return DRFLAC_ERROR;
62789  #endif
62790  #ifdef EBFONT
62791  case EBFONT: return DRFLAC_INVALID_FILE;
62792  #endif
62793  #ifdef ENOSTR
62794  case ENOSTR: return DRFLAC_ERROR;
62795  #endif
62796  #ifdef ENODATA
62797  case ENODATA: return DRFLAC_NO_DATA_AVAILABLE;
62798  #endif
62799  #ifdef ETIME
62800  case ETIME: return DRFLAC_TIMEOUT;
62801  #endif
62802  #ifdef ENOSR
62803  case ENOSR: return DRFLAC_NO_DATA_AVAILABLE;
62804  #endif
62805  #ifdef ENONET
62806  case ENONET: return DRFLAC_NO_NETWORK;
62807  #endif
62808  #ifdef ENOPKG
62809  case ENOPKG: return DRFLAC_ERROR;
62810  #endif
62811  #ifdef EREMOTE
62812  case EREMOTE: return DRFLAC_ERROR;
62813  #endif
62814  #ifdef ENOLINK
62815  case ENOLINK: return DRFLAC_ERROR;
62816  #endif
62817  #ifdef EADV
62818  case EADV: return DRFLAC_ERROR;
62819  #endif
62820  #ifdef ESRMNT
62821  case ESRMNT: return DRFLAC_ERROR;
62822  #endif
62823  #ifdef ECOMM
62824  case ECOMM: return DRFLAC_ERROR;
62825  #endif
62826  #ifdef EPROTO
62827  case EPROTO: return DRFLAC_ERROR;
62828  #endif
62829  #ifdef EMULTIHOP
62830  case EMULTIHOP: return DRFLAC_ERROR;
62831  #endif
62832  #ifdef EDOTDOT
62833  case EDOTDOT: return DRFLAC_ERROR;
62834  #endif
62835  #ifdef EBADMSG
62836  case EBADMSG: return DRFLAC_BAD_MESSAGE;
62837  #endif
62838  #ifdef EOVERFLOW
62839  case EOVERFLOW: return DRFLAC_TOO_BIG;
62840  #endif
62841  #ifdef ENOTUNIQ
62842  case ENOTUNIQ: return DRFLAC_NOT_UNIQUE;
62843  #endif
62844  #ifdef EBADFD
62845  case EBADFD: return DRFLAC_ERROR;
62846  #endif
62847  #ifdef EREMCHG
62848  case EREMCHG: return DRFLAC_ERROR;
62849  #endif
62850  #ifdef ELIBACC
62851  case ELIBACC: return DRFLAC_ACCESS_DENIED;
62852  #endif
62853  #ifdef ELIBBAD
62854  case ELIBBAD: return DRFLAC_INVALID_FILE;
62855  #endif
62856  #ifdef ELIBSCN
62857  case ELIBSCN: return DRFLAC_INVALID_FILE;
62858  #endif
62859  #ifdef ELIBMAX
62860  case ELIBMAX: return DRFLAC_ERROR;
62861  #endif
62862  #ifdef ELIBEXEC
62863  case ELIBEXEC: return DRFLAC_ERROR;
62864  #endif
62865  #ifdef EILSEQ
62866  case EILSEQ: return DRFLAC_INVALID_DATA;
62867  #endif
62868  #ifdef ERESTART
62869  case ERESTART: return DRFLAC_ERROR;
62870  #endif
62871  #ifdef ESTRPIPE
62872  case ESTRPIPE: return DRFLAC_ERROR;
62873  #endif
62874  #ifdef EUSERS
62875  case EUSERS: return DRFLAC_ERROR;
62876  #endif
62877  #ifdef ENOTSOCK
62878  case ENOTSOCK: return DRFLAC_NOT_SOCKET;
62879  #endif
62880  #ifdef EDESTADDRREQ
62881  case EDESTADDRREQ: return DRFLAC_NO_ADDRESS;
62882  #endif
62883  #ifdef EMSGSIZE
62884  case EMSGSIZE: return DRFLAC_TOO_BIG;
62885  #endif
62886  #ifdef EPROTOTYPE
62887  case EPROTOTYPE: return DRFLAC_BAD_PROTOCOL;
62888  #endif
62889  #ifdef ENOPROTOOPT
62890  case ENOPROTOOPT: return DRFLAC_PROTOCOL_UNAVAILABLE;
62891  #endif
62892  #ifdef EPROTONOSUPPORT
62893  case EPROTONOSUPPORT: return DRFLAC_PROTOCOL_NOT_SUPPORTED;
62894  #endif
62895  #ifdef ESOCKTNOSUPPORT
62896  case ESOCKTNOSUPPORT: return DRFLAC_SOCKET_NOT_SUPPORTED;
62897  #endif
62898  #ifdef EOPNOTSUPP
62899  case EOPNOTSUPP: return DRFLAC_INVALID_OPERATION;
62900  #endif
62901  #ifdef EPFNOSUPPORT
62902  case EPFNOSUPPORT: return DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED;
62903  #endif
62904  #ifdef EAFNOSUPPORT
62905  case EAFNOSUPPORT: return DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED;
62906  #endif
62907  #ifdef EADDRINUSE
62908  case EADDRINUSE: return DRFLAC_ALREADY_IN_USE;
62909  #endif
62910  #ifdef EADDRNOTAVAIL
62911  case EADDRNOTAVAIL: return DRFLAC_ERROR;
62912  #endif
62913  #ifdef ENETDOWN
62914  case ENETDOWN: return DRFLAC_NO_NETWORK;
62915  #endif
62916  #ifdef ENETUNREACH
62917  case ENETUNREACH: return DRFLAC_NO_NETWORK;
62918  #endif
62919  #ifdef ENETRESET
62920  case ENETRESET: return DRFLAC_NO_NETWORK;
62921  #endif
62922  #ifdef ECONNABORTED
62923  case ECONNABORTED: return DRFLAC_NO_NETWORK;
62924  #endif
62925  #ifdef ECONNRESET
62926  case ECONNRESET: return DRFLAC_CONNECTION_RESET;
62927  #endif
62928  #ifdef ENOBUFS
62929  case ENOBUFS: return DRFLAC_NO_SPACE;
62930  #endif
62931  #ifdef EISCONN
62932  case EISCONN: return DRFLAC_ALREADY_CONNECTED;
62933  #endif
62934  #ifdef ENOTCONN
62935  case ENOTCONN: return DRFLAC_NOT_CONNECTED;
62936  #endif
62937  #ifdef ESHUTDOWN
62938  case ESHUTDOWN: return DRFLAC_ERROR;
62939  #endif
62940  #ifdef ETOOMANYREFS
62941  case ETOOMANYREFS: return DRFLAC_ERROR;
62942  #endif
62943  #ifdef ETIMEDOUT
62944  case ETIMEDOUT: return DRFLAC_TIMEOUT;
62945  #endif
62946  #ifdef ECONNREFUSED
62947  case ECONNREFUSED: return DRFLAC_CONNECTION_REFUSED;
62948  #endif
62949  #ifdef EHOSTDOWN
62950  case EHOSTDOWN: return DRFLAC_NO_HOST;
62951  #endif
62952  #ifdef EHOSTUNREACH
62953  case EHOSTUNREACH: return DRFLAC_NO_HOST;
62954  #endif
62955  #ifdef EALREADY
62956  case EALREADY: return DRFLAC_IN_PROGRESS;
62957  #endif
62958  #ifdef EINPROGRESS
62959  case EINPROGRESS: return DRFLAC_IN_PROGRESS;
62960  #endif
62961  #ifdef ESTALE
62962  case ESTALE: return DRFLAC_INVALID_FILE;
62963  #endif
62964  #ifdef EUCLEAN
62965  case EUCLEAN: return DRFLAC_ERROR;
62966  #endif
62967  #ifdef ENOTNAM
62968  case ENOTNAM: return DRFLAC_ERROR;
62969  #endif
62970  #ifdef ENAVAIL
62971  case ENAVAIL: return DRFLAC_ERROR;
62972  #endif
62973  #ifdef EISNAM
62974  case EISNAM: return DRFLAC_ERROR;
62975  #endif
62976  #ifdef EREMOTEIO
62977  case EREMOTEIO: return DRFLAC_IO_ERROR;
62978  #endif
62979  #ifdef EDQUOT
62980  case EDQUOT: return DRFLAC_NO_SPACE;
62981  #endif
62982  #ifdef ENOMEDIUM
62983  case ENOMEDIUM: return DRFLAC_DOES_NOT_EXIST;
62984  #endif
62985  #ifdef EMEDIUMTYPE
62986  case EMEDIUMTYPE: return DRFLAC_ERROR;
62987  #endif
62988  #ifdef ECANCELED
62989  case ECANCELED: return DRFLAC_CANCELLED;
62990  #endif
62991  #ifdef ENOKEY
62992  case ENOKEY: return DRFLAC_ERROR;
62993  #endif
62994  #ifdef EKEYEXPIRED
62995  case EKEYEXPIRED: return DRFLAC_ERROR;
62996  #endif
62997  #ifdef EKEYREVOKED
62998  case EKEYREVOKED: return DRFLAC_ERROR;
62999  #endif
63000  #ifdef EKEYREJECTED
63001  case EKEYREJECTED: return DRFLAC_ERROR;
63002  #endif
63003  #ifdef EOWNERDEAD
63004  case EOWNERDEAD: return DRFLAC_ERROR;
63005  #endif
63006  #ifdef ENOTRECOVERABLE
63007  case ENOTRECOVERABLE: return DRFLAC_ERROR;
63008  #endif
63009  #ifdef ERFKILL
63010  case ERFKILL: return DRFLAC_ERROR;
63011  #endif
63012  #ifdef EHWPOISON
63013  case EHWPOISON: return DRFLAC_ERROR;
63014  #endif
63015  default: return DRFLAC_ERROR;
63016  }
63017 }
63018 static drflac_result drflac_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
63019 {
63020 #if defined(_MSC_VER) && _MSC_VER >= 1400
63021  errno_t err;
63022 #endif
63023  if (ppFile != NULL) {
63024  *ppFile = NULL;
63025  }
63026  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
63027  return DRFLAC_INVALID_ARGS;
63028  }
63029 #if defined(_MSC_VER) && _MSC_VER >= 1400
63030  err = fopen_s(ppFile, pFilePath, pOpenMode);
63031  if (err != 0) {
63032  return drflac_result_from_errno(err);
63033  }
63034 #else
63035 #if defined(_WIN32) || defined(__APPLE__)
63036  *ppFile = fopen(pFilePath, pOpenMode);
63037 #else
63038  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
63039  *ppFile = fopen64(pFilePath, pOpenMode);
63040  #else
63041  *ppFile = fopen(pFilePath, pOpenMode);
63042  #endif
63043 #endif
63044  if (*ppFile == NULL) {
63046  if (result == DRFLAC_SUCCESS) {
63047  result = DRFLAC_ERROR;
63048  }
63049  return result;
63050  }
63051 #endif
63052  return DRFLAC_SUCCESS;
63053 }
63054 #if defined(_WIN32)
63055  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
63056  #define DRFLAC_HAS_WFOPEN
63057  #endif
63058 #endif
63059 static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
63060 {
63061  if (ppFile != NULL) {
63062  *ppFile = NULL;
63063  }
63064  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
63065  return DRFLAC_INVALID_ARGS;
63066  }
63067 #if defined(DRFLAC_HAS_WFOPEN)
63068  {
63069  #if defined(_MSC_VER) && _MSC_VER >= 1400
63070  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
63071  if (err != 0) {
63072  return drflac_result_from_errno(err);
63073  }
63074  #else
63075  *ppFile = _wfopen(pFilePath, pOpenMode);
63076  if (*ppFile == NULL) {
63078  }
63079  #endif
63080  (void)pAllocationCallbacks;
63081  }
63082 #else
63083  {
63084  mbstate_t mbs;
63085  size_t lenMB;
63086  const wchar_t* pFilePathTemp = pFilePath;
63087  char* pFilePathMB = NULL;
63088  char pOpenModeMB[32] = {0};
63089  DRFLAC_ZERO_OBJECT(&mbs);
63090  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
63091  if (lenMB == (size_t)-1) {
63093  }
63094  pFilePathMB = (char*)drflac__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
63095  if (pFilePathMB == NULL) {
63096  return DRFLAC_OUT_OF_MEMORY;
63097  }
63098  pFilePathTemp = pFilePath;
63099  DRFLAC_ZERO_OBJECT(&mbs);
63100  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
63101  {
63102  size_t i = 0;
63103  for (;;) {
63104  if (pOpenMode[i] == 0) {
63105  pOpenModeMB[i] = '\0';
63106  break;
63107  }
63108  pOpenModeMB[i] = (char)pOpenMode[i];
63109  i += 1;
63110  }
63111  }
63112  *ppFile = fopen(pFilePathMB, pOpenModeMB);
63113  drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
63114  }
63115  if (*ppFile == NULL) {
63116  return DRFLAC_ERROR;
63117  }
63118 #endif
63119  return DRFLAC_SUCCESS;
63120 }
63121 static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
63122 {
63123  return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
63124 }
63125 static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
63126 {
63127  DRFLAC_ASSERT(offset >= 0);
63128  return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
63129 }
63130 DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
63131 {
63132  drflac* pFlac;
63133  FILE* pFile;
63134  if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
63135  return NULL;
63136  }
63137  pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
63138  if (pFlac == NULL) {
63139  fclose(pFile);
63140  return NULL;
63141  }
63142  return pFlac;
63143 }
63144 DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
63145 {
63146  drflac* pFlac;
63147  FILE* pFile;
63148  if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
63149  return NULL;
63150  }
63151  pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
63152  if (pFlac == NULL) {
63153  fclose(pFile);
63154  return NULL;
63155  }
63156  return pFlac;
63157 }
63158 DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
63159 {
63160  drflac* pFlac;
63161  FILE* pFile;
63162  if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
63163  return NULL;
63164  }
63165  pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
63166  if (pFlac == NULL) {
63167  fclose(pFile);
63168  return pFlac;
63169  }
63170  return pFlac;
63171 }
63172 DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
63173 {
63174  drflac* pFlac;
63175  FILE* pFile;
63176  if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
63177  return NULL;
63178  }
63179  pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
63180  if (pFlac == NULL) {
63181  fclose(pFile);
63182  return pFlac;
63183  }
63184  return pFlac;
63185 }
63186 #endif
63187 static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
63188 {
63189  drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
63190  size_t bytesRemaining;
63191  DRFLAC_ASSERT(memoryStream != NULL);
63192  DRFLAC_ASSERT(memoryStream->dataSize >= memoryStream->currentReadPos);
63193  bytesRemaining = memoryStream->dataSize - memoryStream->currentReadPos;
63194  if (bytesToRead > bytesRemaining) {
63195  bytesToRead = bytesRemaining;
63196  }
63197  if (bytesToRead > 0) {
63198  DRFLAC_COPY_MEMORY(bufferOut, memoryStream->data + memoryStream->currentReadPos, bytesToRead);
63199  memoryStream->currentReadPos += bytesToRead;
63200  }
63201  return bytesToRead;
63202 }
63203 static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
63204 {
63205  drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
63206  DRFLAC_ASSERT(memoryStream != NULL);
63207  DRFLAC_ASSERT(offset >= 0);
63208  if (offset > (drflac_int64)memoryStream->dataSize) {
63209  return DRFLAC_FALSE;
63210  }
63211  if (origin == drflac_seek_origin_current) {
63212  if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
63213  memoryStream->currentReadPos += offset;
63214  } else {
63215  return DRFLAC_FALSE;
63216  }
63217  } else {
63218  if ((drflac_uint32)offset <= memoryStream->dataSize) {
63219  memoryStream->currentReadPos = offset;
63220  } else {
63221  return DRFLAC_FALSE;
63222  }
63223  }
63224  return DRFLAC_TRUE;
63225 }
63226 DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks)
63227 {
63228  drflac__memory_stream memoryStream;
63229  drflac* pFlac;
63230  memoryStream.data = (const drflac_uint8*)pData;
63231  memoryStream.dataSize = dataSize;
63232  memoryStream.currentReadPos = 0;
63233  pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
63234  if (pFlac == NULL) {
63235  return NULL;
63236  }
63237  pFlac->memoryStream = memoryStream;
63238 #ifndef DR_FLAC_NO_OGG
63239  if (pFlac->container == drflac_container_ogg)
63240  {
63241  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
63242  oggbs->pUserData = &pFlac->memoryStream;
63243  }
63244  else
63245 #endif
63246  {
63247  pFlac->bs.pUserData = &pFlac->memoryStream;
63248  }
63249  return pFlac;
63250 }
63251 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)
63252 {
63253  drflac__memory_stream memoryStream;
63254  drflac* pFlac;
63255  memoryStream.data = (const drflac_uint8*)pData;
63256  memoryStream.dataSize = dataSize;
63257  memoryStream.currentReadPos = 0;
63258  pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
63259  if (pFlac == NULL) {
63260  return NULL;
63261  }
63262  pFlac->memoryStream = memoryStream;
63263 #ifndef DR_FLAC_NO_OGG
63264  if (pFlac->container == drflac_container_ogg)
63265  {
63266  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
63267  oggbs->pUserData = &pFlac->memoryStream;
63268  }
63269  else
63270 #endif
63271  {
63272  pFlac->bs.pUserData = &pFlac->memoryStream;
63273  }
63274  return pFlac;
63275 }
63276 DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
63277 {
63278  return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
63279 }
63280 DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
63281 {
63282  return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
63283 }
63284 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)
63285 {
63286  return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
63287 }
63288 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)
63289 {
63290  return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
63291 }
63292 DRFLAC_API void drflac_close(drflac* pFlac)
63293 {
63294  if (pFlac == NULL) {
63295  return;
63296  }
63297 #ifndef DR_FLAC_NO_STDIO
63298  if (pFlac->bs.onRead == drflac__on_read_stdio) {
63299  fclose((FILE*)pFlac->bs.pUserData);
63300  }
63301 #ifndef DR_FLAC_NO_OGG
63302  if (pFlac->container == drflac_container_ogg) {
63303  drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
63305  if (oggbs->onRead == drflac__on_read_stdio) {
63306  fclose((FILE*)oggbs->pUserData);
63307  }
63308  }
63309 #endif
63310 #endif
63312 }
63313 #if 0
63314 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)
63315 {
63316  drflac_uint64 i;
63317  for (i = 0; i < frameCount; ++i) {
63318  drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
63319  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
63320  drflac_uint32 right = left - side;
63321  pOutputSamples[i*2+0] = (drflac_int32)left;
63322  pOutputSamples[i*2+1] = (drflac_int32)right;
63323  }
63324 }
63325 #endif
63326 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)
63327 {
63328  drflac_uint64 i;
63329  drflac_uint64 frameCount4 = frameCount >> 2;
63330  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63331  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63332  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63333  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63334  for (i = 0; i < frameCount4; ++i) {
63335  drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
63336  drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
63337  drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
63338  drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
63339  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
63340  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
63341  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
63342  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
63343  drflac_uint32 right0 = left0 - side0;
63344  drflac_uint32 right1 = left1 - side1;
63345  drflac_uint32 right2 = left2 - side2;
63346  drflac_uint32 right3 = left3 - side3;
63347  pOutputSamples[i*8+0] = (drflac_int32)left0;
63348  pOutputSamples[i*8+1] = (drflac_int32)right0;
63349  pOutputSamples[i*8+2] = (drflac_int32)left1;
63350  pOutputSamples[i*8+3] = (drflac_int32)right1;
63351  pOutputSamples[i*8+4] = (drflac_int32)left2;
63352  pOutputSamples[i*8+5] = (drflac_int32)right2;
63353  pOutputSamples[i*8+6] = (drflac_int32)left3;
63354  pOutputSamples[i*8+7] = (drflac_int32)right3;
63355  }
63356  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63357  drflac_uint32 left = pInputSamples0U32[i] << shift0;
63358  drflac_uint32 side = pInputSamples1U32[i] << shift1;
63359  drflac_uint32 right = left - side;
63360  pOutputSamples[i*2+0] = (drflac_int32)left;
63361  pOutputSamples[i*2+1] = (drflac_int32)right;
63362  }
63363 }
63364 #if defined(DRFLAC_SUPPORT_SSE2)
63365 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)
63366 {
63367  drflac_uint64 i;
63368  drflac_uint64 frameCount4 = frameCount >> 2;
63369  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63370  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63371  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63372  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63373  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
63374  for (i = 0; i < frameCount4; ++i) {
63375  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
63376  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
63377  __m128i right = _mm_sub_epi32(left, side);
63378  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
63379  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
63380  }
63381  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63382  drflac_uint32 left = pInputSamples0U32[i] << shift0;
63383  drflac_uint32 side = pInputSamples1U32[i] << shift1;
63384  drflac_uint32 right = left - side;
63385  pOutputSamples[i*2+0] = (drflac_int32)left;
63386  pOutputSamples[i*2+1] = (drflac_int32)right;
63387  }
63388 }
63389 #endif
63390 #if defined(DRFLAC_SUPPORT_NEON)
63391 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)
63392 {
63393  drflac_uint64 i;
63394  drflac_uint64 frameCount4 = frameCount >> 2;
63395  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63396  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63397  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63398  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63399  int32x4_t shift0_4;
63400  int32x4_t shift1_4;
63401  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
63402  shift0_4 = vdupq_n_s32(shift0);
63403  shift1_4 = vdupq_n_s32(shift1);
63404  for (i = 0; i < frameCount4; ++i) {
63405  uint32x4_t left;
63406  uint32x4_t side;
63407  uint32x4_t right;
63408  left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
63409  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
63410  right = vsubq_u32(left, side);
63411  drflac__vst2q_u32((drflac_uint32*)pOutputSamples + i*8, vzipq_u32(left, right));
63412  }
63413  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63414  drflac_uint32 left = pInputSamples0U32[i] << shift0;
63415  drflac_uint32 side = pInputSamples1U32[i] << shift1;
63416  drflac_uint32 right = left - side;
63417  pOutputSamples[i*2+0] = (drflac_int32)left;
63418  pOutputSamples[i*2+1] = (drflac_int32)right;
63419  }
63420 }
63421 #endif
63422 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)
63423 {
63424 #if defined(DRFLAC_SUPPORT_SSE2)
63425  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
63426  drflac_read_pcm_frames_s32__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63427  } else
63428 #elif defined(DRFLAC_SUPPORT_NEON)
63429  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
63430  drflac_read_pcm_frames_s32__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63431  } else
63432 #endif
63433  {
63434 #if 0
63435  drflac_read_pcm_frames_s32__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63436 #else
63437  drflac_read_pcm_frames_s32__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63438 #endif
63439  }
63440 }
63441 #if 0
63442 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)
63443 {
63444  drflac_uint64 i;
63445  for (i = 0; i < frameCount; ++i) {
63446  drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
63447  drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
63448  drflac_uint32 left = right + side;
63449  pOutputSamples[i*2+0] = (drflac_int32)left;
63450  pOutputSamples[i*2+1] = (drflac_int32)right;
63451  }
63452 }
63453 #endif
63454 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)
63455 {
63456  drflac_uint64 i;
63457  drflac_uint64 frameCount4 = frameCount >> 2;
63458  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63459  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63460  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63461  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63462  for (i = 0; i < frameCount4; ++i) {
63463  drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
63464  drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
63465  drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
63466  drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
63467  drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
63468  drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
63469  drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
63470  drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
63471  drflac_uint32 left0 = right0 + side0;
63472  drflac_uint32 left1 = right1 + side1;
63473  drflac_uint32 left2 = right2 + side2;
63474  drflac_uint32 left3 = right3 + side3;
63475  pOutputSamples[i*8+0] = (drflac_int32)left0;
63476  pOutputSamples[i*8+1] = (drflac_int32)right0;
63477  pOutputSamples[i*8+2] = (drflac_int32)left1;
63478  pOutputSamples[i*8+3] = (drflac_int32)right1;
63479  pOutputSamples[i*8+4] = (drflac_int32)left2;
63480  pOutputSamples[i*8+5] = (drflac_int32)right2;
63481  pOutputSamples[i*8+6] = (drflac_int32)left3;
63482  pOutputSamples[i*8+7] = (drflac_int32)right3;
63483  }
63484  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63485  drflac_uint32 side = pInputSamples0U32[i] << shift0;
63486  drflac_uint32 right = pInputSamples1U32[i] << shift1;
63487  drflac_uint32 left = right + side;
63488  pOutputSamples[i*2+0] = (drflac_int32)left;
63489  pOutputSamples[i*2+1] = (drflac_int32)right;
63490  }
63491 }
63492 #if defined(DRFLAC_SUPPORT_SSE2)
63493 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)
63494 {
63495  drflac_uint64 i;
63496  drflac_uint64 frameCount4 = frameCount >> 2;
63497  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63498  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63499  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63500  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63501  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
63502  for (i = 0; i < frameCount4; ++i) {
63503  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
63504  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
63505  __m128i left = _mm_add_epi32(right, side);
63506  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
63507  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
63508  }
63509  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63510  drflac_uint32 side = pInputSamples0U32[i] << shift0;
63511  drflac_uint32 right = pInputSamples1U32[i] << shift1;
63512  drflac_uint32 left = right + side;
63513  pOutputSamples[i*2+0] = (drflac_int32)left;
63514  pOutputSamples[i*2+1] = (drflac_int32)right;
63515  }
63516 }
63517 #endif
63518 #if defined(DRFLAC_SUPPORT_NEON)
63519 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)
63520 {
63521  drflac_uint64 i;
63522  drflac_uint64 frameCount4 = frameCount >> 2;
63523  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63524  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63525  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63526  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63527  int32x4_t shift0_4;
63528  int32x4_t shift1_4;
63529  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
63530  shift0_4 = vdupq_n_s32(shift0);
63531  shift1_4 = vdupq_n_s32(shift1);
63532  for (i = 0; i < frameCount4; ++i) {
63533  uint32x4_t side;
63534  uint32x4_t right;
63535  uint32x4_t left;
63536  side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
63537  right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
63538  left = vaddq_u32(right, side);
63539  drflac__vst2q_u32((drflac_uint32*)pOutputSamples + i*8, vzipq_u32(left, right));
63540  }
63541  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63542  drflac_uint32 side = pInputSamples0U32[i] << shift0;
63543  drflac_uint32 right = pInputSamples1U32[i] << shift1;
63544  drflac_uint32 left = right + side;
63545  pOutputSamples[i*2+0] = (drflac_int32)left;
63546  pOutputSamples[i*2+1] = (drflac_int32)right;
63547  }
63548 }
63549 #endif
63550 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)
63551 {
63552 #if defined(DRFLAC_SUPPORT_SSE2)
63553  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
63554  drflac_read_pcm_frames_s32__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63555  } else
63556 #elif defined(DRFLAC_SUPPORT_NEON)
63557  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
63558  drflac_read_pcm_frames_s32__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63559  } else
63560 #endif
63561  {
63562 #if 0
63563  drflac_read_pcm_frames_s32__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63564 #else
63565  drflac_read_pcm_frames_s32__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63566 #endif
63567  }
63568 }
63569 #if 0
63570 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)
63571 {
63572  for (drflac_uint64 i = 0; i < frameCount; ++i) {
63573  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63574  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63575  mid = (mid << 1) | (side & 0x01);
63576  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample);
63577  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample);
63578  }
63579 }
63580 #endif
63581 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)
63582 {
63583  drflac_uint64 i;
63584  drflac_uint64 frameCount4 = frameCount >> 2;
63585  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63586  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63587  drflac_int32 shift = unusedBitsPerSample;
63588  if (shift > 0) {
63589  shift -= 1;
63590  for (i = 0; i < frameCount4; ++i) {
63591  drflac_uint32 temp0L;
63592  drflac_uint32 temp1L;
63593  drflac_uint32 temp2L;
63594  drflac_uint32 temp3L;
63595  drflac_uint32 temp0R;
63596  drflac_uint32 temp1R;
63597  drflac_uint32 temp2R;
63598  drflac_uint32 temp3R;
63599  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63600  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63601  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63602  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63603  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63604  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63605  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63606  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63607  mid0 = (mid0 << 1) | (side0 & 0x01);
63608  mid1 = (mid1 << 1) | (side1 & 0x01);
63609  mid2 = (mid2 << 1) | (side2 & 0x01);
63610  mid3 = (mid3 << 1) | (side3 & 0x01);
63611  temp0L = (mid0 + side0) << shift;
63612  temp1L = (mid1 + side1) << shift;
63613  temp2L = (mid2 + side2) << shift;
63614  temp3L = (mid3 + side3) << shift;
63615  temp0R = (mid0 - side0) << shift;
63616  temp1R = (mid1 - side1) << shift;
63617  temp2R = (mid2 - side2) << shift;
63618  temp3R = (mid3 - side3) << shift;
63619  pOutputSamples[i*8+0] = (drflac_int32)temp0L;
63620  pOutputSamples[i*8+1] = (drflac_int32)temp0R;
63621  pOutputSamples[i*8+2] = (drflac_int32)temp1L;
63622  pOutputSamples[i*8+3] = (drflac_int32)temp1R;
63623  pOutputSamples[i*8+4] = (drflac_int32)temp2L;
63624  pOutputSamples[i*8+5] = (drflac_int32)temp2R;
63625  pOutputSamples[i*8+6] = (drflac_int32)temp3L;
63626  pOutputSamples[i*8+7] = (drflac_int32)temp3R;
63627  }
63628  } else {
63629  for (i = 0; i < frameCount4; ++i) {
63630  drflac_uint32 temp0L;
63631  drflac_uint32 temp1L;
63632  drflac_uint32 temp2L;
63633  drflac_uint32 temp3L;
63634  drflac_uint32 temp0R;
63635  drflac_uint32 temp1R;
63636  drflac_uint32 temp2R;
63637  drflac_uint32 temp3R;
63638  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63639  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63640  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63641  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63642  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63643  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63644  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63645  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63646  mid0 = (mid0 << 1) | (side0 & 0x01);
63647  mid1 = (mid1 << 1) | (side1 & 0x01);
63648  mid2 = (mid2 << 1) | (side2 & 0x01);
63649  mid3 = (mid3 << 1) | (side3 & 0x01);
63650  temp0L = (drflac_uint32)((drflac_int32)(mid0 + side0) >> 1);
63651  temp1L = (drflac_uint32)((drflac_int32)(mid1 + side1) >> 1);
63652  temp2L = (drflac_uint32)((drflac_int32)(mid2 + side2) >> 1);
63653  temp3L = (drflac_uint32)((drflac_int32)(mid3 + side3) >> 1);
63654  temp0R = (drflac_uint32)((drflac_int32)(mid0 - side0) >> 1);
63655  temp1R = (drflac_uint32)((drflac_int32)(mid1 - side1) >> 1);
63656  temp2R = (drflac_uint32)((drflac_int32)(mid2 - side2) >> 1);
63657  temp3R = (drflac_uint32)((drflac_int32)(mid3 - side3) >> 1);
63658  pOutputSamples[i*8+0] = (drflac_int32)temp0L;
63659  pOutputSamples[i*8+1] = (drflac_int32)temp0R;
63660  pOutputSamples[i*8+2] = (drflac_int32)temp1L;
63661  pOutputSamples[i*8+3] = (drflac_int32)temp1R;
63662  pOutputSamples[i*8+4] = (drflac_int32)temp2L;
63663  pOutputSamples[i*8+5] = (drflac_int32)temp2R;
63664  pOutputSamples[i*8+6] = (drflac_int32)temp3L;
63665  pOutputSamples[i*8+7] = (drflac_int32)temp3R;
63666  }
63667  }
63668  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63669  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63670  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63671  mid = (mid << 1) | (side & 0x01);
63672  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample);
63673  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample);
63674  }
63675 }
63676 #if defined(DRFLAC_SUPPORT_SSE2)
63677 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)
63678 {
63679  drflac_uint64 i;
63680  drflac_uint64 frameCount4 = frameCount >> 2;
63681  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63682  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63683  drflac_int32 shift = unusedBitsPerSample;
63684  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
63685  if (shift == 0) {
63686  for (i = 0; i < frameCount4; ++i) {
63687  __m128i mid;
63688  __m128i side;
63689  __m128i left;
63690  __m128i right;
63691  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
63692  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
63693  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
63694  left = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
63695  right = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
63696  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
63697  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
63698  }
63699  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63700  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63701  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63702  mid = (mid << 1) | (side & 0x01);
63703  pOutputSamples[i*2+0] = (drflac_int32)(mid + side) >> 1;
63704  pOutputSamples[i*2+1] = (drflac_int32)(mid - side) >> 1;
63705  }
63706  } else {
63707  shift -= 1;
63708  for (i = 0; i < frameCount4; ++i) {
63709  __m128i mid;
63710  __m128i side;
63711  __m128i left;
63712  __m128i right;
63713  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
63714  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
63715  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
63716  left = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
63717  right = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
63718  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
63719  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
63720  }
63721  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63722  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63723  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63724  mid = (mid << 1) | (side & 0x01);
63725  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift);
63726  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift);
63727  }
63728  }
63729 }
63730 #endif
63731 #if defined(DRFLAC_SUPPORT_NEON)
63732 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)
63733 {
63734  drflac_uint64 i;
63735  drflac_uint64 frameCount4 = frameCount >> 2;
63736  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63737  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63738  drflac_int32 shift = unusedBitsPerSample;
63739  int32x4_t wbpsShift0_4;
63740  int32x4_t wbpsShift1_4;
63741  uint32x4_t one4;
63742  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
63743  wbpsShift0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
63744  wbpsShift1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
63745  one4 = vdupq_n_u32(1);
63746  if (shift == 0) {
63747  for (i = 0; i < frameCount4; ++i) {
63748  uint32x4_t mid;
63749  uint32x4_t side;
63750  int32x4_t left;
63751  int32x4_t right;
63752  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
63753  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
63754  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, one4));
63755  left = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
63756  right = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
63757  drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
63758  }
63759  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63760  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63761  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63762  mid = (mid << 1) | (side & 0x01);
63763  pOutputSamples[i*2+0] = (drflac_int32)(mid + side) >> 1;
63764  pOutputSamples[i*2+1] = (drflac_int32)(mid - side) >> 1;
63765  }
63766  } else {
63767  int32x4_t shift4;
63768  shift -= 1;
63769  shift4 = vdupq_n_s32(shift);
63770  for (i = 0; i < frameCount4; ++i) {
63771  uint32x4_t mid;
63772  uint32x4_t side;
63773  int32x4_t left;
63774  int32x4_t right;
63775  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
63776  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
63777  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, one4));
63778  left = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
63779  right = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
63780  drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
63781  }
63782  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63783  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63784  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63785  mid = (mid << 1) | (side & 0x01);
63786  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift);
63787  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift);
63788  }
63789  }
63790 }
63791 #endif
63792 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)
63793 {
63794 #if defined(DRFLAC_SUPPORT_SSE2)
63795  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
63796  drflac_read_pcm_frames_s32__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63797  } else
63798 #elif defined(DRFLAC_SUPPORT_NEON)
63799  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
63800  drflac_read_pcm_frames_s32__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63801  } else
63802 #endif
63803  {
63804 #if 0
63805  drflac_read_pcm_frames_s32__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63806 #else
63807  drflac_read_pcm_frames_s32__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63808 #endif
63809  }
63810 }
63811 #if 0
63812 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)
63813 {
63814  for (drflac_uint64 i = 0; i < frameCount; ++i) {
63815  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample));
63816  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample));
63817  }
63818 }
63819 #endif
63820 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)
63821 {
63822  drflac_uint64 i;
63823  drflac_uint64 frameCount4 = frameCount >> 2;
63824  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63825  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63826  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63827  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63828  for (i = 0; i < frameCount4; ++i) {
63829  drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
63830  drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
63831  drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
63832  drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
63833  drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
63834  drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
63835  drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
63836  drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
63837  pOutputSamples[i*8+0] = (drflac_int32)tempL0;
63838  pOutputSamples[i*8+1] = (drflac_int32)tempR0;
63839  pOutputSamples[i*8+2] = (drflac_int32)tempL1;
63840  pOutputSamples[i*8+3] = (drflac_int32)tempR1;
63841  pOutputSamples[i*8+4] = (drflac_int32)tempL2;
63842  pOutputSamples[i*8+5] = (drflac_int32)tempR2;
63843  pOutputSamples[i*8+6] = (drflac_int32)tempL3;
63844  pOutputSamples[i*8+7] = (drflac_int32)tempR3;
63845  }
63846  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63847  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
63848  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
63849  }
63850 }
63851 #if defined(DRFLAC_SUPPORT_SSE2)
63852 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)
63853 {
63854  drflac_uint64 i;
63855  drflac_uint64 frameCount4 = frameCount >> 2;
63856  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63857  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63858  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63859  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63860  for (i = 0; i < frameCount4; ++i) {
63861  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
63862  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
63863  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
63864  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
63865  }
63866  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63867  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
63868  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
63869  }
63870 }
63871 #endif
63872 #if defined(DRFLAC_SUPPORT_NEON)
63873 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)
63874 {
63875  drflac_uint64 i;
63876  drflac_uint64 frameCount4 = frameCount >> 2;
63877  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
63878  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
63879  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
63880  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
63881  int32x4_t shift4_0 = vdupq_n_s32(shift0);
63882  int32x4_t shift4_1 = vdupq_n_s32(shift1);
63883  for (i = 0; i < frameCount4; ++i) {
63884  int32x4_t left;
63885  int32x4_t right;
63886  left = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift4_0));
63887  right = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift4_1));
63888  drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
63889  }
63890  for (i = (frameCount4 << 2); i < frameCount; ++i) {
63891  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
63892  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
63893  }
63894 }
63895 #endif
63896 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)
63897 {
63898 #if defined(DRFLAC_SUPPORT_SSE2)
63899  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
63900  drflac_read_pcm_frames_s32__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63901  } else
63902 #elif defined(DRFLAC_SUPPORT_NEON)
63903  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
63904  drflac_read_pcm_frames_s32__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63905  } else
63906 #endif
63907  {
63908 #if 0
63909  drflac_read_pcm_frames_s32__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63910 #else
63911  drflac_read_pcm_frames_s32__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
63912 #endif
63913  }
63914 }
63916 {
63917  drflac_uint64 framesRead;
63918  drflac_uint32 unusedBitsPerSample;
63919  if (pFlac == NULL || framesToRead == 0) {
63920  return 0;
63921  }
63922  if (pBufferOut == NULL) {
63923  return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
63924  }
63925  DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
63926  unusedBitsPerSample = 32 - pFlac->bitsPerSample;
63927  framesRead = 0;
63928  while (framesToRead > 0) {
63929  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
63931  break;
63932  }
63933  } else {
63935  drflac_uint64 iFirstPCMFrame = pFlac->currentFLACFrame.header.blockSizeInPCMFrames - pFlac->currentFLACFrame.pcmFramesRemaining;
63936  drflac_uint64 frameCountThisIteration = framesToRead;
63937  if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
63938  frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
63939  }
63940  if (channelCount == 2) {
63941  const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
63942  const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
63943  switch (pFlac->currentFLACFrame.header.channelAssignment)
63944  {
63946  {
63947  drflac_read_pcm_frames_s32__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
63948  } break;
63950  {
63951  drflac_read_pcm_frames_s32__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
63952  } break;
63954  {
63955  drflac_read_pcm_frames_s32__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
63956  } break;
63958  default:
63959  {
63960  drflac_read_pcm_frames_s32__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
63961  } break;
63962  }
63963  } else {
63964  drflac_uint64 i;
63965  for (i = 0; i < frameCountThisIteration; ++i) {
63966  unsigned int j;
63967  for (j = 0; j < channelCount; ++j) {
63968  pBufferOut[(i*channelCount)+j] = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
63969  }
63970  }
63971  }
63972  framesRead += frameCountThisIteration;
63973  pBufferOut += frameCountThisIteration * channelCount;
63974  framesToRead -= frameCountThisIteration;
63975  pFlac->currentPCMFrame += frameCountThisIteration;
63976  pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)frameCountThisIteration;
63977  }
63978  }
63979  return framesRead;
63980 }
63981 #if 0
63982 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)
63983 {
63984  drflac_uint64 i;
63985  for (i = 0; i < frameCount; ++i) {
63986  drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
63987  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
63988  drflac_uint32 right = left - side;
63989  left >>= 16;
63990  right >>= 16;
63991  pOutputSamples[i*2+0] = (drflac_int16)left;
63992  pOutputSamples[i*2+1] = (drflac_int16)right;
63993  }
63994 }
63995 #endif
63996 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)
63997 {
63998  drflac_uint64 i;
63999  drflac_uint64 frameCount4 = frameCount >> 2;
64000  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64001  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64002  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64003  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64004  for (i = 0; i < frameCount4; ++i) {
64005  drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
64006  drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
64007  drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
64008  drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
64009  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
64010  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
64011  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
64012  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
64013  drflac_uint32 right0 = left0 - side0;
64014  drflac_uint32 right1 = left1 - side1;
64015  drflac_uint32 right2 = left2 - side2;
64016  drflac_uint32 right3 = left3 - side3;
64017  left0 >>= 16;
64018  left1 >>= 16;
64019  left2 >>= 16;
64020  left3 >>= 16;
64021  right0 >>= 16;
64022  right1 >>= 16;
64023  right2 >>= 16;
64024  right3 >>= 16;
64025  pOutputSamples[i*8+0] = (drflac_int16)left0;
64026  pOutputSamples[i*8+1] = (drflac_int16)right0;
64027  pOutputSamples[i*8+2] = (drflac_int16)left1;
64028  pOutputSamples[i*8+3] = (drflac_int16)right1;
64029  pOutputSamples[i*8+4] = (drflac_int16)left2;
64030  pOutputSamples[i*8+5] = (drflac_int16)right2;
64031  pOutputSamples[i*8+6] = (drflac_int16)left3;
64032  pOutputSamples[i*8+7] = (drflac_int16)right3;
64033  }
64034  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64035  drflac_uint32 left = pInputSamples0U32[i] << shift0;
64036  drflac_uint32 side = pInputSamples1U32[i] << shift1;
64037  drflac_uint32 right = left - side;
64038  left >>= 16;
64039  right >>= 16;
64040  pOutputSamples[i*2+0] = (drflac_int16)left;
64041  pOutputSamples[i*2+1] = (drflac_int16)right;
64042  }
64043 }
64044 #if defined(DRFLAC_SUPPORT_SSE2)
64045 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)
64046 {
64047  drflac_uint64 i;
64048  drflac_uint64 frameCount4 = frameCount >> 2;
64049  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64050  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64051  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64052  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64053  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64054  for (i = 0; i < frameCount4; ++i) {
64055  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
64056  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
64057  __m128i right = _mm_sub_epi32(left, side);
64058  left = _mm_srai_epi32(left, 16);
64059  right = _mm_srai_epi32(right, 16);
64060  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
64061  }
64062  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64063  drflac_uint32 left = pInputSamples0U32[i] << shift0;
64064  drflac_uint32 side = pInputSamples1U32[i] << shift1;
64065  drflac_uint32 right = left - side;
64066  left >>= 16;
64067  right >>= 16;
64068  pOutputSamples[i*2+0] = (drflac_int16)left;
64069  pOutputSamples[i*2+1] = (drflac_int16)right;
64070  }
64071 }
64072 #endif
64073 #if defined(DRFLAC_SUPPORT_NEON)
64074 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)
64075 {
64076  drflac_uint64 i;
64077  drflac_uint64 frameCount4 = frameCount >> 2;
64078  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64079  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64080  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64081  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64082  int32x4_t shift0_4;
64083  int32x4_t shift1_4;
64084  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64085  shift0_4 = vdupq_n_s32(shift0);
64086  shift1_4 = vdupq_n_s32(shift1);
64087  for (i = 0; i < frameCount4; ++i) {
64088  uint32x4_t left;
64089  uint32x4_t side;
64090  uint32x4_t right;
64091  left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
64092  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
64093  right = vsubq_u32(left, side);
64094  left = vshrq_n_u32(left, 16);
64095  right = vshrq_n_u32(right, 16);
64096  drflac__vst2q_u16((drflac_uint16*)pOutputSamples + i*8, vzip_u16(vmovn_u32(left), vmovn_u32(right)));
64097  }
64098  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64099  drflac_uint32 left = pInputSamples0U32[i] << shift0;
64100  drflac_uint32 side = pInputSamples1U32[i] << shift1;
64101  drflac_uint32 right = left - side;
64102  left >>= 16;
64103  right >>= 16;
64104  pOutputSamples[i*2+0] = (drflac_int16)left;
64105  pOutputSamples[i*2+1] = (drflac_int16)right;
64106  }
64107 }
64108 #endif
64109 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)
64110 {
64111 #if defined(DRFLAC_SUPPORT_SSE2)
64112  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
64113  drflac_read_pcm_frames_s16__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64114  } else
64115 #elif defined(DRFLAC_SUPPORT_NEON)
64116  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
64117  drflac_read_pcm_frames_s16__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64118  } else
64119 #endif
64120  {
64121 #if 0
64122  drflac_read_pcm_frames_s16__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64123 #else
64124  drflac_read_pcm_frames_s16__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64125 #endif
64126  }
64127 }
64128 #if 0
64129 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)
64130 {
64131  drflac_uint64 i;
64132  for (i = 0; i < frameCount; ++i) {
64133  drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
64134  drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
64135  drflac_uint32 left = right + side;
64136  left >>= 16;
64137  right >>= 16;
64138  pOutputSamples[i*2+0] = (drflac_int16)left;
64139  pOutputSamples[i*2+1] = (drflac_int16)right;
64140  }
64141 }
64142 #endif
64143 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)
64144 {
64145  drflac_uint64 i;
64146  drflac_uint64 frameCount4 = frameCount >> 2;
64147  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64148  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64149  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64150  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64151  for (i = 0; i < frameCount4; ++i) {
64152  drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
64153  drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
64154  drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
64155  drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
64156  drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
64157  drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
64158  drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
64159  drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
64160  drflac_uint32 left0 = right0 + side0;
64161  drflac_uint32 left1 = right1 + side1;
64162  drflac_uint32 left2 = right2 + side2;
64163  drflac_uint32 left3 = right3 + side3;
64164  left0 >>= 16;
64165  left1 >>= 16;
64166  left2 >>= 16;
64167  left3 >>= 16;
64168  right0 >>= 16;
64169  right1 >>= 16;
64170  right2 >>= 16;
64171  right3 >>= 16;
64172  pOutputSamples[i*8+0] = (drflac_int16)left0;
64173  pOutputSamples[i*8+1] = (drflac_int16)right0;
64174  pOutputSamples[i*8+2] = (drflac_int16)left1;
64175  pOutputSamples[i*8+3] = (drflac_int16)right1;
64176  pOutputSamples[i*8+4] = (drflac_int16)left2;
64177  pOutputSamples[i*8+5] = (drflac_int16)right2;
64178  pOutputSamples[i*8+6] = (drflac_int16)left3;
64179  pOutputSamples[i*8+7] = (drflac_int16)right3;
64180  }
64181  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64182  drflac_uint32 side = pInputSamples0U32[i] << shift0;
64183  drflac_uint32 right = pInputSamples1U32[i] << shift1;
64184  drflac_uint32 left = right + side;
64185  left >>= 16;
64186  right >>= 16;
64187  pOutputSamples[i*2+0] = (drflac_int16)left;
64188  pOutputSamples[i*2+1] = (drflac_int16)right;
64189  }
64190 }
64191 #if defined(DRFLAC_SUPPORT_SSE2)
64192 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)
64193 {
64194  drflac_uint64 i;
64195  drflac_uint64 frameCount4 = frameCount >> 2;
64196  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64197  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64198  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64199  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64200  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64201  for (i = 0; i < frameCount4; ++i) {
64202  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
64203  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
64204  __m128i left = _mm_add_epi32(right, side);
64205  left = _mm_srai_epi32(left, 16);
64206  right = _mm_srai_epi32(right, 16);
64207  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
64208  }
64209  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64210  drflac_uint32 side = pInputSamples0U32[i] << shift0;
64211  drflac_uint32 right = pInputSamples1U32[i] << shift1;
64212  drflac_uint32 left = right + side;
64213  left >>= 16;
64214  right >>= 16;
64215  pOutputSamples[i*2+0] = (drflac_int16)left;
64216  pOutputSamples[i*2+1] = (drflac_int16)right;
64217  }
64218 }
64219 #endif
64220 #if defined(DRFLAC_SUPPORT_NEON)
64221 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)
64222 {
64223  drflac_uint64 i;
64224  drflac_uint64 frameCount4 = frameCount >> 2;
64225  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64226  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64227  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64228  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64229  int32x4_t shift0_4;
64230  int32x4_t shift1_4;
64231  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64232  shift0_4 = vdupq_n_s32(shift0);
64233  shift1_4 = vdupq_n_s32(shift1);
64234  for (i = 0; i < frameCount4; ++i) {
64235  uint32x4_t side;
64236  uint32x4_t right;
64237  uint32x4_t left;
64238  side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
64239  right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
64240  left = vaddq_u32(right, side);
64241  left = vshrq_n_u32(left, 16);
64242  right = vshrq_n_u32(right, 16);
64243  drflac__vst2q_u16((drflac_uint16*)pOutputSamples + i*8, vzip_u16(vmovn_u32(left), vmovn_u32(right)));
64244  }
64245  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64246  drflac_uint32 side = pInputSamples0U32[i] << shift0;
64247  drflac_uint32 right = pInputSamples1U32[i] << shift1;
64248  drflac_uint32 left = right + side;
64249  left >>= 16;
64250  right >>= 16;
64251  pOutputSamples[i*2+0] = (drflac_int16)left;
64252  pOutputSamples[i*2+1] = (drflac_int16)right;
64253  }
64254 }
64255 #endif
64256 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)
64257 {
64258 #if defined(DRFLAC_SUPPORT_SSE2)
64259  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
64260  drflac_read_pcm_frames_s16__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64261  } else
64262 #elif defined(DRFLAC_SUPPORT_NEON)
64263  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
64264  drflac_read_pcm_frames_s16__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64265  } else
64266 #endif
64267  {
64268 #if 0
64269  drflac_read_pcm_frames_s16__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64270 #else
64271  drflac_read_pcm_frames_s16__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64272 #endif
64273  }
64274 }
64275 #if 0
64276 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)
64277 {
64278  for (drflac_uint64 i = 0; i < frameCount; ++i) {
64279  drflac_uint32 mid = (drflac_uint32)pInputSamples0[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64280  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64281  mid = (mid << 1) | (side & 0x01);
64282  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) >> 16);
64283  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) >> 16);
64284  }
64285 }
64286 #endif
64287 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)
64288 {
64289  drflac_uint64 i;
64290  drflac_uint64 frameCount4 = frameCount >> 2;
64291  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64292  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64293  drflac_uint32 shift = unusedBitsPerSample;
64294  if (shift > 0) {
64295  shift -= 1;
64296  for (i = 0; i < frameCount4; ++i) {
64297  drflac_uint32 temp0L;
64298  drflac_uint32 temp1L;
64299  drflac_uint32 temp2L;
64300  drflac_uint32 temp3L;
64301  drflac_uint32 temp0R;
64302  drflac_uint32 temp1R;
64303  drflac_uint32 temp2R;
64304  drflac_uint32 temp3R;
64305  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64306  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64307  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64308  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64309  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64310  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64311  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64312  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64313  mid0 = (mid0 << 1) | (side0 & 0x01);
64314  mid1 = (mid1 << 1) | (side1 & 0x01);
64315  mid2 = (mid2 << 1) | (side2 & 0x01);
64316  mid3 = (mid3 << 1) | (side3 & 0x01);
64317  temp0L = (mid0 + side0) << shift;
64318  temp1L = (mid1 + side1) << shift;
64319  temp2L = (mid2 + side2) << shift;
64320  temp3L = (mid3 + side3) << shift;
64321  temp0R = (mid0 - side0) << shift;
64322  temp1R = (mid1 - side1) << shift;
64323  temp2R = (mid2 - side2) << shift;
64324  temp3R = (mid3 - side3) << shift;
64325  temp0L >>= 16;
64326  temp1L >>= 16;
64327  temp2L >>= 16;
64328  temp3L >>= 16;
64329  temp0R >>= 16;
64330  temp1R >>= 16;
64331  temp2R >>= 16;
64332  temp3R >>= 16;
64333  pOutputSamples[i*8+0] = (drflac_int16)temp0L;
64334  pOutputSamples[i*8+1] = (drflac_int16)temp0R;
64335  pOutputSamples[i*8+2] = (drflac_int16)temp1L;
64336  pOutputSamples[i*8+3] = (drflac_int16)temp1R;
64337  pOutputSamples[i*8+4] = (drflac_int16)temp2L;
64338  pOutputSamples[i*8+5] = (drflac_int16)temp2R;
64339  pOutputSamples[i*8+6] = (drflac_int16)temp3L;
64340  pOutputSamples[i*8+7] = (drflac_int16)temp3R;
64341  }
64342  } else {
64343  for (i = 0; i < frameCount4; ++i) {
64344  drflac_uint32 temp0L;
64345  drflac_uint32 temp1L;
64346  drflac_uint32 temp2L;
64347  drflac_uint32 temp3L;
64348  drflac_uint32 temp0R;
64349  drflac_uint32 temp1R;
64350  drflac_uint32 temp2R;
64351  drflac_uint32 temp3R;
64352  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64353  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64354  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64355  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64356  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64357  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64358  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64359  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64360  mid0 = (mid0 << 1) | (side0 & 0x01);
64361  mid1 = (mid1 << 1) | (side1 & 0x01);
64362  mid2 = (mid2 << 1) | (side2 & 0x01);
64363  mid3 = (mid3 << 1) | (side3 & 0x01);
64364  temp0L = ((drflac_int32)(mid0 + side0) >> 1);
64365  temp1L = ((drflac_int32)(mid1 + side1) >> 1);
64366  temp2L = ((drflac_int32)(mid2 + side2) >> 1);
64367  temp3L = ((drflac_int32)(mid3 + side3) >> 1);
64368  temp0R = ((drflac_int32)(mid0 - side0) >> 1);
64369  temp1R = ((drflac_int32)(mid1 - side1) >> 1);
64370  temp2R = ((drflac_int32)(mid2 - side2) >> 1);
64371  temp3R = ((drflac_int32)(mid3 - side3) >> 1);
64372  temp0L >>= 16;
64373  temp1L >>= 16;
64374  temp2L >>= 16;
64375  temp3L >>= 16;
64376  temp0R >>= 16;
64377  temp1R >>= 16;
64378  temp2R >>= 16;
64379  temp3R >>= 16;
64380  pOutputSamples[i*8+0] = (drflac_int16)temp0L;
64381  pOutputSamples[i*8+1] = (drflac_int16)temp0R;
64382  pOutputSamples[i*8+2] = (drflac_int16)temp1L;
64383  pOutputSamples[i*8+3] = (drflac_int16)temp1R;
64384  pOutputSamples[i*8+4] = (drflac_int16)temp2L;
64385  pOutputSamples[i*8+5] = (drflac_int16)temp2R;
64386  pOutputSamples[i*8+6] = (drflac_int16)temp3L;
64387  pOutputSamples[i*8+7] = (drflac_int16)temp3R;
64388  }
64389  }
64390  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64391  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64392  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64393  mid = (mid << 1) | (side & 0x01);
64394  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) >> 16);
64395  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) >> 16);
64396  }
64397 }
64398 #if defined(DRFLAC_SUPPORT_SSE2)
64399 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)
64400 {
64401  drflac_uint64 i;
64402  drflac_uint64 frameCount4 = frameCount >> 2;
64403  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64404  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64405  drflac_uint32 shift = unusedBitsPerSample;
64406  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64407  if (shift == 0) {
64408  for (i = 0; i < frameCount4; ++i) {
64409  __m128i mid;
64410  __m128i side;
64411  __m128i left;
64412  __m128i right;
64413  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
64414  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
64415  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
64416  left = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
64417  right = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
64418  left = _mm_srai_epi32(left, 16);
64419  right = _mm_srai_epi32(right, 16);
64420  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
64421  }
64422  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64423  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64424  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64425  mid = (mid << 1) | (side & 0x01);
64426  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_int32)(mid + side) >> 1) >> 16);
64427  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_int32)(mid - side) >> 1) >> 16);
64428  }
64429  } else {
64430  shift -= 1;
64431  for (i = 0; i < frameCount4; ++i) {
64432  __m128i mid;
64433  __m128i side;
64434  __m128i left;
64435  __m128i right;
64436  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
64437  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
64438  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
64439  left = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
64440  right = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
64441  left = _mm_srai_epi32(left, 16);
64442  right = _mm_srai_epi32(right, 16);
64443  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
64444  }
64445  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64446  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64447  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64448  mid = (mid << 1) | (side & 0x01);
64449  pOutputSamples[i*2+0] = (drflac_int16)(((mid + side) << shift) >> 16);
64450  pOutputSamples[i*2+1] = (drflac_int16)(((mid - side) << shift) >> 16);
64451  }
64452  }
64453 }
64454 #endif
64455 #if defined(DRFLAC_SUPPORT_NEON)
64456 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)
64457 {
64458  drflac_uint64 i;
64459  drflac_uint64 frameCount4 = frameCount >> 2;
64460  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64461  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64462  drflac_uint32 shift = unusedBitsPerSample;
64463  int32x4_t wbpsShift0_4;
64464  int32x4_t wbpsShift1_4;
64465  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64466  wbpsShift0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
64467  wbpsShift1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
64468  if (shift == 0) {
64469  for (i = 0; i < frameCount4; ++i) {
64470  uint32x4_t mid;
64471  uint32x4_t side;
64472  int32x4_t left;
64473  int32x4_t right;
64474  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
64475  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
64476  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
64477  left = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
64478  right = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
64479  left = vshrq_n_s32(left, 16);
64480  right = vshrq_n_s32(right, 16);
64481  drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
64482  }
64483  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64484  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64485  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64486  mid = (mid << 1) | (side & 0x01);
64487  pOutputSamples[i*2+0] = (drflac_int16)(((drflac_int32)(mid + side) >> 1) >> 16);
64488  pOutputSamples[i*2+1] = (drflac_int16)(((drflac_int32)(mid - side) >> 1) >> 16);
64489  }
64490  } else {
64491  int32x4_t shift4;
64492  shift -= 1;
64493  shift4 = vdupq_n_s32(shift);
64494  for (i = 0; i < frameCount4; ++i) {
64495  uint32x4_t mid;
64496  uint32x4_t side;
64497  int32x4_t left;
64498  int32x4_t right;
64499  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
64500  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
64501  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
64502  left = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
64503  right = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
64504  left = vshrq_n_s32(left, 16);
64505  right = vshrq_n_s32(right, 16);
64506  drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
64507  }
64508  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64509  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64510  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64511  mid = (mid << 1) | (side & 0x01);
64512  pOutputSamples[i*2+0] = (drflac_int16)(((mid + side) << shift) >> 16);
64513  pOutputSamples[i*2+1] = (drflac_int16)(((mid - side) << shift) >> 16);
64514  }
64515  }
64516 }
64517 #endif
64518 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)
64519 {
64520 #if defined(DRFLAC_SUPPORT_SSE2)
64521  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
64522  drflac_read_pcm_frames_s16__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64523  } else
64524 #elif defined(DRFLAC_SUPPORT_NEON)
64525  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
64526  drflac_read_pcm_frames_s16__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64527  } else
64528 #endif
64529  {
64530 #if 0
64531  drflac_read_pcm_frames_s16__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64532 #else
64533  drflac_read_pcm_frames_s16__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64534 #endif
64535  }
64536 }
64537 #if 0
64538 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)
64539 {
64540  for (drflac_uint64 i = 0; i < frameCount; ++i) {
64541  pOutputSamples[i*2+0] = (drflac_int16)((drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample)) >> 16);
64542  pOutputSamples[i*2+1] = (drflac_int16)((drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample)) >> 16);
64543  }
64544 }
64545 #endif
64546 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)
64547 {
64548  drflac_uint64 i;
64549  drflac_uint64 frameCount4 = frameCount >> 2;
64550  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64551  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64552  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64553  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64554  for (i = 0; i < frameCount4; ++i) {
64555  drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
64556  drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
64557  drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
64558  drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
64559  drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
64560  drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
64561  drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
64562  drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
64563  tempL0 >>= 16;
64564  tempL1 >>= 16;
64565  tempL2 >>= 16;
64566  tempL3 >>= 16;
64567  tempR0 >>= 16;
64568  tempR1 >>= 16;
64569  tempR2 >>= 16;
64570  tempR3 >>= 16;
64571  pOutputSamples[i*8+0] = (drflac_int16)tempL0;
64572  pOutputSamples[i*8+1] = (drflac_int16)tempR0;
64573  pOutputSamples[i*8+2] = (drflac_int16)tempL1;
64574  pOutputSamples[i*8+3] = (drflac_int16)tempR1;
64575  pOutputSamples[i*8+4] = (drflac_int16)tempL2;
64576  pOutputSamples[i*8+5] = (drflac_int16)tempR2;
64577  pOutputSamples[i*8+6] = (drflac_int16)tempL3;
64578  pOutputSamples[i*8+7] = (drflac_int16)tempR3;
64579  }
64580  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64581  pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
64582  pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
64583  }
64584 }
64585 #if defined(DRFLAC_SUPPORT_SSE2)
64586 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)
64587 {
64588  drflac_uint64 i;
64589  drflac_uint64 frameCount4 = frameCount >> 2;
64590  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64591  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64592  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64593  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64594  for (i = 0; i < frameCount4; ++i) {
64595  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
64596  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
64597  left = _mm_srai_epi32(left, 16);
64598  right = _mm_srai_epi32(right, 16);
64599  _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
64600  }
64601  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64602  pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
64603  pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
64604  }
64605 }
64606 #endif
64607 #if defined(DRFLAC_SUPPORT_NEON)
64608 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)
64609 {
64610  drflac_uint64 i;
64611  drflac_uint64 frameCount4 = frameCount >> 2;
64612  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64613  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64614  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64615  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64616  int32x4_t shift0_4 = vdupq_n_s32(shift0);
64617  int32x4_t shift1_4 = vdupq_n_s32(shift1);
64618  for (i = 0; i < frameCount4; ++i) {
64619  int32x4_t left;
64620  int32x4_t right;
64621  left = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4));
64622  right = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4));
64623  left = vshrq_n_s32(left, 16);
64624  right = vshrq_n_s32(right, 16);
64625  drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
64626  }
64627  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64628  pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
64629  pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
64630  }
64631 }
64632 #endif
64633 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)
64634 {
64635 #if defined(DRFLAC_SUPPORT_SSE2)
64636  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
64637  drflac_read_pcm_frames_s16__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64638  } else
64639 #elif defined(DRFLAC_SUPPORT_NEON)
64640  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
64641  drflac_read_pcm_frames_s16__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64642  } else
64643 #endif
64644  {
64645 #if 0
64646  drflac_read_pcm_frames_s16__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64647 #else
64648  drflac_read_pcm_frames_s16__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64649 #endif
64650  }
64651 }
64653 {
64654  drflac_uint64 framesRead;
64655  drflac_uint32 unusedBitsPerSample;
64656  if (pFlac == NULL || framesToRead == 0) {
64657  return 0;
64658  }
64659  if (pBufferOut == NULL) {
64660  return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
64661  }
64662  DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
64663  unusedBitsPerSample = 32 - pFlac->bitsPerSample;
64664  framesRead = 0;
64665  while (framesToRead > 0) {
64666  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
64668  break;
64669  }
64670  } else {
64672  drflac_uint64 iFirstPCMFrame = pFlac->currentFLACFrame.header.blockSizeInPCMFrames - pFlac->currentFLACFrame.pcmFramesRemaining;
64673  drflac_uint64 frameCountThisIteration = framesToRead;
64674  if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
64675  frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
64676  }
64677  if (channelCount == 2) {
64678  const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
64679  const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
64680  switch (pFlac->currentFLACFrame.header.channelAssignment)
64681  {
64683  {
64684  drflac_read_pcm_frames_s16__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
64685  } break;
64687  {
64688  drflac_read_pcm_frames_s16__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
64689  } break;
64691  {
64692  drflac_read_pcm_frames_s16__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
64693  } break;
64695  default:
64696  {
64697  drflac_read_pcm_frames_s16__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
64698  } break;
64699  }
64700  } else {
64701  drflac_uint64 i;
64702  for (i = 0; i < frameCountThisIteration; ++i) {
64703  unsigned int j;
64704  for (j = 0; j < channelCount; ++j) {
64705  drflac_int32 sampleS32 = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
64706  pBufferOut[(i*channelCount)+j] = (drflac_int16)(sampleS32 >> 16);
64707  }
64708  }
64709  }
64710  framesRead += frameCountThisIteration;
64711  pBufferOut += frameCountThisIteration * channelCount;
64712  framesToRead -= frameCountThisIteration;
64713  pFlac->currentPCMFrame += frameCountThisIteration;
64714  pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)frameCountThisIteration;
64715  }
64716  }
64717  return framesRead;
64718 }
64719 #if 0
64720 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)
64721 {
64722  drflac_uint64 i;
64723  for (i = 0; i < frameCount; ++i) {
64724  drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
64725  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
64726  drflac_uint32 right = left - side;
64727  pOutputSamples[i*2+0] = (float)((drflac_int32)left / 2147483648.0);
64728  pOutputSamples[i*2+1] = (float)((drflac_int32)right / 2147483648.0);
64729  }
64730 }
64731 #endif
64732 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)
64733 {
64734  drflac_uint64 i;
64735  drflac_uint64 frameCount4 = frameCount >> 2;
64736  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64737  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64738  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64739  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64740  float factor = 1 / 2147483648.0;
64741  for (i = 0; i < frameCount4; ++i) {
64742  drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
64743  drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
64744  drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
64745  drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
64746  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
64747  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
64748  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
64749  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
64750  drflac_uint32 right0 = left0 - side0;
64751  drflac_uint32 right1 = left1 - side1;
64752  drflac_uint32 right2 = left2 - side2;
64753  drflac_uint32 right3 = left3 - side3;
64754  pOutputSamples[i*8+0] = (drflac_int32)left0 * factor;
64755  pOutputSamples[i*8+1] = (drflac_int32)right0 * factor;
64756  pOutputSamples[i*8+2] = (drflac_int32)left1 * factor;
64757  pOutputSamples[i*8+3] = (drflac_int32)right1 * factor;
64758  pOutputSamples[i*8+4] = (drflac_int32)left2 * factor;
64759  pOutputSamples[i*8+5] = (drflac_int32)right2 * factor;
64760  pOutputSamples[i*8+6] = (drflac_int32)left3 * factor;
64761  pOutputSamples[i*8+7] = (drflac_int32)right3 * factor;
64762  }
64763  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64764  drflac_uint32 left = pInputSamples0U32[i] << shift0;
64765  drflac_uint32 side = pInputSamples1U32[i] << shift1;
64766  drflac_uint32 right = left - side;
64767  pOutputSamples[i*2+0] = (drflac_int32)left * factor;
64768  pOutputSamples[i*2+1] = (drflac_int32)right * factor;
64769  }
64770 }
64771 #if defined(DRFLAC_SUPPORT_SSE2)
64772 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)
64773 {
64774  drflac_uint64 i;
64775  drflac_uint64 frameCount4 = frameCount >> 2;
64776  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64777  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64778  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
64779  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
64780  __m128 factor;
64781  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64782  factor = _mm_set1_ps(1.0f / 8388608.0f);
64783  for (i = 0; i < frameCount4; ++i) {
64784  __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
64785  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
64786  __m128i right = _mm_sub_epi32(left, side);
64787  __m128 leftf = _mm_mul_ps(_mm_cvtepi32_ps(left), factor);
64788  __m128 rightf = _mm_mul_ps(_mm_cvtepi32_ps(right), factor);
64789  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
64790  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
64791  }
64792  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64793  drflac_uint32 left = pInputSamples0U32[i] << shift0;
64794  drflac_uint32 side = pInputSamples1U32[i] << shift1;
64795  drflac_uint32 right = left - side;
64796  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
64797  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
64798  }
64799 }
64800 #endif
64801 #if defined(DRFLAC_SUPPORT_NEON)
64802 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)
64803 {
64804  drflac_uint64 i;
64805  drflac_uint64 frameCount4 = frameCount >> 2;
64806  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64807  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64808  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
64809  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
64810  float32x4_t factor4;
64811  int32x4_t shift0_4;
64812  int32x4_t shift1_4;
64813  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64814  factor4 = vdupq_n_f32(1.0f / 8388608.0f);
64815  shift0_4 = vdupq_n_s32(shift0);
64816  shift1_4 = vdupq_n_s32(shift1);
64817  for (i = 0; i < frameCount4; ++i) {
64818  uint32x4_t left;
64819  uint32x4_t side;
64820  uint32x4_t right;
64821  float32x4_t leftf;
64822  float32x4_t rightf;
64823  left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
64824  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
64825  right = vsubq_u32(left, side);
64826  leftf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(left)), factor4);
64827  rightf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(right)), factor4);
64828  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
64829  }
64830  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64831  drflac_uint32 left = pInputSamples0U32[i] << shift0;
64832  drflac_uint32 side = pInputSamples1U32[i] << shift1;
64833  drflac_uint32 right = left - side;
64834  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
64835  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
64836  }
64837 }
64838 #endif
64839 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)
64840 {
64841 #if defined(DRFLAC_SUPPORT_SSE2)
64842  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
64843  drflac_read_pcm_frames_f32__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64844  } else
64845 #elif defined(DRFLAC_SUPPORT_NEON)
64846  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
64847  drflac_read_pcm_frames_f32__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64848  } else
64849 #endif
64850  {
64851 #if 0
64852  drflac_read_pcm_frames_f32__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64853 #else
64854  drflac_read_pcm_frames_f32__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64855 #endif
64856  }
64857 }
64858 #if 0
64859 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)
64860 {
64861  drflac_uint64 i;
64862  for (i = 0; i < frameCount; ++i) {
64863  drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
64864  drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
64865  drflac_uint32 left = right + side;
64866  pOutputSamples[i*2+0] = (float)((drflac_int32)left / 2147483648.0);
64867  pOutputSamples[i*2+1] = (float)((drflac_int32)right / 2147483648.0);
64868  }
64869 }
64870 #endif
64871 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)
64872 {
64873  drflac_uint64 i;
64874  drflac_uint64 frameCount4 = frameCount >> 2;
64875  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64876  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64877  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
64878  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
64879  float factor = 1 / 2147483648.0;
64880  for (i = 0; i < frameCount4; ++i) {
64881  drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
64882  drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
64883  drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
64884  drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
64885  drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
64886  drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
64887  drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
64888  drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
64889  drflac_uint32 left0 = right0 + side0;
64890  drflac_uint32 left1 = right1 + side1;
64891  drflac_uint32 left2 = right2 + side2;
64892  drflac_uint32 left3 = right3 + side3;
64893  pOutputSamples[i*8+0] = (drflac_int32)left0 * factor;
64894  pOutputSamples[i*8+1] = (drflac_int32)right0 * factor;
64895  pOutputSamples[i*8+2] = (drflac_int32)left1 * factor;
64896  pOutputSamples[i*8+3] = (drflac_int32)right1 * factor;
64897  pOutputSamples[i*8+4] = (drflac_int32)left2 * factor;
64898  pOutputSamples[i*8+5] = (drflac_int32)right2 * factor;
64899  pOutputSamples[i*8+6] = (drflac_int32)left3 * factor;
64900  pOutputSamples[i*8+7] = (drflac_int32)right3 * factor;
64901  }
64902  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64903  drflac_uint32 side = pInputSamples0U32[i] << shift0;
64904  drflac_uint32 right = pInputSamples1U32[i] << shift1;
64905  drflac_uint32 left = right + side;
64906  pOutputSamples[i*2+0] = (drflac_int32)left * factor;
64907  pOutputSamples[i*2+1] = (drflac_int32)right * factor;
64908  }
64909 }
64910 #if defined(DRFLAC_SUPPORT_SSE2)
64911 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)
64912 {
64913  drflac_uint64 i;
64914  drflac_uint64 frameCount4 = frameCount >> 2;
64915  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64916  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64917  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
64918  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
64919  __m128 factor;
64920  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64921  factor = _mm_set1_ps(1.0f / 8388608.0f);
64922  for (i = 0; i < frameCount4; ++i) {
64923  __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
64924  __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
64925  __m128i left = _mm_add_epi32(right, side);
64926  __m128 leftf = _mm_mul_ps(_mm_cvtepi32_ps(left), factor);
64927  __m128 rightf = _mm_mul_ps(_mm_cvtepi32_ps(right), factor);
64928  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
64929  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
64930  }
64931  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64932  drflac_uint32 side = pInputSamples0U32[i] << shift0;
64933  drflac_uint32 right = pInputSamples1U32[i] << shift1;
64934  drflac_uint32 left = right + side;
64935  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
64936  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
64937  }
64938 }
64939 #endif
64940 #if defined(DRFLAC_SUPPORT_NEON)
64941 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)
64942 {
64943  drflac_uint64 i;
64944  drflac_uint64 frameCount4 = frameCount >> 2;
64945  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
64946  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
64947  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
64948  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
64949  float32x4_t factor4;
64950  int32x4_t shift0_4;
64951  int32x4_t shift1_4;
64952  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
64953  factor4 = vdupq_n_f32(1.0f / 8388608.0f);
64954  shift0_4 = vdupq_n_s32(shift0);
64955  shift1_4 = vdupq_n_s32(shift1);
64956  for (i = 0; i < frameCount4; ++i) {
64957  uint32x4_t side;
64958  uint32x4_t right;
64959  uint32x4_t left;
64960  float32x4_t leftf;
64961  float32x4_t rightf;
64962  side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
64963  right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
64964  left = vaddq_u32(right, side);
64965  leftf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(left)), factor4);
64966  rightf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(right)), factor4);
64967  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
64968  }
64969  for (i = (frameCount4 << 2); i < frameCount; ++i) {
64970  drflac_uint32 side = pInputSamples0U32[i] << shift0;
64971  drflac_uint32 right = pInputSamples1U32[i] << shift1;
64972  drflac_uint32 left = right + side;
64973  pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
64974  pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
64975  }
64976 }
64977 #endif
64978 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)
64979 {
64980 #if defined(DRFLAC_SUPPORT_SSE2)
64981  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
64982  drflac_read_pcm_frames_f32__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64983  } else
64984 #elif defined(DRFLAC_SUPPORT_NEON)
64985  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
64986  drflac_read_pcm_frames_f32__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64987  } else
64988 #endif
64989  {
64990 #if 0
64991  drflac_read_pcm_frames_f32__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64992 #else
64993  drflac_read_pcm_frames_f32__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
64994 #endif
64995  }
64996 }
64997 #if 0
64998 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)
64999 {
65000  for (drflac_uint64 i = 0; i < frameCount; ++i) {
65001  drflac_uint32 mid = (drflac_uint32)pInputSamples0[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65002  drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65003  mid = (mid << 1) | (side & 0x01);
65004  pOutputSamples[i*2+0] = (float)((((drflac_int32)(mid + side) >> 1) << (unusedBitsPerSample)) / 2147483648.0);
65005  pOutputSamples[i*2+1] = (float)((((drflac_int32)(mid - side) >> 1) << (unusedBitsPerSample)) / 2147483648.0);
65006  }
65007 }
65008 #endif
65009 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)
65010 {
65011  drflac_uint64 i;
65012  drflac_uint64 frameCount4 = frameCount >> 2;
65013  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
65014  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
65015  drflac_uint32 shift = unusedBitsPerSample;
65016  float factor = 1 / 2147483648.0;
65017  if (shift > 0) {
65018  shift -= 1;
65019  for (i = 0; i < frameCount4; ++i) {
65020  drflac_uint32 temp0L;
65021  drflac_uint32 temp1L;
65022  drflac_uint32 temp2L;
65023  drflac_uint32 temp3L;
65024  drflac_uint32 temp0R;
65025  drflac_uint32 temp1R;
65026  drflac_uint32 temp2R;
65027  drflac_uint32 temp3R;
65028  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65029  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65030  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65031  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65032  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65033  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65034  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65035  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65036  mid0 = (mid0 << 1) | (side0 & 0x01);
65037  mid1 = (mid1 << 1) | (side1 & 0x01);
65038  mid2 = (mid2 << 1) | (side2 & 0x01);
65039  mid3 = (mid3 << 1) | (side3 & 0x01);
65040  temp0L = (mid0 + side0) << shift;
65041  temp1L = (mid1 + side1) << shift;
65042  temp2L = (mid2 + side2) << shift;
65043  temp3L = (mid3 + side3) << shift;
65044  temp0R = (mid0 - side0) << shift;
65045  temp1R = (mid1 - side1) << shift;
65046  temp2R = (mid2 - side2) << shift;
65047  temp3R = (mid3 - side3) << shift;
65048  pOutputSamples[i*8+0] = (drflac_int32)temp0L * factor;
65049  pOutputSamples[i*8+1] = (drflac_int32)temp0R * factor;
65050  pOutputSamples[i*8+2] = (drflac_int32)temp1L * factor;
65051  pOutputSamples[i*8+3] = (drflac_int32)temp1R * factor;
65052  pOutputSamples[i*8+4] = (drflac_int32)temp2L * factor;
65053  pOutputSamples[i*8+5] = (drflac_int32)temp2R * factor;
65054  pOutputSamples[i*8+6] = (drflac_int32)temp3L * factor;
65055  pOutputSamples[i*8+7] = (drflac_int32)temp3R * factor;
65056  }
65057  } else {
65058  for (i = 0; i < frameCount4; ++i) {
65059  drflac_uint32 temp0L;
65060  drflac_uint32 temp1L;
65061  drflac_uint32 temp2L;
65062  drflac_uint32 temp3L;
65063  drflac_uint32 temp0R;
65064  drflac_uint32 temp1R;
65065  drflac_uint32 temp2R;
65066  drflac_uint32 temp3R;
65067  drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65068  drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65069  drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65070  drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65071  drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65072  drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65073  drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65074  drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65075  mid0 = (mid0 << 1) | (side0 & 0x01);
65076  mid1 = (mid1 << 1) | (side1 & 0x01);
65077  mid2 = (mid2 << 1) | (side2 & 0x01);
65078  mid3 = (mid3 << 1) | (side3 & 0x01);
65079  temp0L = (drflac_uint32)((drflac_int32)(mid0 + side0) >> 1);
65080  temp1L = (drflac_uint32)((drflac_int32)(mid1 + side1) >> 1);
65081  temp2L = (drflac_uint32)((drflac_int32)(mid2 + side2) >> 1);
65082  temp3L = (drflac_uint32)((drflac_int32)(mid3 + side3) >> 1);
65083  temp0R = (drflac_uint32)((drflac_int32)(mid0 - side0) >> 1);
65084  temp1R = (drflac_uint32)((drflac_int32)(mid1 - side1) >> 1);
65085  temp2R = (drflac_uint32)((drflac_int32)(mid2 - side2) >> 1);
65086  temp3R = (drflac_uint32)((drflac_int32)(mid3 - side3) >> 1);
65087  pOutputSamples[i*8+0] = (drflac_int32)temp0L * factor;
65088  pOutputSamples[i*8+1] = (drflac_int32)temp0R * factor;
65089  pOutputSamples[i*8+2] = (drflac_int32)temp1L * factor;
65090  pOutputSamples[i*8+3] = (drflac_int32)temp1R * factor;
65091  pOutputSamples[i*8+4] = (drflac_int32)temp2L * factor;
65092  pOutputSamples[i*8+5] = (drflac_int32)temp2R * factor;
65093  pOutputSamples[i*8+6] = (drflac_int32)temp3L * factor;
65094  pOutputSamples[i*8+7] = (drflac_int32)temp3R * factor;
65095  }
65096  }
65097  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65098  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65099  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65100  mid = (mid << 1) | (side & 0x01);
65101  pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) * factor;
65102  pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) * factor;
65103  }
65104 }
65105 #if defined(DRFLAC_SUPPORT_SSE2)
65106 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)
65107 {
65108  drflac_uint64 i;
65109  drflac_uint64 frameCount4 = frameCount >> 2;
65110  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
65111  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
65112  drflac_uint32 shift = unusedBitsPerSample - 8;
65113  float factor;
65114  __m128 factor128;
65115  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
65116  factor = 1.0f / 8388608.0f;
65117  factor128 = _mm_set1_ps(factor);
65118  if (shift == 0) {
65119  for (i = 0; i < frameCount4; ++i) {
65120  __m128i mid;
65121  __m128i side;
65122  __m128i tempL;
65123  __m128i tempR;
65124  __m128 leftf;
65125  __m128 rightf;
65126  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
65127  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
65128  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
65129  tempL = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
65130  tempR = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
65131  leftf = _mm_mul_ps(_mm_cvtepi32_ps(tempL), factor128);
65132  rightf = _mm_mul_ps(_mm_cvtepi32_ps(tempR), factor128);
65133  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
65134  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
65135  }
65136  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65137  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65138  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65139  mid = (mid << 1) | (side & 0x01);
65140  pOutputSamples[i*2+0] = ((drflac_int32)(mid + side) >> 1) * factor;
65141  pOutputSamples[i*2+1] = ((drflac_int32)(mid - side) >> 1) * factor;
65142  }
65143  } else {
65144  shift -= 1;
65145  for (i = 0; i < frameCount4; ++i) {
65146  __m128i mid;
65147  __m128i side;
65148  __m128i tempL;
65149  __m128i tempR;
65150  __m128 leftf;
65151  __m128 rightf;
65152  mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
65153  side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
65154  mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
65155  tempL = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
65156  tempR = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
65157  leftf = _mm_mul_ps(_mm_cvtepi32_ps(tempL), factor128);
65158  rightf = _mm_mul_ps(_mm_cvtepi32_ps(tempR), factor128);
65159  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
65160  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
65161  }
65162  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65163  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65164  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65165  mid = (mid << 1) | (side & 0x01);
65166  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift) * factor;
65167  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift) * factor;
65168  }
65169  }
65170 }
65171 #endif
65172 #if defined(DRFLAC_SUPPORT_NEON)
65173 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)
65174 {
65175  drflac_uint64 i;
65176  drflac_uint64 frameCount4 = frameCount >> 2;
65177  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
65178  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
65179  drflac_uint32 shift = unusedBitsPerSample - 8;
65180  float factor;
65181  float32x4_t factor4;
65182  int32x4_t shift4;
65183  int32x4_t wbps0_4;
65184  int32x4_t wbps1_4;
65185  DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
65186  factor = 1.0f / 8388608.0f;
65187  factor4 = vdupq_n_f32(factor);
65188  wbps0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
65189  wbps1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
65190  if (shift == 0) {
65191  for (i = 0; i < frameCount4; ++i) {
65192  int32x4_t lefti;
65193  int32x4_t righti;
65194  float32x4_t leftf;
65195  float32x4_t rightf;
65196  uint32x4_t mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbps0_4);
65197  uint32x4_t side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbps1_4);
65198  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
65199  lefti = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
65200  righti = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
65201  leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
65202  rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
65203  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
65204  }
65205  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65206  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65207  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65208  mid = (mid << 1) | (side & 0x01);
65209  pOutputSamples[i*2+0] = ((drflac_int32)(mid + side) >> 1) * factor;
65210  pOutputSamples[i*2+1] = ((drflac_int32)(mid - side) >> 1) * factor;
65211  }
65212  } else {
65213  shift -= 1;
65214  shift4 = vdupq_n_s32(shift);
65215  for (i = 0; i < frameCount4; ++i) {
65216  uint32x4_t mid;
65217  uint32x4_t side;
65218  int32x4_t lefti;
65219  int32x4_t righti;
65220  float32x4_t leftf;
65221  float32x4_t rightf;
65222  mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbps0_4);
65223  side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbps1_4);
65224  mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
65225  lefti = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
65226  righti = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
65227  leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
65228  rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
65229  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
65230  }
65231  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65232  drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65233  drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65234  mid = (mid << 1) | (side & 0x01);
65235  pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift) * factor;
65236  pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift) * factor;
65237  }
65238  }
65239 }
65240 #endif
65241 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)
65242 {
65243 #if defined(DRFLAC_SUPPORT_SSE2)
65244  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
65245  drflac_read_pcm_frames_f32__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65246  } else
65247 #elif defined(DRFLAC_SUPPORT_NEON)
65248  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
65249  drflac_read_pcm_frames_f32__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65250  } else
65251 #endif
65252  {
65253 #if 0
65254  drflac_read_pcm_frames_f32__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65255 #else
65256  drflac_read_pcm_frames_f32__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65257 #endif
65258  }
65259 }
65260 #if 0
65261 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)
65262 {
65263  for (drflac_uint64 i = 0; i < frameCount; ++i) {
65264  pOutputSamples[i*2+0] = (float)((drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample)) / 2147483648.0);
65265  pOutputSamples[i*2+1] = (float)((drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample)) / 2147483648.0);
65266  }
65267 }
65268 #endif
65269 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)
65270 {
65271  drflac_uint64 i;
65272  drflac_uint64 frameCount4 = frameCount >> 2;
65273  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
65274  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
65275  drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
65276  drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
65277  float factor = 1 / 2147483648.0;
65278  for (i = 0; i < frameCount4; ++i) {
65279  drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
65280  drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
65281  drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
65282  drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
65283  drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
65284  drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
65285  drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
65286  drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
65287  pOutputSamples[i*8+0] = (drflac_int32)tempL0 * factor;
65288  pOutputSamples[i*8+1] = (drflac_int32)tempR0 * factor;
65289  pOutputSamples[i*8+2] = (drflac_int32)tempL1 * factor;
65290  pOutputSamples[i*8+3] = (drflac_int32)tempR1 * factor;
65291  pOutputSamples[i*8+4] = (drflac_int32)tempL2 * factor;
65292  pOutputSamples[i*8+5] = (drflac_int32)tempR2 * factor;
65293  pOutputSamples[i*8+6] = (drflac_int32)tempL3 * factor;
65294  pOutputSamples[i*8+7] = (drflac_int32)tempR3 * factor;
65295  }
65296  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65297  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
65298  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
65299  }
65300 }
65301 #if defined(DRFLAC_SUPPORT_SSE2)
65302 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)
65303 {
65304  drflac_uint64 i;
65305  drflac_uint64 frameCount4 = frameCount >> 2;
65306  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
65307  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
65308  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
65309  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
65310  float factor = 1.0f / 8388608.0f;
65311  __m128 factor128 = _mm_set1_ps(factor);
65312  for (i = 0; i < frameCount4; ++i) {
65313  __m128i lefti;
65314  __m128i righti;
65315  __m128 leftf;
65316  __m128 rightf;
65317  lefti = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
65318  righti = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
65319  leftf = _mm_mul_ps(_mm_cvtepi32_ps(lefti), factor128);
65320  rightf = _mm_mul_ps(_mm_cvtepi32_ps(righti), factor128);
65321  _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
65322  _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
65323  }
65324  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65325  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
65326  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
65327  }
65328 }
65329 #endif
65330 #if defined(DRFLAC_SUPPORT_NEON)
65331 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)
65332 {
65333  drflac_uint64 i;
65334  drflac_uint64 frameCount4 = frameCount >> 2;
65335  const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
65336  const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
65337  drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
65338  drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
65339  float factor = 1.0f / 8388608.0f;
65340  float32x4_t factor4 = vdupq_n_f32(factor);
65341  int32x4_t shift0_4 = vdupq_n_s32(shift0);
65342  int32x4_t shift1_4 = vdupq_n_s32(shift1);
65343  for (i = 0; i < frameCount4; ++i) {
65344  int32x4_t lefti;
65345  int32x4_t righti;
65346  float32x4_t leftf;
65347  float32x4_t rightf;
65348  lefti = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4));
65349  righti = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4));
65350  leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
65351  rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
65352  drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
65353  }
65354  for (i = (frameCount4 << 2); i < frameCount; ++i) {
65355  pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
65356  pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
65357  }
65358 }
65359 #endif
65360 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)
65361 {
65362 #if defined(DRFLAC_SUPPORT_SSE2)
65363  if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
65364  drflac_read_pcm_frames_f32__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65365  } else
65366 #elif defined(DRFLAC_SUPPORT_NEON)
65367  if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
65368  drflac_read_pcm_frames_f32__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65369  } else
65370 #endif
65371  {
65372 #if 0
65373  drflac_read_pcm_frames_f32__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65374 #else
65375  drflac_read_pcm_frames_f32__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
65376 #endif
65377  }
65378 }
65379 DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut)
65380 {
65381  drflac_uint64 framesRead;
65382  drflac_uint32 unusedBitsPerSample;
65383  if (pFlac == NULL || framesToRead == 0) {
65384  return 0;
65385  }
65386  if (pBufferOut == NULL) {
65387  return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
65388  }
65389  DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
65390  unusedBitsPerSample = 32 - pFlac->bitsPerSample;
65391  framesRead = 0;
65392  while (framesToRead > 0) {
65393  if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
65395  break;
65396  }
65397  } else {
65399  drflac_uint64 iFirstPCMFrame = pFlac->currentFLACFrame.header.blockSizeInPCMFrames - pFlac->currentFLACFrame.pcmFramesRemaining;
65400  drflac_uint64 frameCountThisIteration = framesToRead;
65401  if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
65402  frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
65403  }
65404  if (channelCount == 2) {
65405  const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
65406  const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
65407  switch (pFlac->currentFLACFrame.header.channelAssignment)
65408  {
65410  {
65411  drflac_read_pcm_frames_f32__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
65412  } break;
65414  {
65415  drflac_read_pcm_frames_f32__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
65416  } break;
65418  {
65419  drflac_read_pcm_frames_f32__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
65420  } break;
65422  default:
65423  {
65424  drflac_read_pcm_frames_f32__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
65425  } break;
65426  }
65427  } else {
65428  drflac_uint64 i;
65429  for (i = 0; i < frameCountThisIteration; ++i) {
65430  unsigned int j;
65431  for (j = 0; j < channelCount; ++j) {
65432  drflac_int32 sampleS32 = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
65433  pBufferOut[(i*channelCount)+j] = (float)(sampleS32 / 2147483648.0);
65434  }
65435  }
65436  }
65437  framesRead += frameCountThisIteration;
65438  pBufferOut += frameCountThisIteration * channelCount;
65439  framesToRead -= frameCountThisIteration;
65440  pFlac->currentPCMFrame += frameCountThisIteration;
65441  pFlac->currentFLACFrame.pcmFramesRemaining -= (unsigned int)frameCountThisIteration;
65442  }
65443  }
65444  return framesRead;
65445 }
65447 {
65448  if (pFlac == NULL) {
65449  return DRFLAC_FALSE;
65450  }
65451  if (pFlac->currentPCMFrame == pcmFrameIndex) {
65452  return DRFLAC_TRUE;
65453  }
65454  if (pFlac->firstFLACFramePosInBytes == 0) {
65455  return DRFLAC_FALSE;
65456  }
65457  if (pcmFrameIndex == 0) {
65458  pFlac->currentPCMFrame = 0;
65459  return drflac__seek_to_first_frame(pFlac);
65460  } else {
65461  drflac_bool32 wasSuccessful = DRFLAC_FALSE;
65462  drflac_uint64 originalPCMFrame = pFlac->currentPCMFrame;
65463  if (pcmFrameIndex > pFlac->totalPCMFrameCount) {
65464  pcmFrameIndex = pFlac->totalPCMFrameCount;
65465  }
65466  if (pcmFrameIndex > pFlac->currentPCMFrame) {
65467  drflac_uint32 offset = (drflac_uint32)(pcmFrameIndex - pFlac->currentPCMFrame);
65468  if (pFlac->currentFLACFrame.pcmFramesRemaining > offset) {
65469  pFlac->currentFLACFrame.pcmFramesRemaining -= offset;
65470  pFlac->currentPCMFrame = pcmFrameIndex;
65471  return DRFLAC_TRUE;
65472  }
65473  } else {
65474  drflac_uint32 offsetAbs = (drflac_uint32)(pFlac->currentPCMFrame - pcmFrameIndex);
65475  drflac_uint32 currentFLACFramePCMFrameCount = pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
65476  drflac_uint32 currentFLACFramePCMFramesConsumed = currentFLACFramePCMFrameCount - pFlac->currentFLACFrame.pcmFramesRemaining;
65477  if (currentFLACFramePCMFramesConsumed > offsetAbs) {
65478  pFlac->currentFLACFrame.pcmFramesRemaining += offsetAbs;
65479  pFlac->currentPCMFrame = pcmFrameIndex;
65480  return DRFLAC_TRUE;
65481  }
65482  }
65483 #ifndef DR_FLAC_NO_OGG
65484  if (pFlac->container == drflac_container_ogg)
65485  {
65486  wasSuccessful = drflac_ogg__seek_to_pcm_frame(pFlac, pcmFrameIndex);
65487  }
65488  else
65489 #endif
65490  {
65491  if (!pFlac->_noSeekTableSeek) {
65492  wasSuccessful = drflac__seek_to_pcm_frame__seek_table(pFlac, pcmFrameIndex);
65493  }
65494 #if !defined(DR_FLAC_NO_CRC)
65495  if (!wasSuccessful && !pFlac->_noBinarySearchSeek && pFlac->totalPCMFrameCount > 0) {
65496  wasSuccessful = drflac__seek_to_pcm_frame__binary_search(pFlac, pcmFrameIndex);
65497  }
65498 #endif
65499  if (!wasSuccessful && !pFlac->_noBruteForceSeek) {
65500  wasSuccessful = drflac__seek_to_pcm_frame__brute_force(pFlac, pcmFrameIndex);
65501  }
65502  }
65503  if (wasSuccessful) {
65504  pFlac->currentPCMFrame = pcmFrameIndex;
65505  } else {
65506  if (drflac_seek_to_pcm_frame(pFlac, originalPCMFrame) == DRFLAC_FALSE) {
65507  drflac_seek_to_pcm_frame(pFlac, 0);
65508  }
65509  }
65510  return wasSuccessful;
65511  }
65512 }
65513 #if defined(SIZE_MAX)
65514  #define DRFLAC_SIZE_MAX SIZE_MAX
65515 #else
65516  #if defined(DRFLAC_64BIT)
65517  #define DRFLAC_SIZE_MAX ((drflac_uint64)0xFFFFFFFFFFFFFFFF)
65518  #else
65519  #define DRFLAC_SIZE_MAX 0xFFFFFFFF
65520  #endif
65521 #endif
65522 #define DRFLAC_DEFINE_FULL_READ_AND_CLOSE(extension, type) \
65523 static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut)\
65524 { \
65525  type* pSampleData = NULL; \
65526  drflac_uint64 totalPCMFrameCount; \
65527  \
65528  DRFLAC_ASSERT(pFlac != NULL); \
65529  \
65530  totalPCMFrameCount = pFlac->totalPCMFrameCount; \
65531  \
65532  if (totalPCMFrameCount == 0) { \
65533  type buffer[4096]; \
65534  drflac_uint64 pcmFramesRead; \
65535  size_t sampleDataBufferSize = sizeof(buffer); \
65536  \
65537  pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
65538  if (pSampleData == NULL) { \
65539  goto on_error; \
65540  } \
65541  \
65542  while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
65543  if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
65544  type* pNewSampleData; \
65545  size_t newSampleDataBufferSize; \
65546  \
65547  newSampleDataBufferSize = sampleDataBufferSize * 2; \
65548  pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
65549  if (pNewSampleData == NULL) { \
65550  drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
65551  goto on_error; \
65552  } \
65553  \
65554  sampleDataBufferSize = newSampleDataBufferSize; \
65555  pSampleData = pNewSampleData; \
65556  } \
65557  \
65558  DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
65559  totalPCMFrameCount += pcmFramesRead; \
65560  } \
65561  \
65562  \
65563  DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
65564  } else { \
65565  drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
65566  if (dataSize > DRFLAC_SIZE_MAX) { \
65567  goto on_error; \
65568  } \
65569  \
65570  pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); \
65571  if (pSampleData == NULL) { \
65572  goto on_error; \
65573  } \
65574  \
65575  totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
65576  } \
65577  \
65578  if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
65579  if (channelsOut) *channelsOut = pFlac->channels; \
65580  if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
65581  \
65582  drflac_close(pFlac); \
65583  return pSampleData; \
65584  \
65585 on_error: \
65586  drflac_close(pFlac); \
65587  return NULL; \
65588 }
65592 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)
65593 {
65594  drflac* pFlac;
65595  if (channelsOut) {
65596  *channelsOut = 0;
65597  }
65598  if (sampleRateOut) {
65599  *sampleRateOut = 0;
65600  }
65601  if (totalPCMFrameCountOut) {
65602  *totalPCMFrameCountOut = 0;
65603  }
65604  pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
65605  if (pFlac == NULL) {
65606  return NULL;
65607  }
65608  return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
65609 }
65610 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)
65611 {
65612  drflac* pFlac;
65613  if (channelsOut) {
65614  *channelsOut = 0;
65615  }
65616  if (sampleRateOut) {
65617  *sampleRateOut = 0;
65618  }
65619  if (totalPCMFrameCountOut) {
65620  *totalPCMFrameCountOut = 0;
65621  }
65622  pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
65623  if (pFlac == NULL) {
65624  return NULL;
65625  }
65626  return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
65627 }
65628 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)
65629 {
65630  drflac* pFlac;
65631  if (channelsOut) {
65632  *channelsOut = 0;
65633  }
65634  if (sampleRateOut) {
65635  *sampleRateOut = 0;
65636  }
65637  if (totalPCMFrameCountOut) {
65638  *totalPCMFrameCountOut = 0;
65639  }
65640  pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
65641  if (pFlac == NULL) {
65642  return NULL;
65643  }
65644  return drflac__full_read_and_close_f32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
65645 }
65646 #ifndef DR_FLAC_NO_STDIO
65647 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)
65648 {
65649  drflac* pFlac;
65650  if (sampleRate) {
65651  *sampleRate = 0;
65652  }
65653  if (channels) {
65654  *channels = 0;
65655  }
65656  if (totalPCMFrameCount) {
65657  *totalPCMFrameCount = 0;
65658  }
65659  pFlac = drflac_open_file(filename, pAllocationCallbacks);
65660  if (pFlac == NULL) {
65661  return NULL;
65662  }
65663  return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
65664 }
65665 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)
65666 {
65667  drflac* pFlac;
65668  if (sampleRate) {
65669  *sampleRate = 0;
65670  }
65671  if (channels) {
65672  *channels = 0;
65673  }
65674  if (totalPCMFrameCount) {
65675  *totalPCMFrameCount = 0;
65676  }
65677  pFlac = drflac_open_file(filename, pAllocationCallbacks);
65678  if (pFlac == NULL) {
65679  return NULL;
65680  }
65681  return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
65682 }
65683 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)
65684 {
65685  drflac* pFlac;
65686  if (sampleRate) {
65687  *sampleRate = 0;
65688  }
65689  if (channels) {
65690  *channels = 0;
65691  }
65692  if (totalPCMFrameCount) {
65693  *totalPCMFrameCount = 0;
65694  }
65695  pFlac = drflac_open_file(filename, pAllocationCallbacks);
65696  if (pFlac == NULL) {
65697  return NULL;
65698  }
65699  return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
65700 }
65701 #endif
65702 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)
65703 {
65704  drflac* pFlac;
65705  if (sampleRate) {
65706  *sampleRate = 0;
65707  }
65708  if (channels) {
65709  *channels = 0;
65710  }
65711  if (totalPCMFrameCount) {
65712  *totalPCMFrameCount = 0;
65713  }
65714  pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
65715  if (pFlac == NULL) {
65716  return NULL;
65717  }
65718  return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
65719 }
65720 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)
65721 {
65722  drflac* pFlac;
65723  if (sampleRate) {
65724  *sampleRate = 0;
65725  }
65726  if (channels) {
65727  *channels = 0;
65728  }
65729  if (totalPCMFrameCount) {
65730  *totalPCMFrameCount = 0;
65731  }
65732  pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
65733  if (pFlac == NULL) {
65734  return NULL;
65735  }
65736  return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
65737 }
65738 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)
65739 {
65740  drflac* pFlac;
65741  if (sampleRate) {
65742  *sampleRate = 0;
65743  }
65744  if (channels) {
65745  *channels = 0;
65746  }
65747  if (totalPCMFrameCount) {
65748  *totalPCMFrameCount = 0;
65749  }
65750  pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
65751  if (pFlac == NULL) {
65752  return NULL;
65753  }
65754  return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
65755 }
65756 DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
65757 {
65758  if (pAllocationCallbacks != NULL) {
65759  drflac__free_from_callbacks(p, pAllocationCallbacks);
65760  } else {
65762  }
65763 }
65764 DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments)
65765 {
65766  if (pIter == NULL) {
65767  return;
65768  }
65769  pIter->countRemaining = commentCount;
65770  pIter->pRunningData = (const char*)pComments;
65771 }
65773 {
65774  drflac_int32 length;
65775  const char* pComment;
65776  if (pCommentLengthOut) {
65777  *pCommentLengthOut = 0;
65778  }
65779  if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
65780  return NULL;
65781  }
65782  length = drflac__le2host_32(*(const drflac_uint32*)pIter->pRunningData);
65783  pIter->pRunningData += 4;
65784  pComment = pIter->pRunningData;
65785  pIter->pRunningData += length;
65786  pIter->countRemaining -= 1;
65787  if (pCommentLengthOut) {
65788  *pCommentLengthOut = length;
65789  }
65790  return pComment;
65791 }
65792 DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData)
65793 {
65794  if (pIter == NULL) {
65795  return;
65796  }
65797  pIter->countRemaining = trackCount;
65798  pIter->pRunningData = (const char*)pTrackData;
65799 }
65801 {
65802  drflac_cuesheet_track cuesheetTrack;
65803  const char* pRunningData;
65804  drflac_uint64 offsetHi;
65805  drflac_uint64 offsetLo;
65806  if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
65807  return DRFLAC_FALSE;
65808  }
65809  pRunningData = pIter->pRunningData;
65810  offsetHi = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
65811  offsetLo = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
65812  cuesheetTrack.offset = offsetLo | (offsetHi << 32);
65813  cuesheetTrack.trackNumber = pRunningData[0]; pRunningData += 1;
65814  DRFLAC_COPY_MEMORY(cuesheetTrack.ISRC, pRunningData, sizeof(cuesheetTrack.ISRC)); pRunningData += 12;
65815  cuesheetTrack.isAudio = (pRunningData[0] & 0x80) != 0;
65816  cuesheetTrack.preEmphasis = (pRunningData[0] & 0x40) != 0; pRunningData += 14;
65817  cuesheetTrack.indexCount = pRunningData[0]; pRunningData += 1;
65818  cuesheetTrack.pIndexPoints = (const drflac_cuesheet_track_index*)pRunningData; pRunningData += cuesheetTrack.indexCount * sizeof(drflac_cuesheet_track_index);
65819  pIter->pRunningData = pRunningData;
65820  pIter->countRemaining -= 1;
65821  if (pCuesheetTrack) {
65822  *pCuesheetTrack = cuesheetTrack;
65823  }
65824  return DRFLAC_TRUE;
65825 }
65826 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
65827  #pragma GCC diagnostic pop
65828 #endif
65829 #endif
65830 /* dr_flac_c end */
65831 #endif /* DRFLAC_IMPLEMENTATION */
65832 #endif /* MA_NO_FLAC */
65833 
65834 #if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
65835 #if !defined(DR_MP3_IMPLEMENTATION) && !defined(DRMP3_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */
65836 /* dr_mp3_c begin */
65837 #ifndef dr_mp3_c
65838 #define dr_mp3_c
65839 #include <stdlib.h>
65840 #include <string.h>
65841 #include <limits.h>
65842 DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision)
65843 {
65844  if (pMajor) {
65845  *pMajor = DRMP3_VERSION_MAJOR;
65846  }
65847  if (pMinor) {
65848  *pMinor = DRMP3_VERSION_MINOR;
65849  }
65850  if (pRevision) {
65851  *pRevision = DRMP3_VERSION_REVISION;
65852  }
65853 }
65854 DRMP3_API const char* drmp3_version_string(void)
65855 {
65856  return DRMP3_VERSION_STRING;
65857 }
65858 #if defined(__TINYC__)
65859 #define DR_MP3_NO_SIMD
65860 #endif
65861 #define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
65862 #define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304
65863 #ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
65864 #define DRMP3_MAX_FRAME_SYNC_MATCHES 10
65865 #endif
65866 #define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE
65867 #define DRMP3_MAX_BITRESERVOIR_BYTES 511
65868 #define DRMP3_SHORT_BLOCK_TYPE 2
65869 #define DRMP3_STOP_BLOCK_TYPE 3
65870 #define DRMP3_MODE_MONO 3
65871 #define DRMP3_MODE_JOINT_STEREO 1
65872 #define DRMP3_HDR_SIZE 4
65873 #define DRMP3_HDR_IS_MONO(h) (((h[3]) & 0xC0) == 0xC0)
65874 #define DRMP3_HDR_IS_MS_STEREO(h) (((h[3]) & 0xE0) == 0x60)
65875 #define DRMP3_HDR_IS_FREE_FORMAT(h) (((h[2]) & 0xF0) == 0)
65876 #define DRMP3_HDR_IS_CRC(h) (!((h[1]) & 1))
65877 #define DRMP3_HDR_TEST_PADDING(h) ((h[2]) & 0x2)
65878 #define DRMP3_HDR_TEST_MPEG1(h) ((h[1]) & 0x8)
65879 #define DRMP3_HDR_TEST_NOT_MPEG25(h) ((h[1]) & 0x10)
65880 #define DRMP3_HDR_TEST_I_STEREO(h) ((h[3]) & 0x10)
65881 #define DRMP3_HDR_TEST_MS_STEREO(h) ((h[3]) & 0x20)
65882 #define DRMP3_HDR_GET_STEREO_MODE(h) (((h[3]) >> 6) & 3)
65883 #define DRMP3_HDR_GET_STEREO_MODE_EXT(h) (((h[3]) >> 4) & 3)
65884 #define DRMP3_HDR_GET_LAYER(h) (((h[1]) >> 1) & 3)
65885 #define DRMP3_HDR_GET_BITRATE(h) ((h[2]) >> 4)
65886 #define DRMP3_HDR_GET_SAMPLE_RATE(h) (((h[2]) >> 2) & 3)
65887 #define DRMP3_HDR_GET_MY_SAMPLE_RATE(h) (DRMP3_HDR_GET_SAMPLE_RATE(h) + (((h[1] >> 3) & 1) + ((h[1] >> 4) & 1))*3)
65888 #define DRMP3_HDR_IS_FRAME_576(h) ((h[1] & 14) == 2)
65889 #define DRMP3_HDR_IS_LAYER_1(h) ((h[1] & 6) == 6)
65890 #define DRMP3_BITS_DEQUANTIZER_OUT -1
65891 #define DRMP3_MAX_SCF (255 + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210)
65892 #define DRMP3_MAX_SCFI ((DRMP3_MAX_SCF + 3) & ~3)
65893 #define DRMP3_MIN(a, b) ((a) > (b) ? (b) : (a))
65894 #define DRMP3_MAX(a, b) ((a) < (b) ? (b) : (a))
65895 #if !defined(DR_MP3_NO_SIMD)
65896 #if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64))
65897 #define DR_MP3_ONLY_SIMD
65898 #endif
65899 #if ((defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_IX86) || defined(_M_X64))) || ((defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__))
65900 #if defined(_MSC_VER)
65901 #include <intrin.h>
65902 #endif
65903 #include <emmintrin.h>
65904 #define DRMP3_HAVE_SSE 1
65905 #define DRMP3_HAVE_SIMD 1
65906 #define DRMP3_VSTORE _mm_storeu_ps
65907 #define DRMP3_VLD _mm_loadu_ps
65908 #define DRMP3_VSET _mm_set1_ps
65909 #define DRMP3_VADD _mm_add_ps
65910 #define DRMP3_VSUB _mm_sub_ps
65911 #define DRMP3_VMUL _mm_mul_ps
65912 #define DRMP3_VMAC(a, x, y) _mm_add_ps(a, _mm_mul_ps(x, y))
65913 #define DRMP3_VMSB(a, x, y) _mm_sub_ps(a, _mm_mul_ps(x, y))
65914 #define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
65915 #define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
65916 typedef __m128 drmp3_f4;
65917 #if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
65918 #define drmp3_cpuid __cpuid
65919 #else
65920 static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
65921 {
65922 #if defined(__PIC__)
65923  __asm__ __volatile__(
65924 #if defined(__x86_64__)
65925  "push %%rbx\n"
65926  "cpuid\n"
65927  "xchgl %%ebx, %1\n"
65928  "pop %%rbx\n"
65929 #else
65930  "xchgl %%ebx, %1\n"
65931  "cpuid\n"
65932  "xchgl %%ebx, %1\n"
65933 #endif
65934  : "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
65935  : "a" (InfoType));
65936 #else
65937  __asm__ __volatile__(
65938  "cpuid"
65939  : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
65940  : "a" (InfoType));
65941 #endif
65942 }
65943 #endif
65944 static int drmp3_have_simd(void)
65945 {
65946 #ifdef DR_MP3_ONLY_SIMD
65947  return 1;
65948 #else
65949  static int g_have_simd;
65950  int CPUInfo[4];
65951 #ifdef MINIMP3_TEST
65952  static int g_counter;
65953  if (g_counter++ > 100)
65954  return 0;
65955 #endif
65956  if (g_have_simd)
65957  goto end;
65958  drmp3_cpuid(CPUInfo, 0);
65959  if (CPUInfo[0] > 0)
65960  {
65961  drmp3_cpuid(CPUInfo, 1);
65962  g_have_simd = (CPUInfo[3] & (1 << 26)) + 1;
65963  return g_have_simd - 1;
65964  }
65965 end:
65966  return g_have_simd - 1;
65967 #endif
65968 }
65969 #elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64)
65970 #include <arm_neon.h>
65971 #define DRMP3_HAVE_SSE 0
65972 #define DRMP3_HAVE_SIMD 1
65973 #define DRMP3_VSTORE vst1q_f32
65974 #define DRMP3_VLD vld1q_f32
65975 #define DRMP3_VSET vmovq_n_f32
65976 #define DRMP3_VADD vaddq_f32
65977 #define DRMP3_VSUB vsubq_f32
65978 #define DRMP3_VMUL vmulq_f32
65979 #define DRMP3_VMAC(a, x, y) vmlaq_f32(a, x, y)
65980 #define DRMP3_VMSB(a, x, y) vmlsq_f32(a, x, y)
65981 #define DRMP3_VMUL_S(x, s) vmulq_f32(x, vmovq_n_f32(s))
65982 #define DRMP3_VREV(x) vcombine_f32(vget_high_f32(vrev64q_f32(x)), vget_low_f32(vrev64q_f32(x)))
65983 typedef float32x4_t drmp3_f4;
65984 static int drmp3_have_simd(void)
65985 {
65986  return 1;
65987 }
65988 #else
65989 #define DRMP3_HAVE_SSE 0
65990 #define DRMP3_HAVE_SIMD 0
65991 #ifdef DR_MP3_ONLY_SIMD
65992 #error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled
65993 #endif
65994 #endif
65995 #else
65996 #define DRMP3_HAVE_SIMD 0
65997 #endif
65998 #if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64)
65999 #define DRMP3_HAVE_ARMV6 1
66000 static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_arm(drmp3_int32 a)
66001 {
66002  drmp3_int32 x = 0;
66003  __asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
66004  return x;
66005 }
66006 #else
66007 #define DRMP3_HAVE_ARMV6 0
66008 #endif
66009 typedef struct
66010 {
66011  const drmp3_uint8 *buf;
66012  int pos, limit;
66013 } drmp3_bs;
66014 typedef struct
66015 {
66016  float scf[3*64];
66017  drmp3_uint8 total_bands, stereo_bands, bitalloc[64], scfcod[64];
66019 typedef struct
66020 {
66021  drmp3_uint8 tab_offset, code_tab_width, band_count;
66023 typedef struct
66024 {
66025  const drmp3_uint8 *sfbtab;
66026  drmp3_uint16 part_23_length, big_values, scalefac_compress;
66027  drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
66028  drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
66029  drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
66031 typedef struct
66032 {
66033  drmp3_bs bs;
66034  drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
66035  drmp3_L3_gr_info gr_info[4];
66036  float grbuf[2][576], scf[40], syn[18 + 15][2*32];
66037  drmp3_uint8 ist_pos[2][39];
66039 static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
66040 {
66041  bs->buf = data;
66042  bs->pos = 0;
66043  bs->limit = bytes*8;
66044 }
66045 static drmp3_uint32 drmp3_bs_get_bits(drmp3_bs *bs, int n)
66046 {
66047  drmp3_uint32 next, cache = 0, s = bs->pos & 7;
66048  int shl = n + s;
66049  const drmp3_uint8 *p = bs->buf + (bs->pos >> 3);
66050  if ((bs->pos += n) > bs->limit)
66051  return 0;
66052  next = *p++ & (255 >> s);
66053  while ((shl -= 8) > 0)
66054  {
66055  cache |= next << shl;
66056  next = *p++;
66057  }
66058  return cache | (next >> -shl);
66059 }
66060 static int drmp3_hdr_valid(const drmp3_uint8 *h)
66061 {
66062  return h[0] == 0xff &&
66063  ((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) &&
66064  (DRMP3_HDR_GET_LAYER(h) != 0) &&
66065  (DRMP3_HDR_GET_BITRATE(h) != 15) &&
66066  (DRMP3_HDR_GET_SAMPLE_RATE(h) != 3);
66067 }
66068 static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2)
66069 {
66070  return drmp3_hdr_valid(h2) &&
66071  ((h1[1] ^ h2[1]) & 0xFE) == 0 &&
66072  ((h1[2] ^ h2[2]) & 0x0C) == 0 &&
66074 }
66075 static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h)
66076 {
66077  static const drmp3_uint8 halfrate[2][3][15] = {
66078  { { 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 } },
66079  { { 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 } },
66080  };
66081  return 2*halfrate[!!DRMP3_HDR_TEST_MPEG1(h)][DRMP3_HDR_GET_LAYER(h) - 1][DRMP3_HDR_GET_BITRATE(h)];
66082 }
66083 static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h)
66084 {
66085  static const unsigned g_hz[3] = { 44100, 48000, 32000 };
66086  return g_hz[DRMP3_HDR_GET_SAMPLE_RATE(h)] >> (int)!DRMP3_HDR_TEST_MPEG1(h) >> (int)!DRMP3_HDR_TEST_NOT_MPEG25(h);
66087 }
66088 static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h)
66089 {
66090  return DRMP3_HDR_IS_LAYER_1(h) ? 384 : (1152 >> (int)DRMP3_HDR_IS_FRAME_576(h));
66091 }
66092 static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size)
66093 {
66095  if (DRMP3_HDR_IS_LAYER_1(h))
66096  {
66097  frame_bytes &= ~3;
66098  }
66099  return frame_bytes ? frame_bytes : free_format_size;
66100 }
66101 static int drmp3_hdr_padding(const drmp3_uint8 *h)
66102 {
66103  return DRMP3_HDR_TEST_PADDING(h) ? (DRMP3_HDR_IS_LAYER_1(h) ? 4 : 1) : 0;
66104 }
66105 #ifndef DR_MP3_ONLY_MP3
66107 {
66108  const drmp3_L12_subband_alloc *alloc;
66109  int mode = DRMP3_HDR_GET_STEREO_MODE(hdr);
66110  int nbands, stereo_bands = (mode == DRMP3_MODE_MONO) ? 0 : (mode == DRMP3_MODE_JOINT_STEREO) ? (DRMP3_HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32;
66111  if (DRMP3_HDR_IS_LAYER_1(hdr))
66112  {
66113  static const drmp3_L12_subband_alloc g_alloc_L1[] = { { 76, 4, 32 } };
66114  alloc = g_alloc_L1;
66115  nbands = 32;
66116  } else if (!DRMP3_HDR_TEST_MPEG1(hdr))
66117  {
66118  static const drmp3_L12_subband_alloc g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } };
66119  alloc = g_alloc_L2M2;
66120  nbands = 30;
66121  } else
66122  {
66123  static const drmp3_L12_subband_alloc g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } };
66124  int sample_rate_idx = DRMP3_HDR_GET_SAMPLE_RATE(hdr);
66125  unsigned kbps = drmp3_hdr_bitrate_kbps(hdr) >> (int)(mode != DRMP3_MODE_MONO);
66126  if (!kbps)
66127  {
66128  kbps = 192;
66129  }
66130  alloc = g_alloc_L2M1;
66131  nbands = 27;
66132  if (kbps < 56)
66133  {
66134  static const drmp3_L12_subband_alloc g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } };
66135  alloc = g_alloc_L2M1_lowrate;
66136  nbands = sample_rate_idx == 2 ? 12 : 8;
66137  } else if (kbps >= 96 && sample_rate_idx != 1)
66138  {
66139  nbands = 30;
66140  }
66141  }
66142  sci->total_bands = (drmp3_uint8)nbands;
66143  sci->stereo_bands = (drmp3_uint8)DRMP3_MIN(stereo_bands, nbands);
66144  return alloc;
66145 }
66146 static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf)
66147 {
66148  static const float g_deq_L12[18*3] = {
66149 #define DRMP3_DQ(x) 9.53674316e-07f/x, 7.56931807e-07f/x, 6.00777173e-07f/x
66150  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)
66151  };
66152  int i, m;
66153  for (i = 0; i < bands; i++)
66154  {
66155  float s = 0;
66156  int ba = *pba++;
66157  int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0;
66158  for (m = 4; m; m >>= 1)
66159  {
66160  if (mask & m)
66161  {
66162  int b = drmp3_bs_get_bits(bs, 6);
66163  s = g_deq_L12[ba*3 - 6 + b % 3]*(int)(1 << 21 >> b/3);
66164  }
66165  *scf++ = s;
66166  }
66167  }
66168 }
66169 static void drmp3_L12_read_scale_info(const drmp3_uint8 *hdr, drmp3_bs *bs, drmp3_L12_scale_info *sci)
66170 {
66171  static const drmp3_uint8 g_bitalloc_code_tab[] = {
66172  0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16,
66173  0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16,
66174  0,17,18, 3,19,4,5,16,
66175  0,17,18,16,
66176  0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15,
66177  0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14,
66178  0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16
66179  };
66180  const drmp3_L12_subband_alloc *subband_alloc = drmp3_L12_subband_alloc_table(hdr, sci);
66181  int i, k = 0, ba_bits = 0;
66182  const drmp3_uint8 *ba_code_tab = g_bitalloc_code_tab;
66183  for (i = 0; i < sci->total_bands; i++)
66184  {
66185  drmp3_uint8 ba;
66186  if (i == k)
66187  {
66188  k += subband_alloc->band_count;
66189  ba_bits = subband_alloc->code_tab_width;
66190  ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset;
66191  subband_alloc++;
66192  }
66193  ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
66194  sci->bitalloc[2*i] = ba;
66195  if (i < sci->stereo_bands)
66196  {
66197  ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
66198  }
66199  sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0;
66200  }
66201  for (i = 0; i < 2*sci->total_bands; i++)
66202  {
66203  sci->scfcod[i] = (drmp3_uint8)(sci->bitalloc[i] ? DRMP3_HDR_IS_LAYER_1(hdr) ? 2 : drmp3_bs_get_bits(bs, 2) : 6);
66204  }
66205  drmp3_L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf);
66206  for (i = sci->stereo_bands; i < sci->total_bands; i++)
66207  {
66208  sci->bitalloc[2*i + 1] = 0;
66209  }
66210 }
66211 static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size)
66212 {
66213  int i, j, k, choff = 576;
66214  for (j = 0; j < 4; j++)
66215  {
66216  float *dst = grbuf + group_size*j;
66217  for (i = 0; i < 2*sci->total_bands; i++)
66218  {
66219  int ba = sci->bitalloc[i];
66220  if (ba != 0)
66221  {
66222  if (ba < 17)
66223  {
66224  int half = (1 << (ba - 1)) - 1;
66225  for (k = 0; k < group_size; k++)
66226  {
66227  dst[k] = (float)((int)drmp3_bs_get_bits(bs, ba) - half);
66228  }
66229  } else
66230  {
66231  unsigned mod = (2 << (ba - 17)) + 1;
66232  unsigned code = drmp3_bs_get_bits(bs, mod + 2 - (mod >> 3));
66233  for (k = 0; k < group_size; k++, code /= mod)
66234  {
66235  dst[k] = (float)((int)(code % mod - mod/2));
66236  }
66237  }
66238  }
66239  dst += choff;
66240  choff = 18 - choff;
66241  }
66242  }
66243  return group_size*4;
66244 }
66245 static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst)
66246 {
66247  int i, k;
66248  memcpy(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float));
66249  for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6)
66250  {
66251  for (k = 0; k < 12; k++)
66252  {
66253  dst[k + 0] *= scf[0];
66254  dst[k + 576] *= scf[3];
66255  }
66256  }
66257 }
66258 #endif
66259 static int drmp3_L3_read_side_info(drmp3_bs *bs, drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
66260 {
66261  static const drmp3_uint8 g_scf_long[8][23] = {
66262  { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
66263  { 12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2,0 },
66264  { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
66265  { 6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36,0 },
66266  { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
66267  { 4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,158,0 },
66268  { 4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,192,0 },
66269  { 4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,26,0 }
66270  };
66271  static const drmp3_uint8 g_scf_short[8][40] = {
66272  { 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 },
66273  { 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 },
66274  { 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 },
66275  { 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 },
66276  { 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 },
66277  { 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 },
66278  { 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 },
66279  { 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 }
66280  };
66281  static const drmp3_uint8 g_scf_mixed[8][40] = {
66282  { 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 },
66283  { 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 },
66284  { 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 },
66285  { 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 },
66286  { 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 },
66287  { 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 },
66288  { 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 },
66289  { 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 }
66290  };
66291  unsigned tables, scfsi = 0;
66292  int main_data_begin, part_23_sum = 0;
66293  int gr_count = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
66294  int sr_idx = DRMP3_HDR_GET_MY_SAMPLE_RATE(hdr); sr_idx -= (sr_idx != 0);
66295  if (DRMP3_HDR_TEST_MPEG1(hdr))
66296  {
66297  gr_count *= 2;
66298  main_data_begin = drmp3_bs_get_bits(bs, 9);
66299  scfsi = drmp3_bs_get_bits(bs, 7 + gr_count);
66300  } else
66301  {
66302  main_data_begin = drmp3_bs_get_bits(bs, 8 + gr_count) >> gr_count;
66303  }
66304  do
66305  {
66306  if (DRMP3_HDR_IS_MONO(hdr))
66307  {
66308  scfsi <<= 4;
66309  }
66311  part_23_sum += gr->part_23_length;
66313  if (gr->big_values > 288)
66314  {
66315  return -1;
66316  }
66319  gr->sfbtab = g_scf_long[sr_idx];
66320  gr->n_long_sfb = 22;
66321  gr->n_short_sfb = 0;
66322  if (drmp3_bs_get_bits(bs, 1))
66323  {
66325  if (!gr->block_type)
66326  {
66327  return -1;
66328  }
66330  gr->region_count[0] = 7;
66331  gr->region_count[1] = 255;
66333  {
66334  scfsi &= 0x0F0F;
66335  if (!gr->mixed_block_flag)
66336  {
66337  gr->region_count[0] = 8;
66338  gr->sfbtab = g_scf_short[sr_idx];
66339  gr->n_long_sfb = 0;
66340  gr->n_short_sfb = 39;
66341  } else
66342  {
66343  gr->sfbtab = g_scf_mixed[sr_idx];
66344  gr->n_long_sfb = DRMP3_HDR_TEST_MPEG1(hdr) ? 8 : 6;
66345  gr->n_short_sfb = 30;
66346  }
66347  }
66348  tables = drmp3_bs_get_bits(bs, 10);
66349  tables <<= 5;
66350  gr->subblock_gain[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
66351  gr->subblock_gain[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
66352  gr->subblock_gain[2] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
66353  } else
66354  {
66355  gr->block_type = 0;
66356  gr->mixed_block_flag = 0;
66357  tables = drmp3_bs_get_bits(bs, 15);
66358  gr->region_count[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 4);
66359  gr->region_count[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
66360  gr->region_count[2] = 255;
66361  }
66362  gr->table_select[0] = (drmp3_uint8)(tables >> 10);
66363  gr->table_select[1] = (drmp3_uint8)((tables >> 5) & 31);
66364  gr->table_select[2] = (drmp3_uint8)((tables) & 31);
66365  gr->preflag = (drmp3_uint8)(DRMP3_HDR_TEST_MPEG1(hdr) ? drmp3_bs_get_bits(bs, 1) : (gr->scalefac_compress >= 500));
66368  gr->scfsi = (drmp3_uint8)((scfsi >> 12) & 15);
66369  scfsi <<= 4;
66370  gr++;
66371  } while(--gr_count);
66372  if (part_23_sum + bs->pos > bs->limit + main_data_begin*8)
66373  {
66374  return -1;
66375  }
66376  return main_data_begin;
66377 }
66378 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)
66379 {
66380  int i, k;
66381  for (i = 0; i < 4 && scf_count[i]; i++, scfsi *= 2)
66382  {
66383  int cnt = scf_count[i];
66384  if (scfsi & 8)
66385  {
66386  memcpy(scf, ist_pos, cnt);
66387  } else
66388  {
66389  int bits = scf_size[i];
66390  if (!bits)
66391  {
66392  memset(scf, 0, cnt);
66393  memset(ist_pos, 0, cnt);
66394  } else
66395  {
66396  int max_scf = (scfsi < 0) ? (1 << bits) - 1 : -1;
66397  for (k = 0; k < cnt; k++)
66398  {
66399  int s = drmp3_bs_get_bits(bitbuf, bits);
66400  ist_pos[k] = (drmp3_uint8)(s == max_scf ? -1 : s);
66401  scf[k] = (drmp3_uint8)s;
66402  }
66403  }
66404  }
66405  ist_pos += cnt;
66406  scf += cnt;
66407  }
66408  scf[0] = scf[1] = scf[2] = 0;
66409 }
66410 static float drmp3_L3_ldexp_q2(float y, int exp_q2)
66411 {
66412  static const float g_expfrac[4] = { 9.31322575e-10f,7.83145814e-10f,6.58544508e-10f,5.53767716e-10f };
66413  int e;
66414  do
66415  {
66416  e = DRMP3_MIN(30*4, exp_q2);
66417  y *= g_expfrac[e & 3]*(1 << 30 >> (e >> 2));
66418  } while ((exp_q2 -= e) > 0);
66419  return y;
66420 }
66421 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)
66422 {
66423  static const drmp3_uint8 g_scf_partitions[3][28] = {
66424  { 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 },
66425  { 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 },
66426  { 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 }
66427  };
66428  const drmp3_uint8 *scf_partition = g_scf_partitions[!!gr->n_short_sfb + !gr->n_long_sfb];
66429  drmp3_uint8 scf_size[4], iscf[40];
66430  int i, scf_shift = gr->scalefac_scale + 1, gain_exp, scfsi = gr->scfsi;
66431  float gain;
66432  if (DRMP3_HDR_TEST_MPEG1(hdr))
66433  {
66434  static const drmp3_uint8 g_scfc_decode[16] = { 0,1,2,3, 12,5,6,7, 9,10,11,13, 14,15,18,19 };
66435  int part = g_scfc_decode[gr->scalefac_compress];
66436  scf_size[1] = scf_size[0] = (drmp3_uint8)(part >> 2);
66437  scf_size[3] = scf_size[2] = (drmp3_uint8)(part & 3);
66438  } else
66439  {
66440  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 };
66441  int k, modprod, sfc, ist = DRMP3_HDR_TEST_I_STEREO(hdr) && ch;
66442  sfc = gr->scalefac_compress >> ist;
66443  for (k = ist*3*4; sfc >= 0; sfc -= modprod, k += 4)
66444  {
66445  for (modprod = 1, i = 3; i >= 0; i--)
66446  {
66447  scf_size[i] = (drmp3_uint8)(sfc / modprod % g_mod[k + i]);
66448  modprod *= g_mod[k + i];
66449  }
66450  }
66451  scf_partition += k;
66452  scfsi = -16;
66453  }
66454  drmp3_L3_read_scalefactors(iscf, ist_pos, scf_size, scf_partition, bs, scfsi);
66455  if (gr->n_short_sfb)
66456  {
66457  int sh = 3 - scf_shift;
66458  for (i = 0; i < gr->n_short_sfb; i += 3)
66459  {
66460  iscf[gr->n_long_sfb + i + 0] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 0] + (gr->subblock_gain[0] << sh));
66461  iscf[gr->n_long_sfb + i + 1] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 1] + (gr->subblock_gain[1] << sh));
66462  iscf[gr->n_long_sfb + i + 2] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 2] + (gr->subblock_gain[2] << sh));
66463  }
66464  } else if (gr->preflag)
66465  {
66466  static const drmp3_uint8 g_preamp[10] = { 1,1,1,1,2,2,3,3,3,2 };
66467  for (i = 0; i < 10; i++)
66468  {
66469  iscf[11 + i] = (drmp3_uint8)(iscf[11 + i] + g_preamp[i]);
66470  }
66471  }
66472  gain_exp = gr->global_gain + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210 - (DRMP3_HDR_IS_MS_STEREO(hdr) ? 2 : 0);
66473  gain = drmp3_L3_ldexp_q2(1 << (DRMP3_MAX_SCFI/4), DRMP3_MAX_SCFI - gain_exp);
66474  for (i = 0; i < (int)(gr->n_long_sfb + gr->n_short_sfb); i++)
66475  {
66476  scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
66477  }
66478 }
66479 static const float g_drmp3_pow43[129 + 16] = {
66480  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,
66481  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
66482 };
66483 static float drmp3_L3_pow_43(int x)
66484 {
66485  float frac;
66486  int sign, mult = 256;
66487  if (x < 129)
66488  {
66489  return g_drmp3_pow43[16 + x];
66490  }
66491  if (x < 1024)
66492  {
66493  mult = 16;
66494  x <<= 3;
66495  }
66496  sign = 2*x & 64;
66497  frac = (float)((x & 63) - sign) / ((x & ~63) + sign);
66498  return g_drmp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult;
66499 }
66500 static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
66501 {
66502  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,
66503  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,
66504  -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,
66505  -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,
66506  -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,
66507  -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,
66508  -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,
66509  -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,
66510  -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,
66511  -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,
66512  -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,
66513  -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,
66514  -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,
66515  -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,
66516  -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,
66517  -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 };
66518  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};
66519  static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 };
66520  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 };
66521  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 };
66522 #define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - n))
66523 #define DRMP3_FLUSH_BITS(n) { bs_cache <<= (n); bs_sh += (n); }
66524 #define DRMP3_CHECK_BITS while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; }
66525 #define DRMP3_BSPOS ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh)
66526  float one = 0.0f;
66527  int ireg = 0, big_val_cnt = gr_info->big_values;
66528  const drmp3_uint8 *sfb = gr_info->sfbtab;
66529  const drmp3_uint8 *bs_next_ptr = bs->buf + bs->pos/8;
66530  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);
66531  int pairs_to_decode, np, bs_sh = (bs->pos & 7) - 8;
66532  bs_next_ptr += 4;
66533  while (big_val_cnt > 0)
66534  {
66535  int tab_num = gr_info->table_select[ireg];
66536  int sfb_cnt = gr_info->region_count[ireg++];
66537  const drmp3_int16 *codebook = tabs + tabindex[tab_num];
66538  int linbits = g_linbits[tab_num];
66539  if (linbits)
66540  {
66541  do
66542  {
66543  np = *sfb++ / 2;
66544  pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
66545  one = *scf++;
66546  do
66547  {
66548  int j, w = 5;
66549  int leaf = codebook[DRMP3_PEEK_BITS(w)];
66550  while (leaf < 0)
66551  {
66552  DRMP3_FLUSH_BITS(w);
66553  w = leaf & 7;
66554  leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
66555  }
66556  DRMP3_FLUSH_BITS(leaf >> 8);
66557  for (j = 0; j < 2; j++, dst++, leaf >>= 4)
66558  {
66559  int lsb = leaf & 0x0F;
66560  if (lsb == 15)
66561  {
66562  lsb += DRMP3_PEEK_BITS(linbits);
66563  DRMP3_FLUSH_BITS(linbits);
66565  *dst = one*drmp3_L3_pow_43(lsb)*((drmp3_int32)bs_cache < 0 ? -1: 1);
66566  } else
66567  {
66568  *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
66569  }
66570  DRMP3_FLUSH_BITS(lsb ? 1 : 0);
66571  }
66573  } while (--pairs_to_decode);
66574  } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
66575  } else
66576  {
66577  do
66578  {
66579  np = *sfb++ / 2;
66580  pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
66581  one = *scf++;
66582  do
66583  {
66584  int j, w = 5;
66585  int leaf = codebook[DRMP3_PEEK_BITS(w)];
66586  while (leaf < 0)
66587  {
66588  DRMP3_FLUSH_BITS(w);
66589  w = leaf & 7;
66590  leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
66591  }
66592  DRMP3_FLUSH_BITS(leaf >> 8);
66593  for (j = 0; j < 2; j++, dst++, leaf >>= 4)
66594  {
66595  int lsb = leaf & 0x0F;
66596  *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
66597  DRMP3_FLUSH_BITS(lsb ? 1 : 0);
66598  }
66600  } while (--pairs_to_decode);
66601  } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
66602  }
66603  }
66604  for (np = 1 - big_val_cnt;; dst += 4)
66605  {
66606  const drmp3_uint8 *codebook_count1 = (gr_info->count1_table) ? tab33 : tab32;
66607  int leaf = codebook_count1[DRMP3_PEEK_BITS(4)];
66608  if (!(leaf & 8))
66609  {
66610  leaf = codebook_count1[(leaf >> 3) + (bs_cache << 4 >> (32 - (leaf & 3)))];
66611  }
66612  DRMP3_FLUSH_BITS(leaf & 7);
66613  if (DRMP3_BSPOS > layer3gr_limit)
66614  {
66615  break;
66616  }
66617 #define DRMP3_RELOAD_SCALEFACTOR if (!--np) { np = *sfb++/2; if (!np) break; one = *scf++; }
66618 #define DRMP3_DEQ_COUNT1(s) if (leaf & (128 >> s)) { dst[s] = ((drmp3_int32)bs_cache < 0) ? -one : one; DRMP3_FLUSH_BITS(1) }
66620  DRMP3_DEQ_COUNT1(0);
66621  DRMP3_DEQ_COUNT1(1);
66623  DRMP3_DEQ_COUNT1(2);
66624  DRMP3_DEQ_COUNT1(3);
66626  }
66627  bs->pos = layer3gr_limit;
66628 }
66629 static void drmp3_L3_midside_stereo(float *left, int n)
66630 {
66631  int i = 0;
66632  float *right = left + 576;
66633 #if DRMP3_HAVE_SIMD
66634  if (drmp3_have_simd()) for (; i < n - 3; i += 4)
66635  {
66636  drmp3_f4 vl = DRMP3_VLD(left + i);
66637  drmp3_f4 vr = DRMP3_VLD(right + i);
66638  DRMP3_VSTORE(left + i, DRMP3_VADD(vl, vr));
66639  DRMP3_VSTORE(right + i, DRMP3_VSUB(vl, vr));
66640  }
66641 #endif
66642  for (; i < n; i++)
66643  {
66644  float a = left[i];
66645  float b = right[i];
66646  left[i] = a + b;
66647  right[i] = a - b;
66648  }
66649 }
66650 static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr)
66651 {
66652  int i;
66653  for (i = 0; i < n; i++)
66654  {
66655  left[i + 576] = left[i]*kr;
66656  left[i] = left[i]*kl;
66657  }
66658 }
66659 static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3])
66660 {
66661  int i, k;
66662  max_band[0] = max_band[1] = max_band[2] = -1;
66663  for (i = 0; i < nbands; i++)
66664  {
66665  for (k = 0; k < sfb[i]; k += 2)
66666  {
66667  if (right[k] != 0 || right[k + 1] != 0)
66668  {
66669  max_band[i % 3] = i;
66670  break;
66671  }
66672  }
66673  right += sfb[i];
66674  }
66675 }
66676 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)
66677 {
66678  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 };
66679  unsigned i, max_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 7 : 64;
66680  for (i = 0; sfb[i]; i++)
66681  {
66682  unsigned ipos = ist_pos[i];
66683  if ((int)i > max_band[i % 3] && ipos < max_pos)
66684  {
66685  float kl, kr, s = DRMP3_HDR_TEST_MS_STEREO(hdr) ? 1.41421356f : 1;
66686  if (DRMP3_HDR_TEST_MPEG1(hdr))
66687  {
66688  kl = g_pan[2*ipos];
66689  kr = g_pan[2*ipos + 1];
66690  } else
66691  {
66692  kl = 1;
66693  kr = drmp3_L3_ldexp_q2(1, (ipos + 1) >> 1 << mpeg2_sh);
66694  if (ipos & 1)
66695  {
66696  kl = kr;
66697  kr = 1;
66698  }
66699  }
66700  drmp3_L3_intensity_stereo_band(left, sfb[i], kl*s, kr*s);
66701  } else if (DRMP3_HDR_TEST_MS_STEREO(hdr))
66702  {
66703  drmp3_L3_midside_stereo(left, sfb[i]);
66704  }
66705  left += sfb[i];
66706  }
66707 }
66708 static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
66709 {
66710  int max_band[3], n_sfb = gr->n_long_sfb + gr->n_short_sfb;
66711  int i, max_blocks = gr->n_short_sfb ? 3 : 1;
66712  drmp3_L3_stereo_top_band(left + 576, gr->sfbtab, n_sfb, max_band);
66713  if (gr->n_long_sfb)
66714  {
66715  max_band[0] = max_band[1] = max_band[2] = DRMP3_MAX(DRMP3_MAX(max_band[0], max_band[1]), max_band[2]);
66716  }
66717  for (i = 0; i < max_blocks; i++)
66718  {
66719  int default_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 3 : 0;
66720  int itop = n_sfb - max_blocks + i;
66721  int prev = itop - max_blocks;
66722  ist_pos[itop] = (drmp3_uint8)(max_band[i] >= prev ? default_pos : ist_pos[prev]);
66723  }
66724  drmp3_L3_stereo_process(left, ist_pos, gr->sfbtab, hdr, max_band, gr[1].scalefac_compress & 1);
66725 }
66726 static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb)
66727 {
66728  int i, len;
66729  float *src = grbuf, *dst = scratch;
66730  for (;0 != (len = *sfb); sfb += 3, src += 2*len)
66731  {
66732  for (i = 0; i < len; i++, src++)
66733  {
66734  *dst++ = src[0*len];
66735  *dst++ = src[1*len];
66736  *dst++ = src[2*len];
66737  }
66738  }
66739  memcpy(grbuf, scratch, (dst - scratch)*sizeof(float));
66740 }
66741 static void drmp3_L3_antialias(float *grbuf, int nbands)
66742 {
66743  static const float g_aa[2][8] = {
66744  {0.85749293f,0.88174200f,0.94962865f,0.98331459f,0.99551782f,0.99916056f,0.99989920f,0.99999316f},
66745  {0.51449576f,0.47173197f,0.31337745f,0.18191320f,0.09457419f,0.04096558f,0.01419856f,0.00369997f}
66746  };
66747  for (; nbands > 0; nbands--, grbuf += 18)
66748  {
66749  int i = 0;
66750 #if DRMP3_HAVE_SIMD
66751  if (drmp3_have_simd()) for (; i < 8; i += 4)
66752  {
66753  drmp3_f4 vu = DRMP3_VLD(grbuf + 18 + i);
66754  drmp3_f4 vd = DRMP3_VLD(grbuf + 14 - i);
66755  drmp3_f4 vc0 = DRMP3_VLD(g_aa[0] + i);
66756  drmp3_f4 vc1 = DRMP3_VLD(g_aa[1] + i);
66757  vd = DRMP3_VREV(vd);
66758  DRMP3_VSTORE(grbuf + 18 + i, DRMP3_VSUB(DRMP3_VMUL(vu, vc0), DRMP3_VMUL(vd, vc1)));
66759  vd = DRMP3_VADD(DRMP3_VMUL(vu, vc1), DRMP3_VMUL(vd, vc0));
66760  DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vd));
66761  }
66762 #endif
66763 #ifndef DR_MP3_ONLY_SIMD
66764  for(; i < 8; i++)
66765  {
66766  float u = grbuf[18 + i];
66767  float d = grbuf[17 - i];
66768  grbuf[18 + i] = u*g_aa[0][i] - d*g_aa[1][i];
66769  grbuf[17 - i] = u*g_aa[1][i] + d*g_aa[0][i];
66770  }
66771 #endif
66772  }
66773 }
66774 static void drmp3_L3_dct3_9(float *y)
66775 {
66776  float s0, s1, s2, s3, s4, s5, s6, s7, s8, t0, t2, t4;
66777  s0 = y[0]; s2 = y[2]; s4 = y[4]; s6 = y[6]; s8 = y[8];
66778  t0 = s0 + s6*0.5f;
66779  s0 -= s6;
66780  t4 = (s4 + s2)*0.93969262f;
66781  t2 = (s8 + s2)*0.76604444f;
66782  s6 = (s4 - s8)*0.17364818f;
66783  s4 += s8 - s2;
66784  s2 = s0 - s4*0.5f;
66785  y[4] = s4 + s0;
66786  s8 = t0 - t2 + s6;
66787  s0 = t0 - t4 + t2;
66788  s4 = t0 + t4 - s6;
66789  s1 = y[1]; s3 = y[3]; s5 = y[5]; s7 = y[7];
66790  s3 *= 0.86602540f;
66791  t0 = (s5 + s1)*0.98480775f;
66792  t4 = (s5 - s7)*0.34202014f;
66793  t2 = (s1 + s7)*0.64278761f;
66794  s1 = (s1 - s5 - s7)*0.86602540f;
66795  s5 = t0 - s3 - t2;
66796  s7 = t4 - s3 - t0;
66797  s3 = t4 + s3 - t2;
66798  y[0] = s4 - s7;
66799  y[1] = s2 + s1;
66800  y[2] = s0 - s3;
66801  y[3] = s8 + s5;
66802  y[5] = s8 - s5;
66803  y[6] = s0 + s3;
66804  y[7] = s2 - s1;
66805  y[8] = s4 + s7;
66806 }
66807 static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands)
66808 {
66809  int i, j;
66810  static const float g_twid9[18] = {
66811  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
66812  };
66813  for (j = 0; j < nbands; j++, grbuf += 18, overlap += 9)
66814  {
66815  float co[9], si[9];
66816  co[0] = -grbuf[0];
66817  si[0] = grbuf[17];
66818  for (i = 0; i < 4; i++)
66819  {
66820  si[8 - 2*i] = grbuf[4*i + 1] - grbuf[4*i + 2];
66821  co[1 + 2*i] = grbuf[4*i + 1] + grbuf[4*i + 2];
66822  si[7 - 2*i] = grbuf[4*i + 4] - grbuf[4*i + 3];
66823  co[2 + 2*i] = -(grbuf[4*i + 3] + grbuf[4*i + 4]);
66824  }
66825  drmp3_L3_dct3_9(co);
66826  drmp3_L3_dct3_9(si);
66827  si[1] = -si[1];
66828  si[3] = -si[3];
66829  si[5] = -si[5];
66830  si[7] = -si[7];
66831  i = 0;
66832 #if DRMP3_HAVE_SIMD
66833  if (drmp3_have_simd()) for (; i < 8; i += 4)
66834  {
66835  drmp3_f4 vovl = DRMP3_VLD(overlap + i);
66836  drmp3_f4 vc = DRMP3_VLD(co + i);
66837  drmp3_f4 vs = DRMP3_VLD(si + i);
66838  drmp3_f4 vr0 = DRMP3_VLD(g_twid9 + i);
66839  drmp3_f4 vr1 = DRMP3_VLD(g_twid9 + 9 + i);
66840  drmp3_f4 vw0 = DRMP3_VLD(window + i);
66841  drmp3_f4 vw1 = DRMP3_VLD(window + 9 + i);
66842  drmp3_f4 vsum = DRMP3_VADD(DRMP3_VMUL(vc, vr1), DRMP3_VMUL(vs, vr0));
66843  DRMP3_VSTORE(overlap + i, DRMP3_VSUB(DRMP3_VMUL(vc, vr0), DRMP3_VMUL(vs, vr1)));
66844  DRMP3_VSTORE(grbuf + i, DRMP3_VSUB(DRMP3_VMUL(vovl, vw0), DRMP3_VMUL(vsum, vw1)));
66845  vsum = DRMP3_VADD(DRMP3_VMUL(vovl, vw1), DRMP3_VMUL(vsum, vw0));
66846  DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vsum));
66847  }
66848 #endif
66849  for (; i < 9; i++)
66850  {
66851  float ovl = overlap[i];
66852  float sum = co[i]*g_twid9[9 + i] + si[i]*g_twid9[0 + i];
66853  overlap[i] = co[i]*g_twid9[0 + i] - si[i]*g_twid9[9 + i];
66854  grbuf[i] = ovl*window[0 + i] - sum*window[9 + i];
66855  grbuf[17 - i] = ovl*window[9 + i] + sum*window[0 + i];
66856  }
66857  }
66858 }
66859 static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst)
66860 {
66861  float m1 = x1*0.86602540f;
66862  float a1 = x0 - x2*0.5f;
66863  dst[1] = x0 + x2;
66864  dst[0] = a1 + m1;
66865  dst[2] = a1 - m1;
66866 }
66867 static void drmp3_L3_imdct12(float *x, float *dst, float *overlap)
66868 {
66869  static const float g_twid3[6] = { 0.79335334f,0.92387953f,0.99144486f, 0.60876143f,0.38268343f,0.13052619f };
66870  float co[3], si[3];
66871  int i;
66872  drmp3_L3_idct3(-x[0], x[6] + x[3], x[12] + x[9], co);
66873  drmp3_L3_idct3(x[15], x[12] - x[9], x[6] - x[3], si);
66874  si[1] = -si[1];
66875  for (i = 0; i < 3; i++)
66876  {
66877  float ovl = overlap[i];
66878  float sum = co[i]*g_twid3[3 + i] + si[i]*g_twid3[0 + i];
66879  overlap[i] = co[i]*g_twid3[0 + i] - si[i]*g_twid3[3 + i];
66880  dst[i] = ovl*g_twid3[2 - i] - sum*g_twid3[5 - i];
66881  dst[5 - i] = ovl*g_twid3[5 - i] + sum*g_twid3[2 - i];
66882  }
66883 }
66884 static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands)
66885 {
66886  for (;nbands > 0; nbands--, overlap += 9, grbuf += 18)
66887  {
66888  float tmp[18];
66889  memcpy(tmp, grbuf, sizeof(tmp));
66890  memcpy(grbuf, overlap, 6*sizeof(float));
66891  drmp3_L3_imdct12(tmp, grbuf + 6, overlap + 6);
66892  drmp3_L3_imdct12(tmp + 1, grbuf + 12, overlap + 6);
66893  drmp3_L3_imdct12(tmp + 2, overlap, overlap + 6);
66894  }
66895 }
66896 static void drmp3_L3_change_sign(float *grbuf)
66897 {
66898  int b, i;
66899  for (b = 0, grbuf += 18; b < 32; b += 2, grbuf += 36)
66900  for (i = 1; i < 18; i += 2)
66901  grbuf[i] = -grbuf[i];
66902 }
66903 static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands)
66904 {
66905  static const float g_mdct_window[2][18] = {
66906  { 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 },
66907  { 1,1,1,1,1,1,0.99144486f,0.92387953f,0.79335334f,0,0,0,0,0,0,0.13052619f,0.38268343f,0.60876143f }
66908  };
66909  if (n_long_bands)
66910  {
66911  drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands);
66912  grbuf += 18*n_long_bands;
66913  overlap += 9*n_long_bands;
66914  }
66915  if (block_type == DRMP3_SHORT_BLOCK_TYPE)
66916  drmp3_L3_imdct_short(grbuf, overlap, 32 - n_long_bands);
66917  else
66918  drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[block_type == DRMP3_STOP_BLOCK_TYPE], 32 - n_long_bands);
66919 }
66921 {
66922  int pos = (s->bs.pos + 7)/8u;
66923  int remains = s->bs.limit/8u - pos;
66924  if (remains > DRMP3_MAX_BITRESERVOIR_BYTES)
66925  {
66926  pos += remains - DRMP3_MAX_BITRESERVOIR_BYTES;
66927  remains = DRMP3_MAX_BITRESERVOIR_BYTES;
66928  }
66929  if (remains > 0)
66930  {
66931  memmove(h->reserv_buf, s->maindata + pos, remains);
66932  }
66933  h->reserv = remains;
66934 }
66935 static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin)
66936 {
66937  int frame_bytes = (bs->limit - bs->pos)/8;
66938  int bytes_have = DRMP3_MIN(h->reserv, main_data_begin);
66939  memcpy(s->maindata, h->reserv_buf + DRMP3_MAX(0, h->reserv - main_data_begin), DRMP3_MIN(h->reserv, main_data_begin));
66940  memcpy(s->maindata + bytes_have, bs->buf + bs->pos/8, frame_bytes);
66941  drmp3_bs_init(&s->bs, s->maindata, bytes_have + frame_bytes);
66942  return h->reserv >= main_data_begin;
66943 }
66944 static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch)
66945 {
66946  int ch;
66947  for (ch = 0; ch < nch; ch++)
66948  {
66949  int layer3gr_limit = s->bs.pos + gr_info[ch].part_23_length;
66950  drmp3_L3_decode_scalefactors(h->header, s->ist_pos[ch], &s->bs, gr_info + ch, s->scf, ch);
66951  drmp3_L3_huffman(s->grbuf[ch], &s->bs, gr_info + ch, s->scf, layer3gr_limit);
66952  }
66954  {
66955  drmp3_L3_intensity_stereo(s->grbuf[0], s->ist_pos[1], gr_info, h->header);
66956  } else if (DRMP3_HDR_IS_MS_STEREO(h->header))
66957  {
66958  drmp3_L3_midside_stereo(s->grbuf[0], 576);
66959  }
66960  for (ch = 0; ch < nch; ch++, gr_info++)
66961  {
66962  int aa_bands = 31;
66963  int n_long_bands = (gr_info->mixed_block_flag ? 2 : 0) << (int)(DRMP3_HDR_GET_MY_SAMPLE_RATE(h->header) == 2);
66964  if (gr_info->n_short_sfb)
66965  {
66966  aa_bands = n_long_bands - 1;
66967  drmp3_L3_reorder(s->grbuf[ch] + n_long_bands*18, s->syn[0], gr_info->sfbtab + gr_info->n_long_sfb);
66968  }
66969  drmp3_L3_antialias(s->grbuf[ch], aa_bands);
66970  drmp3_L3_imdct_gr(s->grbuf[ch], h->mdct_overlap[ch], gr_info->block_type, n_long_bands);
66971  drmp3_L3_change_sign(s->grbuf[ch]);
66972  }
66973 }
66974 static void drmp3d_DCT_II(float *grbuf, int n)
66975 {
66976  static const float g_sec[24] = {
66977  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
66978  };
66979  int i, k = 0;
66980 #if DRMP3_HAVE_SIMD
66981  if (drmp3_have_simd()) for (; k < n; k += 4)
66982  {
66983  drmp3_f4 t[4][8], *x;
66984  float *y = grbuf + k;
66985  for (x = t[0], i = 0; i < 8; i++, x++)
66986  {
66987  drmp3_f4 x0 = DRMP3_VLD(&y[i*18]);
66988  drmp3_f4 x1 = DRMP3_VLD(&y[(15 - i)*18]);
66989  drmp3_f4 x2 = DRMP3_VLD(&y[(16 + i)*18]);
66990  drmp3_f4 x3 = DRMP3_VLD(&y[(31 - i)*18]);
66991  drmp3_f4 t0 = DRMP3_VADD(x0, x3);
66992  drmp3_f4 t1 = DRMP3_VADD(x1, x2);
66993  drmp3_f4 t2 = DRMP3_VMUL_S(DRMP3_VSUB(x1, x2), g_sec[3*i + 0]);
66994  drmp3_f4 t3 = DRMP3_VMUL_S(DRMP3_VSUB(x0, x3), g_sec[3*i + 1]);
66995  x[0] = DRMP3_VADD(t0, t1);
66996  x[8] = DRMP3_VMUL_S(DRMP3_VSUB(t0, t1), g_sec[3*i + 2]);
66997  x[16] = DRMP3_VADD(t3, t2);
66998  x[24] = DRMP3_VMUL_S(DRMP3_VSUB(t3, t2), g_sec[3*i + 2]);
66999  }
67000  for (x = t[0], i = 0; i < 4; i++, x += 8)
67001  {
67002  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;
67003  xt = DRMP3_VSUB(x0, x7); x0 = DRMP3_VADD(x0, x7);
67004  x7 = DRMP3_VSUB(x1, x6); x1 = DRMP3_VADD(x1, x6);
67005  x6 = DRMP3_VSUB(x2, x5); x2 = DRMP3_VADD(x2, x5);
67006  x5 = DRMP3_VSUB(x3, x4); x3 = DRMP3_VADD(x3, x4);
67007  x4 = DRMP3_VSUB(x0, x3); x0 = DRMP3_VADD(x0, x3);
67008  x3 = DRMP3_VSUB(x1, x2); x1 = DRMP3_VADD(x1, x2);
67009  x[0] = DRMP3_VADD(x0, x1);
67010  x[4] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x1), 0.70710677f);
67011  x5 = DRMP3_VADD(x5, x6);
67012  x6 = DRMP3_VMUL_S(DRMP3_VADD(x6, x7), 0.70710677f);
67013  x7 = DRMP3_VADD(x7, xt);
67014  x3 = DRMP3_VMUL_S(DRMP3_VADD(x3, x4), 0.70710677f);
67015  x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f));
67016  x7 = DRMP3_VADD(x7, DRMP3_VMUL_S(x5, 0.382683432f));
67017  x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f));
67018  x0 = DRMP3_VSUB(xt, x6); xt = DRMP3_VADD(xt, x6);
67019  x[1] = DRMP3_VMUL_S(DRMP3_VADD(xt, x7), 0.50979561f);
67020  x[2] = DRMP3_VMUL_S(DRMP3_VADD(x4, x3), 0.54119611f);
67021  x[3] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x5), 0.60134488f);
67022  x[5] = DRMP3_VMUL_S(DRMP3_VADD(x0, x5), 0.89997619f);
67023  x[6] = DRMP3_VMUL_S(DRMP3_VSUB(x4, x3), 1.30656302f);
67024  x[7] = DRMP3_VMUL_S(DRMP3_VSUB(xt, x7), 2.56291556f);
67025  }
67026  if (k > n - 3)
67027  {
67028 #if DRMP3_HAVE_SSE
67029 #define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v)
67030 #else
67031 #define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[i*18], vget_low_f32(v))
67032 #endif
67033  for (i = 0; i < 7; i++, y += 4*18)
67034  {
67035  drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
67036  DRMP3_VSAVE2(0, t[0][i]);
67037  DRMP3_VSAVE2(1, DRMP3_VADD(t[2][i], s));
67038  DRMP3_VSAVE2(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
67039  DRMP3_VSAVE2(3, DRMP3_VADD(t[2][1 + i], s));
67040  }
67041  DRMP3_VSAVE2(0, t[0][7]);
67042  DRMP3_VSAVE2(1, DRMP3_VADD(t[2][7], t[3][7]));
67043  DRMP3_VSAVE2(2, t[1][7]);
67044  DRMP3_VSAVE2(3, t[3][7]);
67045  } else
67046  {
67047 #define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[i*18], v)
67048  for (i = 0; i < 7; i++, y += 4*18)
67049  {
67050  drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
67051  DRMP3_VSAVE4(0, t[0][i]);
67052  DRMP3_VSAVE4(1, DRMP3_VADD(t[2][i], s));
67053  DRMP3_VSAVE4(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
67054  DRMP3_VSAVE4(3, DRMP3_VADD(t[2][1 + i], s));
67055  }
67056  DRMP3_VSAVE4(0, t[0][7]);
67057  DRMP3_VSAVE4(1, DRMP3_VADD(t[2][7], t[3][7]));
67058  DRMP3_VSAVE4(2, t[1][7]);
67059  DRMP3_VSAVE4(3, t[3][7]);
67060  }
67061  } else
67062 #endif
67063 #ifdef DR_MP3_ONLY_SIMD
67064  {}
67065 #else
67066  for (; k < n; k++)
67067  {
67068  float t[4][8], *x, *y = grbuf + k;
67069  for (x = t[0], i = 0; i < 8; i++, x++)
67070  {
67071  float x0 = y[i*18];
67072  float x1 = y[(15 - i)*18];
67073  float x2 = y[(16 + i)*18];
67074  float x3 = y[(31 - i)*18];
67075  float t0 = x0 + x3;
67076  float t1 = x1 + x2;
67077  float t2 = (x1 - x2)*g_sec[3*i + 0];
67078  float t3 = (x0 - x3)*g_sec[3*i + 1];
67079  x[0] = t0 + t1;
67080  x[8] = (t0 - t1)*g_sec[3*i + 2];
67081  x[16] = t3 + t2;
67082  x[24] = (t3 - t2)*g_sec[3*i + 2];
67083  }
67084  for (x = t[0], i = 0; i < 4; i++, x += 8)
67085  {
67086  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;
67087  xt = x0 - x7; x0 += x7;
67088  x7 = x1 - x6; x1 += x6;
67089  x6 = x2 - x5; x2 += x5;
67090  x5 = x3 - x4; x3 += x4;
67091  x4 = x0 - x3; x0 += x3;
67092  x3 = x1 - x2; x1 += x2;
67093  x[0] = x0 + x1;
67094  x[4] = (x0 - x1)*0.70710677f;
67095  x5 = x5 + x6;
67096  x6 = (x6 + x7)*0.70710677f;
67097  x7 = x7 + xt;
67098  x3 = (x3 + x4)*0.70710677f;
67099  x5 -= x7*0.198912367f;
67100  x7 += x5*0.382683432f;
67101  x5 -= x7*0.198912367f;
67102  x0 = xt - x6; xt += x6;
67103  x[1] = (xt + x7)*0.50979561f;
67104  x[2] = (x4 + x3)*0.54119611f;
67105  x[3] = (x0 - x5)*0.60134488f;
67106  x[5] = (x0 + x5)*0.89997619f;
67107  x[6] = (x4 - x3)*1.30656302f;
67108  x[7] = (xt - x7)*2.56291556f;
67109  }
67110  for (i = 0; i < 7; i++, y += 4*18)
67111  {
67112  y[0*18] = t[0][i];
67113  y[1*18] = t[2][i] + t[3][i] + t[3][i + 1];
67114  y[2*18] = t[1][i] + t[1][i + 1];
67115  y[3*18] = t[2][i + 1] + t[3][i] + t[3][i + 1];
67116  }
67117  y[0*18] = t[0][7];
67118  y[1*18] = t[2][7] + t[3][7];
67119  y[2*18] = t[1][7];
67120  y[3*18] = t[3][7];
67121  }
67122 #endif
67123 }
67124 #ifndef DR_MP3_FLOAT_OUTPUT
67126 static drmp3_int16 drmp3d_scale_pcm(float sample)
67127 {
67128  drmp3_int16 s;
67129 #if DRMP3_HAVE_ARMV6
67130  drmp3_int32 s32 = (drmp3_int32)(sample + .5f);
67131  s32 -= (s32 < 0);
67132  s = (drmp3_int16)drmp3_clip_int16_arm(s32);
67133 #else
67134  if (sample >= 32766.5) return (drmp3_int16) 32767;
67135  if (sample <= -32767.5) return (drmp3_int16)-32768;
67136  s = (drmp3_int16)(sample + .5f);
67137  s -= (s < 0);
67138 #endif
67139  return s;
67140 }
67141 #else
67142 typedef float drmp3d_sample_t;
67143 static float drmp3d_scale_pcm(float sample)
67144 {
67145  return sample*(1.f/32768.f);
67146 }
67147 #endif
67148 static void drmp3d_synth_pair(drmp3d_sample_t *pcm, int nch, const float *z)
67149 {
67150  float a;
67151  a = (z[14*64] - z[ 0]) * 29;
67152  a += (z[ 1*64] + z[13*64]) * 213;
67153  a += (z[12*64] - z[ 2*64]) * 459;
67154  a += (z[ 3*64] + z[11*64]) * 2037;
67155  a += (z[10*64] - z[ 4*64]) * 5153;
67156  a += (z[ 5*64] + z[ 9*64]) * 6574;
67157  a += (z[ 8*64] - z[ 6*64]) * 37489;
67158  a += z[ 7*64] * 75038;
67159  pcm[0] = drmp3d_scale_pcm(a);
67160  z += 2;
67161  a = z[14*64] * 104;
67162  a += z[12*64] * 1567;
67163  a += z[10*64] * 9727;
67164  a += z[ 8*64] * 64019;
67165  a += z[ 6*64] * -9975;
67166  a += z[ 4*64] * -45;
67167  a += z[ 2*64] * 146;
67168  a += z[ 0*64] * -5;
67169  pcm[16*nch] = drmp3d_scale_pcm(a);
67170 }
67171 static void drmp3d_synth(float *xl, drmp3d_sample_t *dstl, int nch, float *lins)
67172 {
67173  int i;
67174  float *xr = xl + 576*(nch - 1);
67175  drmp3d_sample_t *dstr = dstl + (nch - 1);
67176  static const float g_win[] = {
67177  -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
67178  -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
67179  -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
67180  -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
67181  -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
67182  -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
67183  -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
67184  -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
67185  -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
67186  -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
67187  -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
67188  -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
67189  -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
67190  -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
67191  -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
67192  };
67193  float *zlin = lins + 15*64;
67194  const float *w = g_win;
67195  zlin[4*15] = xl[18*16];
67196  zlin[4*15 + 1] = xr[18*16];
67197  zlin[4*15 + 2] = xl[0];
67198  zlin[4*15 + 3] = xr[0];
67199  zlin[4*31] = xl[1 + 18*16];
67200  zlin[4*31 + 1] = xr[1 + 18*16];
67201  zlin[4*31 + 2] = xl[1];
67202  zlin[4*31 + 3] = xr[1];
67203  drmp3d_synth_pair(dstr, nch, lins + 4*15 + 1);
67204  drmp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1);
67205  drmp3d_synth_pair(dstl, nch, lins + 4*15);
67206  drmp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64);
67207 #if DRMP3_HAVE_SIMD
67208  if (drmp3_have_simd()) for (i = 14; i >= 0; i--)
67209  {
67210 #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)]);
67211 #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)); }
67212 #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))); }
67213 #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))); }
67214  drmp3_f4 a, b;
67215  zlin[4*i] = xl[18*(31 - i)];
67216  zlin[4*i + 1] = xr[18*(31 - i)];
67217  zlin[4*i + 2] = xl[1 + 18*(31 - i)];
67218  zlin[4*i + 3] = xr[1 + 18*(31 - i)];
67219  zlin[4*i + 64] = xl[1 + 18*(1 + i)];
67220  zlin[4*i + 64 + 1] = xr[1 + 18*(1 + i)];
67221  zlin[4*i - 64 + 2] = xl[18*(1 + i)];
67222  zlin[4*i - 64 + 3] = xr[18*(1 + i)];
67223  DRMP3_V0(0) DRMP3_V2(1) DRMP3_V1(2) DRMP3_V2(3) DRMP3_V1(4) DRMP3_V2(5) DRMP3_V1(6) DRMP3_V2(7)
67224  {
67225 #ifndef DR_MP3_FLOAT_OUTPUT
67226 #if DRMP3_HAVE_SSE
67227  static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f };
67228  static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f };
67229  __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)),
67230  _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min)));
67231  dstr[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
67232  dstr[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
67233  dstl[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
67234  dstl[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
67235  dstr[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
67236  dstr[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
67237  dstl[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
67238  dstl[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
67239 #else
67240  int16x4_t pcma, pcmb;
67241  a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
67242  b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
67243  pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
67244  pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
67245  vst1_lane_s16(dstr + (15 - i)*nch, pcma, 1);
67246  vst1_lane_s16(dstr + (17 + i)*nch, pcmb, 1);
67247  vst1_lane_s16(dstl + (15 - i)*nch, pcma, 0);
67248  vst1_lane_s16(dstl + (17 + i)*nch, pcmb, 0);
67249  vst1_lane_s16(dstr + (47 - i)*nch, pcma, 3);
67250  vst1_lane_s16(dstr + (49 + i)*nch, pcmb, 3);
67251  vst1_lane_s16(dstl + (47 - i)*nch, pcma, 2);
67252  vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2);
67253 #endif
67254 #else
67255  static const drmp3_f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f };
67256  a = DRMP3_VMUL(a, g_scale);
67257  b = DRMP3_VMUL(b, g_scale);
67258 #if DRMP3_HAVE_SSE
67259  _mm_store_ss(dstr + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)));
67260  _mm_store_ss(dstr + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(1, 1, 1, 1)));
67261  _mm_store_ss(dstl + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)));
67262  _mm_store_ss(dstl + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(0, 0, 0, 0)));
67263  _mm_store_ss(dstr + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)));
67264  _mm_store_ss(dstr + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 3, 3, 3)));
67265  _mm_store_ss(dstl + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
67266  _mm_store_ss(dstl + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(2, 2, 2, 2)));
67267 #else
67268  vst1q_lane_f32(dstr + (15 - i)*nch, a, 1);
67269  vst1q_lane_f32(dstr + (17 + i)*nch, b, 1);
67270  vst1q_lane_f32(dstl + (15 - i)*nch, a, 0);
67271  vst1q_lane_f32(dstl + (17 + i)*nch, b, 0);
67272  vst1q_lane_f32(dstr + (47 - i)*nch, a, 3);
67273  vst1q_lane_f32(dstr + (49 + i)*nch, b, 3);
67274  vst1q_lane_f32(dstl + (47 - i)*nch, a, 2);
67275  vst1q_lane_f32(dstl + (49 + i)*nch, b, 2);
67276 #endif
67277 #endif
67278  }
67279  } else
67280 #endif
67281 #ifdef DR_MP3_ONLY_SIMD
67282  {}
67283 #else
67284  for (i = 14; i >= 0; i--)
67285  {
67286 #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];
67287 #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; }
67288 #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; }
67289 #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; }
67290  float a[4], b[4];
67291  zlin[4*i] = xl[18*(31 - i)];
67292  zlin[4*i + 1] = xr[18*(31 - i)];
67293  zlin[4*i + 2] = xl[1 + 18*(31 - i)];
67294  zlin[4*i + 3] = xr[1 + 18*(31 - i)];
67295  zlin[4*(i + 16)] = xl[1 + 18*(1 + i)];
67296  zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)];
67297  zlin[4*(i - 16) + 2] = xl[18*(1 + i)];
67298  zlin[4*(i - 16) + 3] = xr[18*(1 + i)];
67300  dstr[(15 - i)*nch] = drmp3d_scale_pcm(a[1]);
67301  dstr[(17 + i)*nch] = drmp3d_scale_pcm(b[1]);
67302  dstl[(15 - i)*nch] = drmp3d_scale_pcm(a[0]);
67303  dstl[(17 + i)*nch] = drmp3d_scale_pcm(b[0]);
67304  dstr[(47 - i)*nch] = drmp3d_scale_pcm(a[3]);
67305  dstr[(49 + i)*nch] = drmp3d_scale_pcm(b[3]);
67306  dstl[(47 - i)*nch] = drmp3d_scale_pcm(a[2]);
67307  dstl[(49 + i)*nch] = drmp3d_scale_pcm(b[2]);
67308  }
67309 #endif
67310 }
67311 static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, drmp3d_sample_t *pcm, float *lins)
67312 {
67313  int i;
67314  for (i = 0; i < nch; i++)
67315  {
67316  drmp3d_DCT_II(grbuf + 576*i, nbands);
67317  }
67318  memcpy(lins, qmf_state, sizeof(float)*15*64);
67319  for (i = 0; i < nbands; i += 2)
67320  {
67321  drmp3d_synth(grbuf + i, pcm + 32*nch*i, nch, lins + i*64);
67322  }
67323 #ifndef DR_MP3_NONSTANDARD_BUT_LOGICAL
67324  if (nch == 1)
67325  {
67326  for (i = 0; i < 15*64; i += 2)
67327  {
67328  qmf_state[i] = lins[nbands*64 + i];
67329  }
67330  } else
67331 #endif
67332  {
67333  memcpy(qmf_state, lins + nbands*64, sizeof(float)*15*64);
67334  }
67335 }
67336 static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes)
67337 {
67338  int i, nmatch;
67339  for (i = 0, nmatch = 0; nmatch < DRMP3_MAX_FRAME_SYNC_MATCHES; nmatch++)
67340  {
67341  i += drmp3_hdr_frame_bytes(hdr + i, frame_bytes) + drmp3_hdr_padding(hdr + i);
67342  if (i + DRMP3_HDR_SIZE > mp3_bytes)
67343  return nmatch > 0;
67344  if (!drmp3_hdr_compare(hdr, hdr + i))
67345  return 0;
67346  }
67347  return 1;
67348 }
67349 static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes)
67350 {
67351  int i, k;
67352  for (i = 0; i < mp3_bytes - DRMP3_HDR_SIZE; i++, mp3++)
67353  {
67354  if (drmp3_hdr_valid(mp3))
67355  {
67356  int frame_bytes = drmp3_hdr_frame_bytes(mp3, *free_format_bytes);
67357  int frame_and_padding = frame_bytes + drmp3_hdr_padding(mp3);
67358  for (k = DRMP3_HDR_SIZE; !frame_bytes && k < DRMP3_MAX_FREE_FORMAT_FRAME_SIZE && i + 2*k < mp3_bytes - DRMP3_HDR_SIZE; k++)
67359  {
67360  if (drmp3_hdr_compare(mp3, mp3 + k))
67361  {
67362  int fb = k - drmp3_hdr_padding(mp3);
67363  int nextfb = fb + drmp3_hdr_padding(mp3 + k);
67364  if (i + k + nextfb + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + k + nextfb))
67365  continue;
67366  frame_and_padding = k;
67367  frame_bytes = fb;
67368  *free_format_bytes = fb;
67369  }
67370  }
67371  if ((frame_bytes && i + frame_and_padding <= mp3_bytes &&
67372  drmp3d_match_frame(mp3, mp3_bytes - i, frame_bytes)) ||
67373  (!i && frame_and_padding == mp3_bytes))
67374  {
67375  *ptr_frame_bytes = frame_and_padding;
67376  return i;
67377  }
67378  *free_format_bytes = 0;
67379  }
67380  }
67381  *ptr_frame_bytes = 0;
67382  return mp3_bytes;
67383 }
67384 DRMP3_API void drmp3dec_init(drmp3dec *dec)
67385 {
67386  dec->header[0] = 0;
67387 }
67388 DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info)
67389 {
67390  int i = 0, igr, frame_size = 0, success = 1;
67391  const drmp3_uint8 *hdr;
67392  drmp3_bs bs_frame[1];
67393  drmp3dec_scratch scratch;
67394  if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
67395  {
67396  frame_size = drmp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + drmp3_hdr_padding(mp3);
67397  if (frame_size != mp3_bytes && (frame_size + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + frame_size)))
67398  {
67399  frame_size = 0;
67400  }
67401  }
67402  if (!frame_size)
67403  {
67404  memset(dec, 0, sizeof(drmp3dec));
67405  i = drmp3d_find_frame(mp3, mp3_bytes, &dec->free_format_bytes, &frame_size);
67406  if (!frame_size || i + frame_size > mp3_bytes)
67407  {
67408  info->frame_bytes = i;
67409  return 0;
67410  }
67411  }
67412  hdr = mp3 + i;
67413  memcpy(dec->header, hdr, DRMP3_HDR_SIZE);
67414  info->frame_bytes = i + frame_size;
67415  info->channels = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
67416  info->hz = drmp3_hdr_sample_rate_hz(hdr);
67417  info->layer = 4 - DRMP3_HDR_GET_LAYER(hdr);
67418  info->bitrate_kbps = drmp3_hdr_bitrate_kbps(hdr);
67419  drmp3_bs_init(bs_frame, hdr + DRMP3_HDR_SIZE, frame_size - DRMP3_HDR_SIZE);
67420  if (DRMP3_HDR_IS_CRC(hdr))
67421  {
67422  drmp3_bs_get_bits(bs_frame, 16);
67423  }
67424  if (info->layer == 3)
67425  {
67426  int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
67427  if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
67428  {
67429  drmp3dec_init(dec);
67430  return 0;
67431  }
67432  success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
67433  if (success && pcm != NULL)
67434  {
67435  for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
67436  {
67437  memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
67438  drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
67439  drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
67440  }
67441  }
67442  drmp3_L3_save_reservoir(dec, &scratch);
67443  } else
67444  {
67445 #ifdef DR_MP3_ONLY_MP3
67446  return 0;
67447 #else
67448  drmp3_L12_scale_info sci[1];
67449  if (pcm == NULL) {
67450  return drmp3_hdr_frame_samples(hdr);
67451  }
67452  drmp3_L12_read_scale_info(hdr, bs_frame, sci);
67453  memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
67454  for (i = 0, igr = 0; igr < 3; igr++)
67455  {
67456  if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
67457  {
67458  i = 0;
67459  drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
67460  drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
67461  memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
67462  pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
67463  }
67464  if (bs_frame->pos > bs_frame->limit)
67465  {
67466  drmp3dec_init(dec);
67467  return 0;
67468  }
67469  }
67470 #endif
67471  }
67472  return success*drmp3_hdr_frame_samples(dec->header);
67473 }
67474 DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples)
67475 {
67476  size_t i = 0;
67477 #if DRMP3_HAVE_SIMD
67478  size_t aligned_count = num_samples & ~7;
67479  for(; i < aligned_count; i+=8)
67480  {
67481  drmp3_f4 scale = DRMP3_VSET(32768.0f);
67482  drmp3_f4 a = DRMP3_VMUL(DRMP3_VLD(&in[i ]), scale);
67483  drmp3_f4 b = DRMP3_VMUL(DRMP3_VLD(&in[i+4]), scale);
67484 #if DRMP3_HAVE_SSE
67485  drmp3_f4 s16max = DRMP3_VSET( 32767.0f);
67486  drmp3_f4 s16min = DRMP3_VSET(-32768.0f);
67487  __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, s16max), s16min)),
67488  _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, s16max), s16min)));
67489  out[i ] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
67490  out[i+1] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
67491  out[i+2] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
67492  out[i+3] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
67493  out[i+4] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
67494  out[i+5] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
67495  out[i+6] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
67496  out[i+7] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
67497 #else
67498  int16x4_t pcma, pcmb;
67499  a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
67500  b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
67501  pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
67502  pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
67503  vst1_lane_s16(out+i , pcma, 0);
67504  vst1_lane_s16(out+i+1, pcma, 1);
67505  vst1_lane_s16(out+i+2, pcma, 2);
67506  vst1_lane_s16(out+i+3, pcma, 3);
67507  vst1_lane_s16(out+i+4, pcmb, 0);
67508  vst1_lane_s16(out+i+5, pcmb, 1);
67509  vst1_lane_s16(out+i+6, pcmb, 2);
67510  vst1_lane_s16(out+i+7, pcmb, 3);
67511 #endif
67512  }
67513 #endif
67514  for(; i < num_samples; i++)
67515  {
67516  float sample = in[i] * 32768.0f;
67517  if (sample >= 32766.5)
67518  out[i] = (drmp3_int16) 32767;
67519  else if (sample <= -32767.5)
67520  out[i] = (drmp3_int16)-32768;
67521  else
67522  {
67523  short s = (drmp3_int16)(sample + .5f);
67524  s -= (s < 0);
67525  out[i] = s;
67526  }
67527  }
67528 }
67529 #include <math.h>
67530 #if defined(SIZE_MAX)
67531  #define DRMP3_SIZE_MAX SIZE_MAX
67532 #else
67533  #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
67534  #define DRMP3_SIZE_MAX ((drmp3_uint64)0xFFFFFFFFFFFFFFFF)
67535  #else
67536  #define DRMP3_SIZE_MAX 0xFFFFFFFF
67537  #endif
67538 #endif
67539 #ifndef DRMP3_SEEK_LEADING_MP3_FRAMES
67540 #define DRMP3_SEEK_LEADING_MP3_FRAMES 2
67541 #endif
67542 #define DRMP3_MIN_DATA_CHUNK_SIZE 16384
67543 #ifndef DRMP3_DATA_CHUNK_SIZE
67544 #define DRMP3_DATA_CHUNK_SIZE DRMP3_MIN_DATA_CHUNK_SIZE*4
67545 #endif
67546 #ifndef DRMP3_ASSERT
67547 #include <assert.h>
67548 #define DRMP3_ASSERT(expression) assert(expression)
67549 #endif
67550 #ifndef DRMP3_COPY_MEMORY
67551 #define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
67552 #endif
67553 #ifndef DRMP3_ZERO_MEMORY
67554 #define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
67555 #endif
67556 #define DRMP3_ZERO_OBJECT(p) DRMP3_ZERO_MEMORY((p), sizeof(*(p)))
67557 #ifndef DRMP3_MALLOC
67558 #define DRMP3_MALLOC(sz) malloc((sz))
67559 #endif
67560 #ifndef DRMP3_REALLOC
67561 #define DRMP3_REALLOC(p, sz) realloc((p), (sz))
67562 #endif
67563 #ifndef DRMP3_FREE
67564 #define DRMP3_FREE(p) free((p))
67565 #endif
67566 #define DRMP3_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
67567 #define DRMP3_CLAMP(x, lo, hi) (DRMP3_MAX(lo, DRMP3_MIN(x, hi)))
67568 #ifndef DRMP3_PI_D
67569 #define DRMP3_PI_D 3.14159265358979323846264
67570 #endif
67571 #define DRMP3_DEFAULT_RESAMPLER_LPF_ORDER 2
67572 static DRMP3_INLINE float drmp3_mix_f32(float x, float y, float a)
67573 {
67574  return x*(1-a) + y*a;
67575 }
67576 static DRMP3_INLINE float drmp3_mix_f32_fast(float x, float y, float a)
67577 {
67578  float r0 = (y - x);
67579  float r1 = r0*a;
67580  return x + r1;
67581 }
67583 {
67584  for (;;) {
67585  if (b == 0) {
67586  break;
67587  } else {
67588  drmp3_uint32 t = a;
67589  a = b;
67590  b = t % a;
67591  }
67592  }
67593  return a;
67594 }
67595 static DRMP3_INLINE double drmp3_sin(double x)
67596 {
67597  return sin(x);
67598 }
67599 static DRMP3_INLINE double drmp3_exp(double x)
67600 {
67601  return exp(x);
67602 }
67603 static DRMP3_INLINE double drmp3_cos(double x)
67604 {
67605  return drmp3_sin((DRMP3_PI_D*0.5) - x);
67606 }
67607 static void* drmp3__malloc_default(size_t sz, void* pUserData)
67608 {
67609  (void)pUserData;
67610  return DRMP3_MALLOC(sz);
67611 }
67612 static void* drmp3__realloc_default(void* p, size_t sz, void* pUserData)
67613 {
67614  (void)pUserData;
67615  return DRMP3_REALLOC(p, sz);
67616 }
67617 static void drmp3__free_default(void* p, void* pUserData)
67618 {
67619  (void)pUserData;
67620  DRMP3_FREE(p);
67621 }
67622 static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
67623 {
67624  if (pAllocationCallbacks == NULL) {
67625  return NULL;
67626  }
67627  if (pAllocationCallbacks->onMalloc != NULL) {
67628  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
67629  }
67630  if (pAllocationCallbacks->onRealloc != NULL) {
67631  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
67632  }
67633  return NULL;
67634 }
67635 static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks* pAllocationCallbacks)
67636 {
67637  if (pAllocationCallbacks == NULL) {
67638  return NULL;
67639  }
67640  if (pAllocationCallbacks->onRealloc != NULL) {
67641  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
67642  }
67643  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
67644  void* p2;
67645  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
67646  if (p2 == NULL) {
67647  return NULL;
67648  }
67649  if (p != NULL) {
67650  DRMP3_COPY_MEMORY(p2, p, szOld);
67651  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
67652  }
67653  return p2;
67654  }
67655  return NULL;
67656 }
67657 static void drmp3__free_from_callbacks(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
67658 {
67659  if (p == NULL || pAllocationCallbacks == NULL) {
67660  return;
67661  }
67662  if (pAllocationCallbacks->onFree != NULL) {
67663  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
67664  }
67665 }
67667 {
67668  if (pAllocationCallbacks != NULL) {
67669  return *pAllocationCallbacks;
67670  } else {
67671  drmp3_allocation_callbacks allocationCallbacks;
67672  allocationCallbacks.pUserData = NULL;
67673  allocationCallbacks.onMalloc = drmp3__malloc_default;
67674  allocationCallbacks.onRealloc = drmp3__realloc_default;
67675  allocationCallbacks.onFree = drmp3__free_default;
67676  return allocationCallbacks;
67677  }
67678 }
67679 static size_t drmp3__on_read(drmp3* pMP3, void* pBufferOut, size_t bytesToRead)
67680 {
67681  size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
67682  pMP3->streamCursor += bytesRead;
67683  return bytesRead;
67684 }
67685 static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin)
67686 {
67687  DRMP3_ASSERT(offset >= 0);
67688  if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
67689  return DRMP3_FALSE;
67690  }
67691  if (origin == drmp3_seek_origin_start) {
67692  pMP3->streamCursor = (drmp3_uint64)offset;
67693  } else {
67694  pMP3->streamCursor += offset;
67695  }
67696  return DRMP3_TRUE;
67697 }
67699 {
67700  if (offset <= 0x7FFFFFFF) {
67701  return drmp3__on_seek(pMP3, (int)offset, origin);
67702  }
67703  if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) {
67704  return DRMP3_FALSE;
67705  }
67706  offset -= 0x7FFFFFFF;
67707  while (offset > 0) {
67708  if (offset <= 0x7FFFFFFF) {
67709  if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) {
67710  return DRMP3_FALSE;
67711  }
67712  offset = 0;
67713  } else {
67714  if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) {
67715  return DRMP3_FALSE;
67716  }
67717  offset -= 0x7FFFFFFF;
67718  }
67719  }
67720  return DRMP3_TRUE;
67721 }
67723 {
67724  drmp3_uint32 pcmFramesRead = 0;
67725  DRMP3_ASSERT(pMP3 != NULL);
67726  DRMP3_ASSERT(pMP3->onRead != NULL);
67727  if (pMP3->atEnd) {
67728  return 0;
67729  }
67730  for (;;) {
67731  drmp3dec_frame_info info;
67732  if (pMP3->dataSize < DRMP3_MIN_DATA_CHUNK_SIZE) {
67733  size_t bytesRead;
67734  if (pMP3->pData != NULL) {
67735  memmove(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
67736  }
67737  pMP3->dataConsumed = 0;
67738  if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) {
67739  drmp3_uint8* pNewData;
67740  size_t newDataCap;
67741  newDataCap = DRMP3_DATA_CHUNK_SIZE;
67742  pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
67743  if (pNewData == NULL) {
67744  return 0;
67745  }
67746  pMP3->pData = pNewData;
67747  pMP3->dataCapacity = newDataCap;
67748  }
67749  bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
67750  if (bytesRead == 0) {
67751  if (pMP3->dataSize == 0) {
67752  pMP3->atEnd = DRMP3_TRUE;
67753  return 0;
67754  }
67755  }
67756  pMP3->dataSize += bytesRead;
67757  }
67758  if (pMP3->dataSize > INT_MAX) {
67759  pMP3->atEnd = DRMP3_TRUE;
67760  return 0;
67761  }
67762  DRMP3_ASSERT(pMP3->pData != NULL);
67763  DRMP3_ASSERT(pMP3->dataCapacity > 0);
67764  pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info);
67765  if (info.frame_bytes > 0) {
67766  pMP3->dataConsumed += (size_t)info.frame_bytes;
67767  pMP3->dataSize -= (size_t)info.frame_bytes;
67768  }
67769  if (pcmFramesRead > 0) {
67770  pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
67771  pMP3->pcmFramesConsumedInMP3Frame = 0;
67772  pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
67773  pMP3->mp3FrameChannels = info.channels;
67774  pMP3->mp3FrameSampleRate = info.hz;
67775  break;
67776  } else if (info.frame_bytes == 0) {
67777  size_t bytesRead;
67778  memmove(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
67779  pMP3->dataConsumed = 0;
67780  if (pMP3->dataCapacity == pMP3->dataSize) {
67781  drmp3_uint8* pNewData;
67782  size_t newDataCap;
67783  newDataCap = pMP3->dataCapacity + DRMP3_DATA_CHUNK_SIZE;
67784  pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
67785  if (pNewData == NULL) {
67786  return 0;
67787  }
67788  pMP3->pData = pNewData;
67789  pMP3->dataCapacity = newDataCap;
67790  }
67791  bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
67792  if (bytesRead == 0) {
67793  pMP3->atEnd = DRMP3_TRUE;
67794  return 0;
67795  }
67796  pMP3->dataSize += bytesRead;
67797  }
67798  };
67799  return pcmFramesRead;
67800 }
67802 {
67803  drmp3_uint32 pcmFramesRead = 0;
67804  drmp3dec_frame_info info;
67805  DRMP3_ASSERT(pMP3 != NULL);
67806  DRMP3_ASSERT(pMP3->memory.pData != NULL);
67807  if (pMP3->atEnd) {
67808  return 0;
67809  }
67810  pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->memory.pData + pMP3->memory.currentReadPos, (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos), pPCMFrames, &info);
67811  if (pcmFramesRead > 0) {
67812  pMP3->pcmFramesConsumedInMP3Frame = 0;
67813  pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
67814  pMP3->mp3FrameChannels = info.channels;
67815  pMP3->mp3FrameSampleRate = info.hz;
67816  }
67817  pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
67818  return pcmFramesRead;
67819 }
67821 {
67822  if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
67823  return drmp3_decode_next_frame_ex__memory(pMP3, pPCMFrames);
67824  } else {
67825  return drmp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames);
67826  }
67827 }
67829 {
67830  DRMP3_ASSERT(pMP3 != NULL);
67832 }
67833 #if 0
67834 static drmp3_uint32 drmp3_seek_next_frame(drmp3* pMP3)
67835 {
67836  drmp3_uint32 pcmFrameCount;
67837  DRMP3_ASSERT(pMP3 != NULL);
67838  pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, NULL);
67839  if (pcmFrameCount == 0) {
67840  return 0;
67841  }
67842  pMP3->currentPCMFrame += pcmFrameCount;
67843  pMP3->pcmFramesConsumedInMP3Frame = pcmFrameCount;
67844  pMP3->pcmFramesRemainingInMP3Frame = 0;
67845  return pcmFrameCount;
67846 }
67847 #endif
67848 static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
67849 {
67850  DRMP3_ASSERT(pMP3 != NULL);
67851  DRMP3_ASSERT(onRead != NULL);
67852  drmp3dec_init(&pMP3->decoder);
67853  pMP3->onRead = onRead;
67854  pMP3->onSeek = onSeek;
67855  pMP3->pUserData = pUserData;
67858  return DRMP3_FALSE;
67859  }
67860  if (!drmp3_decode_next_frame(pMP3)) {
67862  return DRMP3_FALSE;
67863  }
67864  pMP3->channels = pMP3->mp3FrameChannels;
67865  pMP3->sampleRate = pMP3->mp3FrameSampleRate;
67866  return DRMP3_TRUE;
67867 }
67868 DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
67869 {
67870  if (pMP3 == NULL || onRead == NULL) {
67871  return DRMP3_FALSE;
67872  }
67873  DRMP3_ZERO_OBJECT(pMP3);
67874  return drmp3_init_internal(pMP3, onRead, onSeek, pUserData, pAllocationCallbacks);
67875 }
67876 static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
67877 {
67878  drmp3* pMP3 = (drmp3*)pUserData;
67879  size_t bytesRemaining;
67880  DRMP3_ASSERT(pMP3 != NULL);
67882  bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos;
67883  if (bytesToRead > bytesRemaining) {
67884  bytesToRead = bytesRemaining;
67885  }
67886  if (bytesToRead > 0) {
67887  DRMP3_COPY_MEMORY(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead);
67888  pMP3->memory.currentReadPos += bytesToRead;
67889  }
67890  return bytesToRead;
67891 }
67892 static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin)
67893 {
67894  drmp3* pMP3 = (drmp3*)pUserData;
67895  DRMP3_ASSERT(pMP3 != NULL);
67896  if (origin == drmp3_seek_origin_current) {
67897  if (byteOffset > 0) {
67898  if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
67899  byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos);
67900  }
67901  } else {
67902  if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
67903  byteOffset = -(int)pMP3->memory.currentReadPos;
67904  }
67905  }
67906  pMP3->memory.currentReadPos += byteOffset;
67907  } else {
67908  if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) {
67909  pMP3->memory.currentReadPos = byteOffset;
67910  } else {
67911  pMP3->memory.currentReadPos = pMP3->memory.dataSize;
67912  }
67913  }
67914  return DRMP3_TRUE;
67915 }
67916 DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks)
67917 {
67918  if (pMP3 == NULL) {
67919  return DRMP3_FALSE;
67920  }
67921  DRMP3_ZERO_OBJECT(pMP3);
67922  if (pData == NULL || dataSize == 0) {
67923  return DRMP3_FALSE;
67924  }
67925  pMP3->memory.pData = (const drmp3_uint8*)pData;
67926  pMP3->memory.dataSize = dataSize;
67927  pMP3->memory.currentReadPos = 0;
67928  return drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, pMP3, pAllocationCallbacks);
67929 }
67930 #ifndef DR_MP3_NO_STDIO
67931 #include <stdio.h>
67932 #include <wchar.h>
67933 #include <errno.h>
67935 {
67936  switch (e)
67937  {
67938  case 0: return DRMP3_SUCCESS;
67939  #ifdef EPERM
67940  case EPERM: return DRMP3_INVALID_OPERATION;
67941  #endif
67942  #ifdef ENOENT
67943  case ENOENT: return DRMP3_DOES_NOT_EXIST;
67944  #endif
67945  #ifdef ESRCH
67946  case ESRCH: return DRMP3_DOES_NOT_EXIST;
67947  #endif
67948  #ifdef EINTR
67949  case EINTR: return DRMP3_INTERRUPT;
67950  #endif
67951  #ifdef EIO
67952  case EIO: return DRMP3_IO_ERROR;
67953  #endif
67954  #ifdef ENXIO
67955  case ENXIO: return DRMP3_DOES_NOT_EXIST;
67956  #endif
67957  #ifdef E2BIG
67958  case E2BIG: return DRMP3_INVALID_ARGS;
67959  #endif
67960  #ifdef ENOEXEC
67961  case ENOEXEC: return DRMP3_INVALID_FILE;
67962  #endif
67963  #ifdef EBADF
67964  case EBADF: return DRMP3_INVALID_FILE;
67965  #endif
67966  #ifdef ECHILD
67967  case ECHILD: return DRMP3_ERROR;
67968  #endif
67969  #ifdef EAGAIN
67970  case EAGAIN: return DRMP3_UNAVAILABLE;
67971  #endif
67972  #ifdef ENOMEM
67973  case ENOMEM: return DRMP3_OUT_OF_MEMORY;
67974  #endif
67975  #ifdef EACCES
67976  case EACCES: return DRMP3_ACCESS_DENIED;
67977  #endif
67978  #ifdef EFAULT
67979  case EFAULT: return DRMP3_BAD_ADDRESS;
67980  #endif
67981  #ifdef ENOTBLK
67982  case ENOTBLK: return DRMP3_ERROR;
67983  #endif
67984  #ifdef EBUSY
67985  case EBUSY: return DRMP3_BUSY;
67986  #endif
67987  #ifdef EEXIST
67988  case EEXIST: return DRMP3_ALREADY_EXISTS;
67989  #endif
67990  #ifdef EXDEV
67991  case EXDEV: return DRMP3_ERROR;
67992  #endif
67993  #ifdef ENODEV
67994  case ENODEV: return DRMP3_DOES_NOT_EXIST;
67995  #endif
67996  #ifdef ENOTDIR
67997  case ENOTDIR: return DRMP3_NOT_DIRECTORY;
67998  #endif
67999  #ifdef EISDIR
68000  case EISDIR: return DRMP3_IS_DIRECTORY;
68001  #endif
68002  #ifdef EINVAL
68003  case EINVAL: return DRMP3_INVALID_ARGS;
68004  #endif
68005  #ifdef ENFILE
68006  case ENFILE: return DRMP3_TOO_MANY_OPEN_FILES;
68007  #endif
68008  #ifdef EMFILE
68009  case EMFILE: return DRMP3_TOO_MANY_OPEN_FILES;
68010  #endif
68011  #ifdef ENOTTY
68012  case ENOTTY: return DRMP3_INVALID_OPERATION;
68013  #endif
68014  #ifdef ETXTBSY
68015  case ETXTBSY: return DRMP3_BUSY;
68016  #endif
68017  #ifdef EFBIG
68018  case EFBIG: return DRMP3_TOO_BIG;
68019  #endif
68020  #ifdef ENOSPC
68021  case ENOSPC: return DRMP3_NO_SPACE;
68022  #endif
68023  #ifdef ESPIPE
68024  case ESPIPE: return DRMP3_BAD_SEEK;
68025  #endif
68026  #ifdef EROFS
68027  case EROFS: return DRMP3_ACCESS_DENIED;
68028  #endif
68029  #ifdef EMLINK
68030  case EMLINK: return DRMP3_TOO_MANY_LINKS;
68031  #endif
68032  #ifdef EPIPE
68033  case EPIPE: return DRMP3_BAD_PIPE;
68034  #endif
68035  #ifdef EDOM
68036  case EDOM: return DRMP3_OUT_OF_RANGE;
68037  #endif
68038  #ifdef ERANGE
68039  case ERANGE: return DRMP3_OUT_OF_RANGE;
68040  #endif
68041  #ifdef EDEADLK
68042  case EDEADLK: return DRMP3_DEADLOCK;
68043  #endif
68044  #ifdef ENAMETOOLONG
68045  case ENAMETOOLONG: return DRMP3_PATH_TOO_LONG;
68046  #endif
68047  #ifdef ENOLCK
68048  case ENOLCK: return DRMP3_ERROR;
68049  #endif
68050  #ifdef ENOSYS
68051  case ENOSYS: return DRMP3_NOT_IMPLEMENTED;
68052  #endif
68053  #ifdef ENOTEMPTY
68054  case ENOTEMPTY: return DRMP3_DIRECTORY_NOT_EMPTY;
68055  #endif
68056  #ifdef ELOOP
68057  case ELOOP: return DRMP3_TOO_MANY_LINKS;
68058  #endif
68059  #ifdef ENOMSG
68060  case ENOMSG: return DRMP3_NO_MESSAGE;
68061  #endif
68062  #ifdef EIDRM
68063  case EIDRM: return DRMP3_ERROR;
68064  #endif
68065  #ifdef ECHRNG
68066  case ECHRNG: return DRMP3_ERROR;
68067  #endif
68068  #ifdef EL2NSYNC
68069  case EL2NSYNC: return DRMP3_ERROR;
68070  #endif
68071  #ifdef EL3HLT
68072  case EL3HLT: return DRMP3_ERROR;
68073  #endif
68074  #ifdef EL3RST
68075  case EL3RST: return DRMP3_ERROR;
68076  #endif
68077  #ifdef ELNRNG
68078  case ELNRNG: return DRMP3_OUT_OF_RANGE;
68079  #endif
68080  #ifdef EUNATCH
68081  case EUNATCH: return DRMP3_ERROR;
68082  #endif
68083  #ifdef ENOCSI
68084  case ENOCSI: return DRMP3_ERROR;
68085  #endif
68086  #ifdef EL2HLT
68087  case EL2HLT: return DRMP3_ERROR;
68088  #endif
68089  #ifdef EBADE
68090  case EBADE: return DRMP3_ERROR;
68091  #endif
68092  #ifdef EBADR
68093  case EBADR: return DRMP3_ERROR;
68094  #endif
68095  #ifdef EXFULL
68096  case EXFULL: return DRMP3_ERROR;
68097  #endif
68098  #ifdef ENOANO
68099  case ENOANO: return DRMP3_ERROR;
68100  #endif
68101  #ifdef EBADRQC
68102  case EBADRQC: return DRMP3_ERROR;
68103  #endif
68104  #ifdef EBADSLT
68105  case EBADSLT: return DRMP3_ERROR;
68106  #endif
68107  #ifdef EBFONT
68108  case EBFONT: return DRMP3_INVALID_FILE;
68109  #endif
68110  #ifdef ENOSTR
68111  case ENOSTR: return DRMP3_ERROR;
68112  #endif
68113  #ifdef ENODATA
68114  case ENODATA: return DRMP3_NO_DATA_AVAILABLE;
68115  #endif
68116  #ifdef ETIME
68117  case ETIME: return DRMP3_TIMEOUT;
68118  #endif
68119  #ifdef ENOSR
68120  case ENOSR: return DRMP3_NO_DATA_AVAILABLE;
68121  #endif
68122  #ifdef ENONET
68123  case ENONET: return DRMP3_NO_NETWORK;
68124  #endif
68125  #ifdef ENOPKG
68126  case ENOPKG: return DRMP3_ERROR;
68127  #endif
68128  #ifdef EREMOTE
68129  case EREMOTE: return DRMP3_ERROR;
68130  #endif
68131  #ifdef ENOLINK
68132  case ENOLINK: return DRMP3_ERROR;
68133  #endif
68134  #ifdef EADV
68135  case EADV: return DRMP3_ERROR;
68136  #endif
68137  #ifdef ESRMNT
68138  case ESRMNT: return DRMP3_ERROR;
68139  #endif
68140  #ifdef ECOMM
68141  case ECOMM: return DRMP3_ERROR;
68142  #endif
68143  #ifdef EPROTO
68144  case EPROTO: return DRMP3_ERROR;
68145  #endif
68146  #ifdef EMULTIHOP
68147  case EMULTIHOP: return DRMP3_ERROR;
68148  #endif
68149  #ifdef EDOTDOT
68150  case EDOTDOT: return DRMP3_ERROR;
68151  #endif
68152  #ifdef EBADMSG
68153  case EBADMSG: return DRMP3_BAD_MESSAGE;
68154  #endif
68155  #ifdef EOVERFLOW
68156  case EOVERFLOW: return DRMP3_TOO_BIG;
68157  #endif
68158  #ifdef ENOTUNIQ
68159  case ENOTUNIQ: return DRMP3_NOT_UNIQUE;
68160  #endif
68161  #ifdef EBADFD
68162  case EBADFD: return DRMP3_ERROR;
68163  #endif
68164  #ifdef EREMCHG
68165  case EREMCHG: return DRMP3_ERROR;
68166  #endif
68167  #ifdef ELIBACC
68168  case ELIBACC: return DRMP3_ACCESS_DENIED;
68169  #endif
68170  #ifdef ELIBBAD
68171  case ELIBBAD: return DRMP3_INVALID_FILE;
68172  #endif
68173  #ifdef ELIBSCN
68174  case ELIBSCN: return DRMP3_INVALID_FILE;
68175  #endif
68176  #ifdef ELIBMAX
68177  case ELIBMAX: return DRMP3_ERROR;
68178  #endif
68179  #ifdef ELIBEXEC
68180  case ELIBEXEC: return DRMP3_ERROR;
68181  #endif
68182  #ifdef EILSEQ
68183  case EILSEQ: return DRMP3_INVALID_DATA;
68184  #endif
68185  #ifdef ERESTART
68186  case ERESTART: return DRMP3_ERROR;
68187  #endif
68188  #ifdef ESTRPIPE
68189  case ESTRPIPE: return DRMP3_ERROR;
68190  #endif
68191  #ifdef EUSERS
68192  case EUSERS: return DRMP3_ERROR;
68193  #endif
68194  #ifdef ENOTSOCK
68195  case ENOTSOCK: return DRMP3_NOT_SOCKET;
68196  #endif
68197  #ifdef EDESTADDRREQ
68198  case EDESTADDRREQ: return DRMP3_NO_ADDRESS;
68199  #endif
68200  #ifdef EMSGSIZE
68201  case EMSGSIZE: return DRMP3_TOO_BIG;
68202  #endif
68203  #ifdef EPROTOTYPE
68204  case EPROTOTYPE: return DRMP3_BAD_PROTOCOL;
68205  #endif
68206  #ifdef ENOPROTOOPT
68207  case ENOPROTOOPT: return DRMP3_PROTOCOL_UNAVAILABLE;
68208  #endif
68209  #ifdef EPROTONOSUPPORT
68210  case EPROTONOSUPPORT: return DRMP3_PROTOCOL_NOT_SUPPORTED;
68211  #endif
68212  #ifdef ESOCKTNOSUPPORT
68213  case ESOCKTNOSUPPORT: return DRMP3_SOCKET_NOT_SUPPORTED;
68214  #endif
68215  #ifdef EOPNOTSUPP
68216  case EOPNOTSUPP: return DRMP3_INVALID_OPERATION;
68217  #endif
68218  #ifdef EPFNOSUPPORT
68219  case EPFNOSUPPORT: return DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED;
68220  #endif
68221  #ifdef EAFNOSUPPORT
68222  case EAFNOSUPPORT: return DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED;
68223  #endif
68224  #ifdef EADDRINUSE
68225  case EADDRINUSE: return DRMP3_ALREADY_IN_USE;
68226  #endif
68227  #ifdef EADDRNOTAVAIL
68228  case EADDRNOTAVAIL: return DRMP3_ERROR;
68229  #endif
68230  #ifdef ENETDOWN
68231  case ENETDOWN: return DRMP3_NO_NETWORK;
68232  #endif
68233  #ifdef ENETUNREACH
68234  case ENETUNREACH: return DRMP3_NO_NETWORK;
68235  #endif
68236  #ifdef ENETRESET
68237  case ENETRESET: return DRMP3_NO_NETWORK;
68238  #endif
68239  #ifdef ECONNABORTED
68240  case ECONNABORTED: return DRMP3_NO_NETWORK;
68241  #endif
68242  #ifdef ECONNRESET
68243  case ECONNRESET: return DRMP3_CONNECTION_RESET;
68244  #endif
68245  #ifdef ENOBUFS
68246  case ENOBUFS: return DRMP3_NO_SPACE;
68247  #endif
68248  #ifdef EISCONN
68249  case EISCONN: return DRMP3_ALREADY_CONNECTED;
68250  #endif
68251  #ifdef ENOTCONN
68252  case ENOTCONN: return DRMP3_NOT_CONNECTED;
68253  #endif
68254  #ifdef ESHUTDOWN
68255  case ESHUTDOWN: return DRMP3_ERROR;
68256  #endif
68257  #ifdef ETOOMANYREFS
68258  case ETOOMANYREFS: return DRMP3_ERROR;
68259  #endif
68260  #ifdef ETIMEDOUT
68261  case ETIMEDOUT: return DRMP3_TIMEOUT;
68262  #endif
68263  #ifdef ECONNREFUSED
68264  case ECONNREFUSED: return DRMP3_CONNECTION_REFUSED;
68265  #endif
68266  #ifdef EHOSTDOWN
68267  case EHOSTDOWN: return DRMP3_NO_HOST;
68268  #endif
68269  #ifdef EHOSTUNREACH
68270  case EHOSTUNREACH: return DRMP3_NO_HOST;
68271  #endif
68272  #ifdef EALREADY
68273  case EALREADY: return DRMP3_IN_PROGRESS;
68274  #endif
68275  #ifdef EINPROGRESS
68276  case EINPROGRESS: return DRMP3_IN_PROGRESS;
68277  #endif
68278  #ifdef ESTALE
68279  case ESTALE: return DRMP3_INVALID_FILE;
68280  #endif
68281  #ifdef EUCLEAN
68282  case EUCLEAN: return DRMP3_ERROR;
68283  #endif
68284  #ifdef ENOTNAM
68285  case ENOTNAM: return DRMP3_ERROR;
68286  #endif
68287  #ifdef ENAVAIL
68288  case ENAVAIL: return DRMP3_ERROR;
68289  #endif
68290  #ifdef EISNAM
68291  case EISNAM: return DRMP3_ERROR;
68292  #endif
68293  #ifdef EREMOTEIO
68294  case EREMOTEIO: return DRMP3_IO_ERROR;
68295  #endif
68296  #ifdef EDQUOT
68297  case EDQUOT: return DRMP3_NO_SPACE;
68298  #endif
68299  #ifdef ENOMEDIUM
68300  case ENOMEDIUM: return DRMP3_DOES_NOT_EXIST;
68301  #endif
68302  #ifdef EMEDIUMTYPE
68303  case EMEDIUMTYPE: return DRMP3_ERROR;
68304  #endif
68305  #ifdef ECANCELED
68306  case ECANCELED: return DRMP3_CANCELLED;
68307  #endif
68308  #ifdef ENOKEY
68309  case ENOKEY: return DRMP3_ERROR;
68310  #endif
68311  #ifdef EKEYEXPIRED
68312  case EKEYEXPIRED: return DRMP3_ERROR;
68313  #endif
68314  #ifdef EKEYREVOKED
68315  case EKEYREVOKED: return DRMP3_ERROR;
68316  #endif
68317  #ifdef EKEYREJECTED
68318  case EKEYREJECTED: return DRMP3_ERROR;
68319  #endif
68320  #ifdef EOWNERDEAD
68321  case EOWNERDEAD: return DRMP3_ERROR;
68322  #endif
68323  #ifdef ENOTRECOVERABLE
68324  case ENOTRECOVERABLE: return DRMP3_ERROR;
68325  #endif
68326  #ifdef ERFKILL
68327  case ERFKILL: return DRMP3_ERROR;
68328  #endif
68329  #ifdef EHWPOISON
68330  case EHWPOISON: return DRMP3_ERROR;
68331  #endif
68332  default: return DRMP3_ERROR;
68333  }
68334 }
68335 static drmp3_result drmp3_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
68336 {
68337 #if defined(_MSC_VER) && _MSC_VER >= 1400
68338  errno_t err;
68339 #endif
68340  if (ppFile != NULL) {
68341  *ppFile = NULL;
68342  }
68343  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
68344  return DRMP3_INVALID_ARGS;
68345  }
68346 #if defined(_MSC_VER) && _MSC_VER >= 1400
68347  err = fopen_s(ppFile, pFilePath, pOpenMode);
68348  if (err != 0) {
68349  return drmp3_result_from_errno(err);
68350  }
68351 #else
68352 #if defined(_WIN32) || defined(__APPLE__)
68353  *ppFile = fopen(pFilePath, pOpenMode);
68354 #else
68355  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
68356  *ppFile = fopen64(pFilePath, pOpenMode);
68357  #else
68358  *ppFile = fopen(pFilePath, pOpenMode);
68359  #endif
68360 #endif
68361  if (*ppFile == NULL) {
68363  if (result == DRMP3_SUCCESS) {
68364  result = DRMP3_ERROR;
68365  }
68366  return result;
68367  }
68368 #endif
68369  return DRMP3_SUCCESS;
68370 }
68371 #if defined(_WIN32)
68372  #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
68373  #define DRMP3_HAS_WFOPEN
68374  #endif
68375 #endif
68376 static drmp3_result drmp3_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drmp3_allocation_callbacks* pAllocationCallbacks)
68377 {
68378  if (ppFile != NULL) {
68379  *ppFile = NULL;
68380  }
68381  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
68382  return DRMP3_INVALID_ARGS;
68383  }
68384 #if defined(DRMP3_HAS_WFOPEN)
68385  {
68386  #if defined(_MSC_VER) && _MSC_VER >= 1400
68387  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
68388  if (err != 0) {
68389  return drmp3_result_from_errno(err);
68390  }
68391  #else
68392  *ppFile = _wfopen(pFilePath, pOpenMode);
68393  if (*ppFile == NULL) {
68395  }
68396  #endif
68397  (void)pAllocationCallbacks;
68398  }
68399 #else
68400  {
68401  mbstate_t mbs;
68402  size_t lenMB;
68403  const wchar_t* pFilePathTemp = pFilePath;
68404  char* pFilePathMB = NULL;
68405  char pOpenModeMB[32] = {0};
68406  DRMP3_ZERO_OBJECT(&mbs);
68407  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
68408  if (lenMB == (size_t)-1) {
68410  }
68411  pFilePathMB = (char*)drmp3__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
68412  if (pFilePathMB == NULL) {
68413  return DRMP3_OUT_OF_MEMORY;
68414  }
68415  pFilePathTemp = pFilePath;
68416  DRMP3_ZERO_OBJECT(&mbs);
68417  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
68418  {
68419  size_t i = 0;
68420  for (;;) {
68421  if (pOpenMode[i] == 0) {
68422  pOpenModeMB[i] = '\0';
68423  break;
68424  }
68425  pOpenModeMB[i] = (char)pOpenMode[i];
68426  i += 1;
68427  }
68428  }
68429  *ppFile = fopen(pFilePathMB, pOpenModeMB);
68430  drmp3__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
68431  }
68432  if (*ppFile == NULL) {
68433  return DRMP3_ERROR;
68434  }
68435 #endif
68436  return DRMP3_SUCCESS;
68437 }
68438 static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
68439 {
68440  return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
68441 }
68442 static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin)
68443 {
68444  return fseek((FILE*)pUserData, offset, (origin == drmp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
68445 }
68446 DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
68447 {
68448  drmp3_bool32 result;
68449  FILE* pFile;
68450  if (drmp3_fopen(&pFile, pFilePath, "rb") != DRMP3_SUCCESS) {
68451  return DRMP3_FALSE;
68452  }
68453  result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
68454  if (result != DRMP3_TRUE) {
68455  fclose(pFile);
68456  return result;
68457  }
68458  return DRMP3_TRUE;
68459 }
68460 DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
68461 {
68462  drmp3_bool32 result;
68463  FILE* pFile;
68464  if (drmp3_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != DRMP3_SUCCESS) {
68465  return DRMP3_FALSE;
68466  }
68467  result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
68468  if (result != DRMP3_TRUE) {
68469  fclose(pFile);
68470  return result;
68471  }
68472  return DRMP3_TRUE;
68473 }
68474 #endif
68475 DRMP3_API void drmp3_uninit(drmp3* pMP3)
68476 {
68477  if (pMP3 == NULL) {
68478  return;
68479  }
68480 #ifndef DR_MP3_NO_STDIO
68481  if (pMP3->onRead == drmp3__on_read_stdio) {
68482  FILE* pFile = (FILE*)pMP3->pUserData;
68483  if (pFile != NULL) {
68484  fclose(pFile);
68485  pMP3->pUserData = NULL;
68486  }
68487  }
68488 #endif
68490 }
68491 #if defined(DR_MP3_FLOAT_OUTPUT)
68492 static void drmp3_f32_to_s16(drmp3_int16* dst, const float* src, drmp3_uint64 sampleCount)
68493 {
68494  drmp3_uint64 i;
68495  drmp3_uint64 i4;
68496  drmp3_uint64 sampleCount4;
68497  i = 0;
68498  sampleCount4 = sampleCount >> 2;
68499  for (i4 = 0; i4 < sampleCount4; i4 += 1) {
68500  float x0 = src[i+0];
68501  float x1 = src[i+1];
68502  float x2 = src[i+2];
68503  float x3 = src[i+3];
68504  x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
68505  x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
68506  x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
68507  x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
68508  x0 = x0 * 32767.0f;
68509  x1 = x1 * 32767.0f;
68510  x2 = x2 * 32767.0f;
68511  x3 = x3 * 32767.0f;
68512  dst[i+0] = (drmp3_int16)x0;
68513  dst[i+1] = (drmp3_int16)x1;
68514  dst[i+2] = (drmp3_int16)x2;
68515  dst[i+3] = (drmp3_int16)x3;
68516  i += 4;
68517  }
68518  for (; i < sampleCount; i += 1) {
68519  float x = src[i];
68520  x = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
68521  x = x * 32767.0f;
68522  dst[i] = (drmp3_int16)x;
68523  }
68524 }
68525 #endif
68526 #if !defined(DR_MP3_FLOAT_OUTPUT)
68527 static void drmp3_s16_to_f32(float* dst, const drmp3_int16* src, drmp3_uint64 sampleCount)
68528 {
68529  drmp3_uint64 i;
68530  for (i = 0; i < sampleCount; i += 1) {
68531  float x = (float)src[i];
68532  x = x * 0.000030517578125f;
68533  dst[i] = x;
68534  }
68535 }
68536 #endif
68537 static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3* pMP3, drmp3_uint64 framesToRead, void* pBufferOut)
68538 {
68539  drmp3_uint64 totalFramesRead = 0;
68540  DRMP3_ASSERT(pMP3 != NULL);
68541  DRMP3_ASSERT(pMP3->onRead != NULL);
68542  while (framesToRead > 0) {
68543  drmp3_uint32 framesToConsume = (drmp3_uint32)DRMP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
68544  if (pBufferOut != NULL) {
68545  #if defined(DR_MP3_FLOAT_OUTPUT)
68546  float* pFramesOutF32 = (float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
68547  float* pFramesInF32 = (float*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
68548  DRMP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
68549  #else
68550  drmp3_int16* pFramesOutS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalFramesRead * pMP3->channels);
68551  drmp3_int16* pFramesInS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(drmp3_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
68552  DRMP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(drmp3_int16) * framesToConsume * pMP3->channels);
68553  #endif
68554  }
68555  pMP3->currentPCMFrame += framesToConsume;
68556  pMP3->pcmFramesConsumedInMP3Frame += framesToConsume;
68557  pMP3->pcmFramesRemainingInMP3Frame -= framesToConsume;
68558  totalFramesRead += framesToConsume;
68559  framesToRead -= framesToConsume;
68560  if (framesToRead == 0) {
68561  break;
68562  }
68564  if (drmp3_decode_next_frame(pMP3) == 0) {
68565  break;
68566  }
68567  }
68568  return totalFramesRead;
68569 }
68570 DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut)
68571 {
68572  if (pMP3 == NULL || pMP3->onRead == NULL) {
68573  return 0;
68574  }
68575 #if defined(DR_MP3_FLOAT_OUTPUT)
68576  return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
68577 #else
68578  {
68579  drmp3_int16 pTempS16[8192];
68580  drmp3_uint64 totalPCMFramesRead = 0;
68581  while (totalPCMFramesRead < framesToRead) {
68582  drmp3_uint64 framesJustRead;
68583  drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
68584  drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempS16) / pMP3->channels;
68585  if (framesToReadNow > framesRemaining) {
68586  framesToReadNow = framesRemaining;
68587  }
68588  framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempS16);
68589  if (framesJustRead == 0) {
68590  break;
68591  }
68592  drmp3_s16_to_f32((float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalPCMFramesRead * pMP3->channels), pTempS16, framesJustRead * pMP3->channels);
68593  totalPCMFramesRead += framesJustRead;
68594  }
68595  return totalPCMFramesRead;
68596  }
68597 #endif
68598 }
68600 {
68601  if (pMP3 == NULL || pMP3->onRead == NULL) {
68602  return 0;
68603  }
68604 #if !defined(DR_MP3_FLOAT_OUTPUT)
68605  return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
68606 #else
68607  {
68608  float pTempF32[4096];
68609  drmp3_uint64 totalPCMFramesRead = 0;
68610  while (totalPCMFramesRead < framesToRead) {
68611  drmp3_uint64 framesJustRead;
68612  drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
68613  drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempF32) / pMP3->channels;
68614  if (framesToReadNow > framesRemaining) {
68615  framesToReadNow = framesRemaining;
68616  }
68617  framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempF32);
68618  if (framesJustRead == 0) {
68619  break;
68620  }
68621  drmp3_f32_to_s16((drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalPCMFramesRead * pMP3->channels), pTempF32, framesJustRead * pMP3->channels);
68622  totalPCMFramesRead += framesJustRead;
68623  }
68624  return totalPCMFramesRead;
68625  }
68626 #endif
68627 }
68628 static void drmp3_reset(drmp3* pMP3)
68629 {
68630  DRMP3_ASSERT(pMP3 != NULL);
68631  pMP3->pcmFramesConsumedInMP3Frame = 0;
68632  pMP3->pcmFramesRemainingInMP3Frame = 0;
68633  pMP3->currentPCMFrame = 0;
68634  pMP3->dataSize = 0;
68635  pMP3->atEnd = DRMP3_FALSE;
68636  drmp3dec_init(&pMP3->decoder);
68637 }
68639 {
68640  DRMP3_ASSERT(pMP3 != NULL);
68641  DRMP3_ASSERT(pMP3->onSeek != NULL);
68642  if (!drmp3__on_seek(pMP3, 0, drmp3_seek_origin_start)) {
68643  return DRMP3_FALSE;
68644  }
68645  drmp3_reset(pMP3);
68646  return DRMP3_TRUE;
68647 }
68649 {
68650  drmp3_uint64 framesRead;
68651 #if defined(DR_MP3_FLOAT_OUTPUT)
68652  framesRead = drmp3_read_pcm_frames_f32(pMP3, frameOffset, NULL);
68653 #else
68654  framesRead = drmp3_read_pcm_frames_s16(pMP3, frameOffset, NULL);
68655 #endif
68656  if (framesRead != frameOffset) {
68657  return DRMP3_FALSE;
68658  }
68659  return DRMP3_TRUE;
68660 }
68662 {
68663  DRMP3_ASSERT(pMP3 != NULL);
68664  if (frameIndex == pMP3->currentPCMFrame) {
68665  return DRMP3_TRUE;
68666  }
68667  if (frameIndex < pMP3->currentPCMFrame) {
68668  if (!drmp3_seek_to_start_of_stream(pMP3)) {
68669  return DRMP3_FALSE;
68670  }
68671  }
68672  DRMP3_ASSERT(frameIndex >= pMP3->currentPCMFrame);
68673  return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, (frameIndex - pMP3->currentPCMFrame));
68674 }
68675 static drmp3_bool32 drmp3_find_closest_seek_point(drmp3* pMP3, drmp3_uint64 frameIndex, drmp3_uint32* pSeekPointIndex)
68676 {
68677  drmp3_uint32 iSeekPoint;
68678  DRMP3_ASSERT(pSeekPointIndex != NULL);
68679  *pSeekPointIndex = 0;
68680  if (frameIndex < pMP3->pSeekPoints[0].pcmFrameIndex) {
68681  return DRMP3_FALSE;
68682  }
68683  for (iSeekPoint = 0; iSeekPoint < pMP3->seekPointCount; ++iSeekPoint) {
68684  if (pMP3->pSeekPoints[iSeekPoint].pcmFrameIndex > frameIndex) {
68685  break;
68686  }
68687  *pSeekPointIndex = iSeekPoint;
68688  }
68689  return DRMP3_TRUE;
68690 }
68692 {
68693  drmp3_seek_point seekPoint;
68694  drmp3_uint32 priorSeekPointIndex;
68695  drmp3_uint16 iMP3Frame;
68696  drmp3_uint64 leftoverFrames;
68697  DRMP3_ASSERT(pMP3 != NULL);
68698  DRMP3_ASSERT(pMP3->pSeekPoints != NULL);
68699  DRMP3_ASSERT(pMP3->seekPointCount > 0);
68700  if (drmp3_find_closest_seek_point(pMP3, frameIndex, &priorSeekPointIndex)) {
68701  seekPoint = pMP3->pSeekPoints[priorSeekPointIndex];
68702  } else {
68703  seekPoint.seekPosInBytes = 0;
68704  seekPoint.pcmFrameIndex = 0;
68705  seekPoint.mp3FramesToDiscard = 0;
68706  seekPoint.pcmFramesToDiscard = 0;
68707  }
68708  if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, drmp3_seek_origin_start)) {
68709  return DRMP3_FALSE;
68710  }
68711  drmp3_reset(pMP3);
68712  for (iMP3Frame = 0; iMP3Frame < seekPoint.mp3FramesToDiscard; ++iMP3Frame) {
68713  drmp3_uint32 pcmFramesRead;
68714  drmp3d_sample_t* pPCMFrames;
68715  pPCMFrames = NULL;
68716  if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) {
68717  pPCMFrames = (drmp3d_sample_t*)pMP3->pcmFrames;
68718  }
68719  pcmFramesRead = drmp3_decode_next_frame_ex(pMP3, pPCMFrames);
68720  if (pcmFramesRead == 0) {
68721  return DRMP3_FALSE;
68722  }
68723  }
68724  pMP3->currentPCMFrame = seekPoint.pcmFrameIndex - seekPoint.pcmFramesToDiscard;
68725  leftoverFrames = frameIndex - pMP3->currentPCMFrame;
68726  return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, leftoverFrames);
68727 }
68729 {
68730  if (pMP3 == NULL || pMP3->onSeek == NULL) {
68731  return DRMP3_FALSE;
68732  }
68733  if (frameIndex == 0) {
68734  return drmp3_seek_to_start_of_stream(pMP3);
68735  }
68736  if (pMP3->pSeekPoints != NULL && pMP3->seekPointCount > 0) {
68737  return drmp3_seek_to_pcm_frame__seek_table(pMP3, frameIndex);
68738  } else {
68739  return drmp3_seek_to_pcm_frame__brute_force(pMP3, frameIndex);
68740  }
68741 }
68743 {
68744  drmp3_uint64 currentPCMFrame;
68745  drmp3_uint64 totalPCMFrameCount;
68746  drmp3_uint64 totalMP3FrameCount;
68747  if (pMP3 == NULL) {
68748  return DRMP3_FALSE;
68749  }
68750  if (pMP3->onSeek == NULL) {
68751  return DRMP3_FALSE;
68752  }
68753  currentPCMFrame = pMP3->currentPCMFrame;
68754  if (!drmp3_seek_to_start_of_stream(pMP3)) {
68755  return DRMP3_FALSE;
68756  }
68757  totalPCMFrameCount = 0;
68758  totalMP3FrameCount = 0;
68759  for (;;) {
68760  drmp3_uint32 pcmFramesInCurrentMP3Frame;
68761  pcmFramesInCurrentMP3Frame = drmp3_decode_next_frame_ex(pMP3, NULL);
68762  if (pcmFramesInCurrentMP3Frame == 0) {
68763  break;
68764  }
68765  totalPCMFrameCount += pcmFramesInCurrentMP3Frame;
68766  totalMP3FrameCount += 1;
68767  }
68768  if (!drmp3_seek_to_start_of_stream(pMP3)) {
68769  return DRMP3_FALSE;
68770  }
68771  if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
68772  return DRMP3_FALSE;
68773  }
68774  if (pMP3FrameCount != NULL) {
68775  *pMP3FrameCount = totalMP3FrameCount;
68776  }
68777  if (pPCMFrameCount != NULL) {
68778  *pPCMFrameCount = totalPCMFrameCount;
68779  }
68780  return DRMP3_TRUE;
68781 }
68783 {
68784  drmp3_uint64 totalPCMFrameCount;
68785  if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) {
68786  return 0;
68787  }
68788  return totalPCMFrameCount;
68789 }
68791 {
68792  drmp3_uint64 totalMP3FrameCount;
68793  if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, NULL)) {
68794  return 0;
68795  }
68796  return totalMP3FrameCount;
68797 }
68798 static void drmp3__accumulate_running_pcm_frame_count(drmp3* pMP3, drmp3_uint32 pcmFrameCountIn, drmp3_uint64* pRunningPCMFrameCount, float* pRunningPCMFrameCountFractionalPart)
68799 {
68800  float srcRatio;
68801  float pcmFrameCountOutF;
68802  drmp3_uint32 pcmFrameCountOut;
68803  srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate;
68804  DRMP3_ASSERT(srcRatio > 0);
68805  pcmFrameCountOutF = *pRunningPCMFrameCountFractionalPart + (pcmFrameCountIn / srcRatio);
68806  pcmFrameCountOut = (drmp3_uint32)pcmFrameCountOutF;
68807  *pRunningPCMFrameCountFractionalPart = pcmFrameCountOutF - pcmFrameCountOut;
68808  *pRunningPCMFrameCount += pcmFrameCountOut;
68809 }
68810 typedef struct
68811 {
68812  drmp3_uint64 bytePos;
68813  drmp3_uint64 pcmFrameIndex;
68816 {
68817  drmp3_uint32 seekPointCount;
68818  drmp3_uint64 currentPCMFrame;
68819  drmp3_uint64 totalMP3FrameCount;
68820  drmp3_uint64 totalPCMFrameCount;
68821  if (pMP3 == NULL || pSeekPointCount == NULL || pSeekPoints == NULL) {
68822  return DRMP3_FALSE;
68823  }
68824  seekPointCount = *pSeekPointCount;
68825  if (seekPointCount == 0) {
68826  return DRMP3_FALSE;
68827  }
68828  currentPCMFrame = pMP3->currentPCMFrame;
68829  if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, &totalPCMFrameCount)) {
68830  return DRMP3_FALSE;
68831  }
68832  if (totalMP3FrameCount < DRMP3_SEEK_LEADING_MP3_FRAMES+1) {
68833  seekPointCount = 1;
68834  pSeekPoints[0].seekPosInBytes = 0;
68835  pSeekPoints[0].pcmFrameIndex = 0;
68836  pSeekPoints[0].mp3FramesToDiscard = 0;
68837  pSeekPoints[0].pcmFramesToDiscard = 0;
68838  } else {
68839  drmp3_uint64 pcmFramesBetweenSeekPoints;
68840  drmp3__seeking_mp3_frame_info mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES+1];
68841  drmp3_uint64 runningPCMFrameCount = 0;
68842  float runningPCMFrameCountFractionalPart = 0;
68843  drmp3_uint64 nextTargetPCMFrame;
68844  drmp3_uint32 iMP3Frame;
68845  drmp3_uint32 iSeekPoint;
68846  if (seekPointCount > totalMP3FrameCount-1) {
68847  seekPointCount = (drmp3_uint32)totalMP3FrameCount-1;
68848  }
68849  pcmFramesBetweenSeekPoints = totalPCMFrameCount / (seekPointCount+1);
68850  if (!drmp3_seek_to_start_of_stream(pMP3)) {
68851  return DRMP3_FALSE;
68852  }
68853  for (iMP3Frame = 0; iMP3Frame < DRMP3_SEEK_LEADING_MP3_FRAMES+1; ++iMP3Frame) {
68854  drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
68855  DRMP3_ASSERT(pMP3->streamCursor >= pMP3->dataSize);
68856  mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize;
68857  mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount;
68858  pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
68859  if (pcmFramesInCurrentMP3FrameIn == 0) {
68860  return DRMP3_FALSE;
68861  }
68862  drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
68863  }
68864  nextTargetPCMFrame = 0;
68865  for (iSeekPoint = 0; iSeekPoint < seekPointCount; ++iSeekPoint) {
68866  nextTargetPCMFrame += pcmFramesBetweenSeekPoints;
68867  for (;;) {
68868  if (nextTargetPCMFrame < runningPCMFrameCount) {
68869  pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
68870  pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
68871  pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
68872  pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
68873  break;
68874  } else {
68875  size_t i;
68876  drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
68877  for (i = 0; i < DRMP3_COUNTOF(mp3FrameInfo)-1; ++i) {
68878  mp3FrameInfo[i] = mp3FrameInfo[i+1];
68879  }
68880  mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize;
68881  mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount;
68882  pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
68883  if (pcmFramesInCurrentMP3FrameIn == 0) {
68884  pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
68885  pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
68886  pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
68887  pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
68888  break;
68889  }
68890  drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
68891  }
68892  }
68893  }
68894  if (!drmp3_seek_to_start_of_stream(pMP3)) {
68895  return DRMP3_FALSE;
68896  }
68897  if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
68898  return DRMP3_FALSE;
68899  }
68900  }
68901  *pSeekPointCount = seekPointCount;
68902  return DRMP3_TRUE;
68903 }
68905 {
68906  if (pMP3 == NULL) {
68907  return DRMP3_FALSE;
68908  }
68909  if (seekPointCount == 0 || pSeekPoints == NULL) {
68910  pMP3->seekPointCount = 0;
68911  pMP3->pSeekPoints = NULL;
68912  } else {
68913  pMP3->seekPointCount = seekPointCount;
68914  pMP3->pSeekPoints = pSeekPoints;
68915  }
68916  return DRMP3_TRUE;
68917 }
68918 static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
68919 {
68920  drmp3_uint64 totalFramesRead = 0;
68921  drmp3_uint64 framesCapacity = 0;
68922  float* pFrames = NULL;
68923  float temp[4096];
68924  DRMP3_ASSERT(pMP3 != NULL);
68925  for (;;) {
68926  drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
68927  drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp);
68928  if (framesJustRead == 0) {
68929  break;
68930  }
68931  if (framesCapacity < totalFramesRead + framesJustRead) {
68932  drmp3_uint64 oldFramesBufferSize;
68933  drmp3_uint64 newFramesBufferSize;
68934  drmp3_uint64 newFramesCap;
68935  float* pNewFrames;
68936  newFramesCap = framesCapacity * 2;
68937  if (newFramesCap < totalFramesRead + framesJustRead) {
68938  newFramesCap = totalFramesRead + framesJustRead;
68939  }
68940  oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(float);
68941  newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(float);
68942  if (newFramesBufferSize > DRMP3_SIZE_MAX) {
68943  break;
68944  }
68945  pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
68946  if (pNewFrames == NULL) {
68948  break;
68949  }
68950  pFrames = pNewFrames;
68951  framesCapacity = newFramesCap;
68952  }
68953  DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float)));
68954  totalFramesRead += framesJustRead;
68955  if (framesJustRead != framesToReadRightNow) {
68956  break;
68957  }
68958  }
68959  if (pConfig != NULL) {
68960  pConfig->channels = pMP3->channels;
68961  pConfig->sampleRate = pMP3->sampleRate;
68962  }
68963  drmp3_uninit(pMP3);
68964  if (pTotalFrameCount) {
68965  *pTotalFrameCount = totalFramesRead;
68966  }
68967  return pFrames;
68968 }
68969 static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
68970 {
68971  drmp3_uint64 totalFramesRead = 0;
68972  drmp3_uint64 framesCapacity = 0;
68973  drmp3_int16* pFrames = NULL;
68974  drmp3_int16 temp[4096];
68975  DRMP3_ASSERT(pMP3 != NULL);
68976  for (;;) {
68977  drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
68978  drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_s16(pMP3, framesToReadRightNow, temp);
68979  if (framesJustRead == 0) {
68980  break;
68981  }
68982  if (framesCapacity < totalFramesRead + framesJustRead) {
68983  drmp3_uint64 newFramesBufferSize;
68984  drmp3_uint64 oldFramesBufferSize;
68985  drmp3_uint64 newFramesCap;
68986  drmp3_int16* pNewFrames;
68987  newFramesCap = framesCapacity * 2;
68988  if (newFramesCap < totalFramesRead + framesJustRead) {
68989  newFramesCap = totalFramesRead + framesJustRead;
68990  }
68991  oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(drmp3_int16);
68992  newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(drmp3_int16);
68993  if (newFramesBufferSize > DRMP3_SIZE_MAX) {
68994  break;
68995  }
68996  pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
68997  if (pNewFrames == NULL) {
68999  break;
69000  }
69001  pFrames = pNewFrames;
69002  framesCapacity = newFramesCap;
69003  }
69004  DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(drmp3_int16)));
69005  totalFramesRead += framesJustRead;
69006  if (framesJustRead != framesToReadRightNow) {
69007  break;
69008  }
69009  }
69010  if (pConfig != NULL) {
69011  pConfig->channels = pMP3->channels;
69012  pConfig->sampleRate = pMP3->sampleRate;
69013  }
69014  drmp3_uninit(pMP3);
69015  if (pTotalFrameCount) {
69016  *pTotalFrameCount = totalFramesRead;
69017  }
69018  return pFrames;
69019 }
69020 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)
69021 {
69022  drmp3 mp3;
69023  if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
69024  return NULL;
69025  }
69026  return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
69027 }
69028 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)
69029 {
69030  drmp3 mp3;
69031  if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
69032  return NULL;
69033  }
69034  return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
69035 }
69036 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)
69037 {
69038  drmp3 mp3;
69039  if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
69040  return NULL;
69041  }
69042  return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
69043 }
69044 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)
69045 {
69046  drmp3 mp3;
69047  if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
69048  return NULL;
69049  }
69050  return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
69051 }
69052 #ifndef DR_MP3_NO_STDIO
69053 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)
69054 {
69055  drmp3 mp3;
69056  if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
69057  return NULL;
69058  }
69059  return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
69060 }
69061 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)
69062 {
69063  drmp3 mp3;
69064  if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
69065  return NULL;
69066  }
69067  return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
69068 }
69069 #endif
69070 DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
69071 {
69072  if (pAllocationCallbacks != NULL) {
69073  return drmp3__malloc_from_callbacks(sz, pAllocationCallbacks);
69074  } else {
69075  return drmp3__malloc_default(sz, NULL);
69076  }
69077 }
69078 DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
69079 {
69080  if (pAllocationCallbacks != NULL) {
69081  drmp3__free_from_callbacks(p, pAllocationCallbacks);
69082  } else {
69084  }
69085 }
69086 #endif
69087 /* dr_mp3_c end */
69088 #endif /* DRMP3_IMPLEMENTATION */
69089 #endif /* MA_NO_MP3 */
69090 
69091 
69092 /* End globally disabled warnings. */
69093 #if defined(_MSC_VER)
69094  #pragma warning(pop)
69095 #endif
69096 
69097 #endif /* miniaudio_c */
69098 #endif /* MINIAUDIO_IMPLEMENTATION */
69099 
69100 /*
69101 RELEASE NOTES - VERSION 0.10.x
69102 ==============================
69103 Version 0.10 includes major API changes and refactoring, mostly concerned with the data conversion system. Data conversion is performed internally to convert
69104 audio data between the format requested when initializing the `ma_device` object and the format of the internal device used by the backend. The same applies
69105 to the `ma_decoder` object. The previous design has several design flaws and missing features which necessitated a complete redesign.
69106 
69107 
69108 Changes to Data Conversion
69109 --------------------------
69110 The previous data conversion system used callbacks to deliver input data for conversion. This design works well in some specific situations, but in other
69111 situations it has some major readability and maintenance issues. The decision was made to replace this with a more iterative approach where you just pass in a
69112 pointer to the input data directly rather than dealing with a callback.
69113 
69114 The following are the data conversion APIs that have been removed and their replacements:
69115 
69116  - ma_format_converter -> ma_convert_pcm_frames_format()
69117  - ma_channel_router -> ma_channel_converter
69118  - ma_src -> ma_resampler
69119  - ma_pcm_converter -> ma_data_converter
69120 
69121 The previous conversion APIs accepted a callback in their configs. There are no longer any callbacks to deal with. Instead you just pass the data into the
69122 `*_process_pcm_frames()` function as a pointer to a buffer.
69123 
69124 The simplest aspect of data conversion is sample format conversion. To convert between two formats, just call `ma_convert_pcm_frames_format()`. Channel
69125 conversion is also simple which you can do with `ma_channel_converter` via `ma_channel_converter_process_pcm_frames()`.
69126 
69127 Resampling is more complicated because the number of output frames that are processed is different to the number of input frames that are consumed. When you
69128 call `ma_resampler_process_pcm_frames()` you need to pass in the number of input frames available for processing and the number of output frames you want to
69129 output. Upon returning they will receive the number of input frames that were consumed and the number of output frames that were generated.
69130 
69131 The `ma_data_converter` API is a wrapper around format, channel and sample rate conversion and handles all of the data conversion you'll need which probably
69132 makes it the best option if you need to do data conversion.
69133 
69134 In addition to changes to the API design, a few other changes have been made to the data conversion pipeline:
69135 
69136  - The sinc resampler has been removed. This was completely broken and never actually worked properly.
69137  - The linear resampler now uses low-pass filtering to remove aliasing. The quality of the low-pass filter can be controlled via the resampler config with the
69138  `lpfOrder` option, which has a maximum value of MA_MAX_FILTER_ORDER.
69139  - Data conversion now supports s16 natively which runs through a fixed point pipeline. Previously everything needed to be converted to floating point before
69140  processing, whereas now both s16 and f32 are natively supported. Other formats still require conversion to either s16 or f32 prior to processing, however
69141  `ma_data_converter` will handle this for you.
69142 
69143 
69144 Custom Memory Allocators
69145 ------------------------
69146 miniaudio has always supported macro level customization for memory allocation via MA_MALLOC, MA_REALLOC and MA_FREE, however some scenarios require more
69147 flexibility by allowing a user data pointer to be passed to the custom allocation routines. Support for this has been added to version 0.10 via the
69148 `ma_allocation_callbacks` structure. Anything making use of heap allocations has been updated to accept this new structure.
69149 
69150 The `ma_context_config` structure has been updated with a new member called `allocationCallbacks`. Leaving this set to it's defaults returned by
69151 `ma_context_config_init()` will cause it to use MA_MALLOC, MA_REALLOC and MA_FREE. Likewise, The `ma_decoder_config` structure has been updated in the same
69152 way, and leaving everything as-is after `ma_decoder_config_init()` will cause it to use the same defaults.
69153 
69154 The following APIs have been updated to take a pointer to a `ma_allocation_callbacks` object. Setting this parameter to NULL will cause it to use defaults.
69155 Otherwise they will use the relevant callback in the structure.
69156 
69157  - ma_malloc()
69158  - ma_realloc()
69159  - ma_free()
69160  - ma_aligned_malloc()
69161  - ma_aligned_free()
69162  - ma_rb_init() / ma_rb_init_ex()
69163  - ma_pcm_rb_init() / ma_pcm_rb_init_ex()
69164 
69165 Note that you can continue to use MA_MALLOC, MA_REALLOC and MA_FREE as per normal. These will continue to be used by default if you do not specify custom
69166 allocation callbacks.
69167 
69168 
69169 Buffer and Period Configuration Changes
69170 ---------------------------------------
69171 The way in which the size of the internal buffer and periods are specified in the device configuration have changed. In previous versions, the config variables
69172 `bufferSizeInFrames` and `bufferSizeInMilliseconds` defined the size of the entire buffer, with the size of a period being the size of this variable divided by
69173 the period count. This became confusing because people would expect the value of `bufferSizeInFrames` or `bufferSizeInMilliseconds` to independantly determine
69174 latency, when in fact it was that value divided by the period count that determined it. These variables have been removed and replaced with new ones called
69175 `periodSizeInFrames` and `periodSizeInMilliseconds`.
69176 
69177 These new configuration variables work in the same way as their predecessors in that if one is set to 0, the other will be used, but the main difference is
69178 that you now set these to you desired latency rather than the size of the entire buffer. The benefit of this is that it's much easier and less confusing to
69179 configure latency.
69180 
69181 The following unused APIs have been removed:
69182 
69183  ma_get_default_buffer_size_in_milliseconds()
69184  ma_get_default_buffer_size_in_frames()
69185 
69186 The following macros have been removed:
69187 
69188  MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY
69189  MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE
69190 
69191 
69192 Other API Changes
69193 -----------------
69194 Other less major API changes have also been made in version 0.10.
69195 
69196 `ma_device_set_stop_callback()` has been removed. If you require a stop callback, you must now set it via the device config just like the data callback.
69197 
69198 The `ma_sine_wave` API has been replaced with a more general API called `ma_waveform`. This supports generation of different types of waveforms, including
69199 sine, square, triangle and sawtooth. Use `ma_waveform_init()` in place of `ma_sine_wave_init()` to initialize the waveform object. This takes a configuration
69200 object called `ma_waveform_config` which defines the properties of the waveform. Use `ma_waveform_config_init()` to initialize a `ma_waveform_config` object.
69201 Use `ma_waveform_read_pcm_frames()` in place of `ma_sine_wave_read_f32()` and `ma_sine_wave_read_f32_ex()`.
69202 
69203 `ma_convert_frames()` and `ma_convert_frames_ex()` have been changed. Both of these functions now take a new parameter called `frameCountOut` which specifies
69204 the size of the output buffer in PCM frames. This has been added for safety. In addition to this, the parameters for `ma_convert_frames_ex()` have changed to
69205 take a pointer to a `ma_data_converter_config` object to specify the input and output formats to convert between. This was done to make it more flexible, to
69206 prevent the parameter list getting too long, and to prevent API breakage whenever a new conversion property is added.
69207 
69208 `ma_calculate_frame_count_after_src()` has been renamed to `ma_calculate_frame_count_after_resampling()` for consistency with the new `ma_resampler` API.
69209 
69210 
69211 Filters
69212 -------
69213 The following filters have been added:
69214 
69215  |-------------|-------------------------------------------------------------------|
69216  | API | Description |
69217  |-------------|-------------------------------------------------------------------|
69218  | ma_biquad | Biquad filter (transposed direct form 2) |
69219  | ma_lpf1 | First order low-pass filter |
69220  | ma_lpf2 | Second order low-pass filter |
69221  | ma_lpf | High order low-pass filter (Butterworth) |
69222  | ma_hpf1 | First order high-pass filter |
69223  | ma_hpf2 | Second order high-pass filter |
69224  | ma_hpf | High order high-pass filter (Butterworth) |
69225  | ma_bpf2 | Second order band-pass filter |
69226  | ma_bpf | High order band-pass filter |
69227  | ma_peak2 | Second order peaking filter |
69228  | ma_notch2 | Second order notching filter |
69229  | ma_loshelf2 | Second order low shelf filter |
69230  | ma_hishelf2 | Second order high shelf filter |
69231  |-------------|-------------------------------------------------------------------|
69232 
69233 These filters all support 32-bit floating point and 16-bit signed integer formats natively. Other formats need to be converted beforehand.
69234 
69235 
69236 Sine, Square, Triangle and Sawtooth Waveforms
69237 ---------------------------------------------
69238 Previously miniaudio supported only sine wave generation. This has now been generalized to support sine, square, triangle and sawtooth waveforms. The old
69239 `ma_sine_wave` API has been removed and replaced with the `ma_waveform` API. Use `ma_waveform_config_init()` to initialize a config object, and then pass it
69240 into `ma_waveform_init()`. Then use `ma_waveform_read_pcm_frames()` to read PCM data.
69241 
69242 
69243 Noise Generation
69244 ----------------
69245 A noise generation API has been added. This is used via the `ma_noise` API. Currently white, pink and Brownian noise is supported. The `ma_noise` API is
69246 similar to the waveform API. Use `ma_noise_config_init()` to initialize a config object, and then pass it into `ma_noise_init()` to initialize a `ma_noise`
69247 object. Then use `ma_noise_read_pcm_frames()` to read PCM data.
69248 
69249 
69250 Miscellaneous Changes
69251 ---------------------
69252 The MA_NO_STDIO option has been removed. This would disable file I/O APIs, however this has proven to be too hard to maintain for it's perceived value and was
69253 therefore removed.
69254 
69255 Internal functions have all been made static where possible. If you get warnings about unused functions, please submit a bug report.
69256 
69257 The `ma_device` structure is no longer defined as being aligned to MA_SIMD_ALIGNMENT. This resulted in a possible crash when allocating a `ma_device` object on
69258 the heap, but not aligning it to MA_SIMD_ALIGNMENT. This crash would happen due to the compiler seeing the alignment specified on the structure and assuming it
69259 was always aligned as such and thinking it was safe to emit alignment-dependant SIMD instructions. Since miniaudio's philosophy is for things to just work,
69260 this has been removed from all structures.
69261 
69262 Results codes have been overhauled. Unnecessary result codes have been removed, and some have been renumbered for organisation purposes. If you are are binding
69263 maintainer you will need to update your result codes. Support has also been added for retrieving a human readable description of a given result code via the
69264 `ma_result_description()` API.
69265 
69266 ALSA: The automatic format conversion, channel conversion and resampling performed by ALSA is now disabled by default as they were causing some compatibility
69267 issues with certain devices and configurations. These can be individually enabled via the device config:
69268 
69269  ```c
69270  deviceConfig.alsa.noAutoFormat = MA_TRUE;
69271  deviceConfig.alsa.noAutoChannels = MA_TRUE;
69272  deviceConfig.alsa.noAutoResample = MA_TRUE;
69273  ```
69274 */
69275 
69276 /*
69277 RELEASE NOTES - VERSION 0.9.x
69278 =============================
69279 Version 0.9 includes major API changes, centered mostly around full-duplex and the rebrand to "miniaudio". Before I go into detail about the major changes I
69280 would like to apologize. I know it's annoying dealing with breaking API changes, but I think it's best to get these changes out of the way now while the
69281 library is still relatively young and unknown.
69282 
69283 There's been a lot of refactoring with this release so there's a good chance a few bugs have been introduced. I apologize in advance for this. You may want to
69284 hold off on upgrading for the short term if you're worried. If mini_al v0.8.14 works for you, and you don't need full-duplex support, you can avoid upgrading
69285 (though you won't be getting future bug fixes).
69286 
69287 
69288 Rebranding to "miniaudio"
69289 -------------------------
69290 The decision was made to rename mini_al to miniaudio. Don't worry, it's the same project. The reason for this is simple:
69291 
69292 1) Having the word "audio" in the title makes it immediately clear that the library is related to audio; and
69293 2) I don't like the look of the underscore.
69294 
69295 This rebrand has necessitated a change in namespace from "mal" to "ma". I know this is annoying, and I apologize, but it's better to get this out of the road
69296 now rather than later. Also, since there are necessary API changes for full-duplex support I think it's better to just get the namespace change over and done
69297 with at the same time as the full-duplex changes. I'm hoping this will be the last of the major API changes. Fingers crossed!
69298 
69299 The implementation define is now "#define MINIAUDIO_IMPLEMENTATION". You can also use "#define MA_IMPLEMENTATION" if that's your preference.
69300 
69301 
69302 Full-Duplex Support
69303 -------------------
69304 The major feature added to version 0.9 is full-duplex. This has necessitated a few API changes.
69305 
69306 1) The data callback has now changed. Previously there was one type of callback for playback and another for capture. I wanted to avoid a third callback just
69307  for full-duplex so the decision was made to break this API and unify the callbacks. Now, there is just one callback which is the same for all three modes
69308  (playback, capture, duplex). The new callback looks like the following:
69309 
69310  void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
69311 
69312  This callback allows you to move data straight out of the input buffer and into the output buffer in full-duplex mode. In playback-only mode, pInput will be
69313  null. Likewise, pOutput will be null in capture-only mode. The sample count is no longer returned from the callback since it's not necessary for miniaudio
69314  anymore.
69315 
69316 2) The device config needed to change in order to support full-duplex. Full-duplex requires the ability to allow the client to choose a different PCM format
69317  for the playback and capture sides. The old ma_device_config object simply did not allow this and needed to change. With these changes you now specify the
69318  device ID, format, channels, channel map and share mode on a per-playback and per-capture basis (see example below). The sample rate must be the same for
69319  playback and capture.
69320 
69321  Since the device config API has changed I have also decided to take the opportunity to simplify device initialization. Now, the device ID, device type and
69322  callback user data are set in the config. ma_device_init() is now simplified down to taking just the context, device config and a pointer to the device
69323  object being initialized. The rationale for this change is that it just makes more sense to me that these are set as part of the config like everything
69324  else.
69325 
69326  Example device initialization:
69327 
69328  ma_device_config config = ma_device_config_init(ma_device_type_duplex); // Or ma_device_type_playback or ma_device_type_capture.
69329  config.playback.pDeviceID = &myPlaybackDeviceID; // Or NULL for the default playback device.
69330  config.playback.format = ma_format_f32;
69331  config.playback.channels = 2;
69332  config.capture.pDeviceID = &myCaptureDeviceID; // Or NULL for the default capture device.
69333  config.capture.format = ma_format_s16;
69334  config.capture.channels = 1;
69335  config.sampleRate = 44100;
69336  config.dataCallback = data_callback;
69337  config.pUserData = &myUserData;
69338 
69339  result = ma_device_init(&myContext, &config, &device);
69340  if (result != MA_SUCCESS) {
69341  ... handle error ...
69342  }
69343 
69344  Note that the "onDataCallback" member of ma_device_config has been renamed to "dataCallback". Also, "onStopCallback" has been renamed to "stopCallback".
69345 
69346 This is the first pass for full-duplex and there is a known bug. You will hear crackling on the following backends when sample rate conversion is required for
69347 the playback device:
69348  - Core Audio
69349  - JACK
69350  - AAudio
69351  - OpenSL
69352  - WebAudio
69353 
69354 In addition to the above, not all platforms have been absolutely thoroughly tested simply because I lack the hardware for such thorough testing. If you
69355 experience a bug, an issue report on GitHub or an email would be greatly appreciated (and a sample program that reproduces the issue if possible).
69356 
69357 
69358 Other API Changes
69359 -----------------
69360 In addition to the above, the following API changes have been made:
69361 
69362 - The log callback is no longer passed to ma_context_config_init(). Instead you need to set it manually after initialization.
69363 - The onLogCallback member of ma_context_config has been renamed to "logCallback".
69364 - The log callback now takes a logLevel parameter. The new callback looks like: void log_callback(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message)
69365  - You can use ma_log_level_to_string() to convert the logLevel to human readable text if you want to log it.
69366 - Some APIs have been renamed:
69367  - mal_decoder_read() -> ma_decoder_read_pcm_frames()
69368  - mal_decoder_seek_to_frame() -> ma_decoder_seek_to_pcm_frame()
69369  - mal_sine_wave_read() -> ma_sine_wave_read_f32()
69370  - mal_sine_wave_read_ex() -> ma_sine_wave_read_f32_ex()
69371 - Some APIs have been removed:
69372  - mal_device_get_buffer_size_in_bytes()
69373  - mal_device_set_recv_callback()
69374  - mal_device_set_send_callback()
69375  - mal_src_set_input_sample_rate()
69376  - mal_src_set_output_sample_rate()
69377 - Error codes have been rearranged. If you're a binding maintainer you will need to update.
69378 - The ma_backend enums have been rearranged to priority order. The rationale for this is to simplify automatic backend selection and to make it easier to see
69379  the priority. If you're a binding maintainer you will need to update.
69380 - ma_dsp has been renamed to ma_pcm_converter. The rationale for this change is that I'm expecting "ma_dsp" to conflict with some future planned high-level
69381  APIs.
69382 - For functions that take a pointer/count combo, such as ma_decoder_read_pcm_frames(), the parameter order has changed so that the pointer comes before the
69383  count. The rationale for this is to keep it consistent with things like memcpy().
69384 
69385 
69386 Miscellaneous Changes
69387 ---------------------
69388 The following miscellaneous changes have also been made.
69389 
69390 - The AAudio backend has been added for Android 8 and above. This is Android's new "High-Performance Audio" API. (For the record, this is one of the nicest
69391  audio APIs out there, just behind the BSD audio APIs).
69392 - The WebAudio backend has been added. This is based on ScriptProcessorNode. This removes the need for SDL.
69393 - The SDL and OpenAL backends have been removed. These were originally implemented to add support for platforms for which miniaudio was not explicitly
69394  supported. These are no longer needed and have therefore been removed.
69395 - Device initialization now fails if the requested share mode is not supported. If you ask for exclusive mode, you either get an exclusive mode device, or an
69396  error. The rationale for this change is to give the client more control over how to handle cases when the desired shared mode is unavailable.
69397 - A lock-free ring buffer API has been added. There are two varients of this. "ma_rb" operates on bytes, whereas "ma_pcm_rb" operates on PCM frames.
69398 - The library is now licensed as a choice of Public Domain (Unlicense) _or_ MIT-0 (No Attribution) which is the same as MIT, but removes the attribution
69399  requirement. The rationale for this is to support countries that don't recognize public domain.
69400 */
69401 
69402 /*
69403 REVISION HISTORY
69404 ================
69405 v0.10.41 - 2021-08-15
69406  - Core Audio: Fix some deadlock errors.
69407 
69408 v0.10.40 - 2021-07-23
69409  - Fix a bug when converting from stereo to mono.
69410  - PulseAudio: Fix a glitch when pausing and resuming a device.
69411 
69412 v0.10.39 - 2021-07-20
69413  - Core Audio: Fix a deadlock when the default device is changed.
69414  - Core Audio: Fix compilation errors on macOS and iOS.
69415  - PulseAudio: Fix a bug where the stop callback is not fired when a device is unplugged.
69416  - PulseAudio: Fix a null pointer dereference.
69417 
69418 v0.10.38 - 2021-07-14
69419  - Fix a linking error when MA_DEBUG_OUTPUT is not enabled.
69420  - Fix an error where ma_log_postv() does not return a value.
69421  - OpenSL: Fix a bug with setting of stream types and recording presets.
69422 
69423 0.10.37 - 2021-07-06
69424  - Fix a bug with log message formatting.
69425  - Fix build when compiling with MA_NO_THREADING.
69426  - Minor updates to channel mapping.
69427 
69428 0.10.36 - 2021-07-03
69429  - Add support for custom decoding backends.
69430  - Fix some bugs with the Vorbis decoder.
69431  - PulseAudio: Fix a bug with channel mapping.
69432  - PulseAudio: Fix a bug where miniaudio does not fall back to a supported format when PulseAudio
69433  defaults to a format not known to miniaudio.
69434  - OpenSL: Fix a crash when initializing a capture device when a recording preset other than the
69435  default is specified.
69436  - Silence some warnings when compiling with MA_DEBUG_OUTPUT
69437  - Improvements to logging. See the `ma_log` API for details. The logCallback variable used by
69438  ma_context has been deprecated and will be replaced with the new system in version 0.11.
69439  - Initialize an `ma_log` object with `ma_log_init()`.
69440  - Register a callback with `ma_log_register_callback()`.
69441  - In the context config, set `pLog` to your `ma_log` object and stop using `logCallback`.
69442  - Prep work for some upcoming changes to data sources. These changes are still compatible with
69443  existing code, however code will need to be updated in preparation for version 0.11 which will
69444  be breaking. You should make these changes now for any custom data sources:
69445  - Change your base data source object from `ma_data_source_callbacks` to `ma_data_source_base`.
69446  - Call `ma_data_source_init()` for your base object in your custom data source's initialization
69447  routine. This takes a config object which includes a pointer to a vtable which is now where
69448  your custom callbacks are defined.
69449  - Call `ma_data_source_uninit()` in your custom data source's uninitialization routine. This
69450  doesn't currently do anything, but it placeholder in case some future uninitialization code
69451  is required to be added at a later date.
69452 
69453 v0.10.35 - 2021-04-27
69454  - Fix the C++ build.
69455 
69456 v0.10.34 - 2021-04-26
69457  - WASAPI: Fix a bug where a result code is not getting checked at initialization time.
69458  - WASAPI: Bug fixes for loopback mode.
69459  - ALSA: Fix a possible deadlock when stopping devices.
69460  - Mark devices as default on the null backend.
69461 
69462 v0.10.33 - 2021-04-04
69463  - Core Audio: Fix a memory leak.
69464  - Core Audio: Fix a bug where the performance profile is not being used by playback devices.
69465  - JACK: Fix loading of 64-bit JACK on Windows.
69466  - Fix a calculation error and add a safety check to the following APIs to prevent a division by zero:
69467  - ma_calculate_buffer_size_in_milliseconds_from_frames()
69468  - ma_calculate_buffer_size_in_frames_from_milliseconds()
69469  - Fix compilation errors relating to c89atomic.
69470  - Update FLAC decoder.
69471 
69472 v0.10.32 - 2021-02-23
69473  - WASAPI: Fix a deadlock in exclusive mode.
69474  - WASAPI: No longer return an error from ma_context_get_device_info() when an exclusive mode format
69475  cannot be retrieved.
69476  - WASAPI: Attempt to fix some bugs with device uninitialization.
69477  - PulseAudio: Yet another refactor, this time to remove the dependency on `pa_threaded_mainloop`.
69478  - Web Audio: Fix a bug on Chrome and any other browser using the same engine.
69479  - Web Audio: Automatically start the device on some user input if the device has been started. This
69480  is to work around Google's policy of not starting audio if no user input has yet been performed.
69481  - Fix a bug where thread handles are not being freed.
69482  - Fix some static analysis warnings in FLAC, WAV and MP3 decoders.
69483  - Fix a warning due to referencing _MSC_VER when it is undefined.
69484  - Update to latest version of c89atomic.
69485  - Internal refactoring to migrate over to the new backend callback system for the following backends:
69486  - PulseAudio
69487  - ALSA
69488  - Core Audio
69489  - AAudio
69490  - OpenSL|ES
69491  - OSS
69492  - audio(4)
69493  - sndio
69494 
69495 v0.10.31 - 2021-01-17
69496  - Make some functions const correct.
69497  - Update ma_data_source_read_pcm_frames() to initialize pFramesRead to 0 for safety.
69498  - Add the MA_ATOMIC annotation for use with variables that should be used atomically and remove unnecessary volatile qualifiers.
69499  - Add support for enabling only specific backends at compile time. This is the reverse of the pre-existing system. With the new
69500  system, all backends are first disabled with `MA_ENABLE_ONLY_SPECIFIC_BACKENDS`, which is then followed with `MA_ENABLE_*`. The
69501  old system where you disable backends with `MA_NO_*` still exists and is still the default.
69502 
69503 v0.10.30 - 2021-01-10
69504  - Fix a crash in ma_audio_buffer_read_pcm_frames().
69505  - Update spinlock APIs to take a volatile parameter as input.
69506  - Silence some unused parameter warnings.
69507  - Fix a warning on GCC when compiling as C++.
69508 
69509 v0.10.29 - 2020-12-26
69510  - Fix some subtle multi-threading bugs on non-x86 platforms.
69511  - Fix a bug resulting in superfluous memory allocations when enumerating devices.
69512  - Core Audio: Fix a compilation error when compiling for iOS.
69513 
69514 v0.10.28 - 2020-12-16
69515  - Fix a crash when initializing a POSIX thread.
69516  - OpenSL|ES: Respect the MA_NO_RUNTIME_LINKING option.
69517 
69518 v0.10.27 - 2020-12-04
69519  - Add support for dynamically configuring some properties of `ma_noise` objects post-initialization.
69520  - Add support for configuring the channel mixing mode in the device config.
69521  - Fix a bug with simple channel mixing mode (drop or silence excess channels).
69522  - Fix some bugs with trying to access uninitialized variables.
69523  - Fix some errors with stopping devices for synchronous backends where the backend's stop callback would get fired twice.
69524  - Fix a bug in the decoder due to using an uninitialized variable.
69525  - Fix some data race errors.
69526 
69527 v0.10.26 - 2020-11-24
69528  - WASAPI: Fix a bug where the exclusive mode format may not be retrieved correctly due to accessing freed memory.
69529  - Fix a bug with ma_waveform where glitching occurs after changing frequency.
69530  - Fix compilation with OpenWatcom.
69531  - Fix compilation with TCC.
69532  - Fix compilation with Digital Mars.
69533  - Fix compilation warnings.
69534  - Remove bitfields from public structures to aid in binding maintenance.
69535 
69536 v0.10.25 - 2020-11-15
69537  - PulseAudio: Fix a bug where the stop callback isn't fired.
69538  - WebAudio: Fix an error that occurs when Emscripten increases the size of it's heap.
69539  - Custom Backends: Change the onContextInit and onDeviceInit callbacks to take a parameter which is a pointer to the config that was
69540  passed into ma_context_init() and ma_device_init(). This replaces the deviceType parameter of onDeviceInit.
69541  - Fix compilation warnings on older versions of GCC.
69542 
69543 v0.10.24 - 2020-11-10
69544  - Fix a bug where initialization of a backend can fail due to some bad state being set from a prior failed attempt at initializing a
69545  lower priority backend.
69546 
69547 v0.10.23 - 2020-11-09
69548  - AAudio: Add support for configuring a playback stream's usage.
69549  - Fix a compilation error when all built-in asynchronous backends are disabled at compile time.
69550  - Fix compilation errors when compiling as C++.
69551 
69552 v0.10.22 - 2020-11-08
69553  - Add support for custom backends.
69554  - Add support for detecting default devices during device enumeration and with `ma_context_get_device_info()`.
69555  - Refactor to the PulseAudio backend. This simplifies the implementation and fixes a capture bug.
69556  - ALSA: Fix a bug in `ma_context_get_device_info()` where the PCM handle is left open in the event of an error.
69557  - Core Audio: Further improvements to sample rate selection.
69558  - Core Audio: Fix some bugs with capture mode.
69559  - OpenSL: Add support for configuring stream types and recording presets.
69560  - AAudio: Add support for configuring content types and input presets.
69561  - Fix bugs in `ma_decoder_init_file*()` where the file handle is not closed after a decoding error.
69562  - Fix some compilation warnings on GCC and Clang relating to the Speex resampler.
69563  - Fix a compilation error for the Linux build when the ALSA and JACK backends are both disabled.
69564  - Fix a compilation error for the BSD build.
69565  - Fix some compilation errors on older versions of GCC.
69566  - Add documentation for `MA_NO_RUNTIME_LINKING`.
69567 
69568 v0.10.21 - 2020-10-30
69569  - Add ma_is_backend_enabled() and ma_get_enabled_backends() for retrieving enabled backends at run-time.
69570  - WASAPI: Fix a copy and paste bug relating to loopback mode.
69571  - Core Audio: Fix a bug when using multiple contexts.
69572  - Core Audio: Fix a compilation warning.
69573  - Core Audio: Improvements to sample rate selection.
69574  - Core Audio: Improvements to format/channels/rate selection when requesting defaults.
69575  - Core Audio: Add notes regarding the Apple notarization process.
69576  - Fix some bugs due to null pointer dereferences.
69577 
69578 v0.10.20 - 2020-10-06
69579  - Fix build errors with UWP.
69580  - Minor documentation updates.
69581 
69582 v0.10.19 - 2020-09-22
69583  - WASAPI: Return an error when exclusive mode is requested, but the native format is not supported by miniaudio.
69584  - Fix a bug where ma_decoder_seek_to_pcm_frames() never returns MA_SUCCESS even though it was successful.
69585  - Store the sample rate in the `ma_lpf` and `ma_hpf` structures.
69586 
69587 v0.10.18 - 2020-08-30
69588  - Fix build errors with VC6.
69589  - Fix a bug in channel converter for s32 format.
69590  - Change channel converter configs to use the default channel map instead of a blank channel map when no channel map is specified when initializing the
69591  config. This fixes an issue where the optimized mono expansion path would never get used.
69592  - Use a more appropriate default format for FLAC decoders. This will now use ma_format_s16 when the FLAC is encoded as 16-bit.
69593  - Update FLAC decoder.
69594  - Update links to point to the new repository location (https://github.com/mackron/miniaudio).
69595 
69596 v0.10.17 - 2020-08-28
69597  - Fix an error where the WAV codec is incorrectly excluded from the build depending on which compile time options are set.
69598  - Fix a bug in ma_audio_buffer_read_pcm_frames() where it isn't returning the correct number of frames processed.
69599  - Fix compilation error on Android.
69600  - Core Audio: Fix a bug with full-duplex mode.
69601  - Add ma_decoder_get_cursor_in_pcm_frames().
69602  - Update WAV codec.
69603 
69604 v0.10.16 - 2020-08-14
69605  - WASAPI: Fix a potential crash due to using an uninitialized variable.
69606  - OpenSL: Enable runtime linking.
69607  - OpenSL: Fix a multithreading bug when initializing and uninitializing multiple contexts at the same time.
69608  - iOS: Improvements to device enumeration.
69609  - Fix a crash in ma_data_source_read_pcm_frames() when the output frame count parameter is NULL.
69610  - Fix a bug in ma_data_source_read_pcm_frames() where looping doesn't work.
69611  - Fix some compilation warnings on Windows when both DirectSound and WinMM are disabled.
69612  - Fix some compilation warnings when no decoders are enabled.
69613  - Add ma_audio_buffer_get_available_frames().
69614  - Add ma_decoder_get_available_frames().
69615  - Add sample rate to ma_data_source_get_data_format().
69616  - Change volume APIs to take 64-bit frame counts.
69617  - Updates to documentation.
69618 
69619 v0.10.15 - 2020-07-15
69620  - Fix a bug when converting bit-masked channel maps to miniaudio channel maps. This affects the WASAPI and OpenSL backends.
69621 
69622 v0.10.14 - 2020-07-14
69623  - Fix compilation errors on Android.
69624  - Fix compilation errors with -march=armv6.
69625  - Updates to the documentation.
69626 
69627 v0.10.13 - 2020-07-11
69628  - Fix some potential buffer overflow errors with channel maps when channel counts are greater than MA_MAX_CHANNELS.
69629  - Fix compilation error on Emscripten.
69630  - Silence some unused function warnings.
69631  - Increase the default buffer size on the Web Audio backend. This fixes glitching issues on some browsers.
69632  - Bring FLAC decoder up-to-date with dr_flac.
69633  - Bring MP3 decoder up-to-date with dr_mp3.
69634 
69635 v0.10.12 - 2020-07-04
69636  - Fix compilation errors on the iOS build.
69637 
69638 v0.10.11 - 2020-06-28
69639  - Fix some bugs with device tracking on Core Audio.
69640  - Updates to documentation.
69641 
69642 v0.10.10 - 2020-06-26
69643  - Add include guard for the implementation section.
69644  - Mark ma_device_sink_info_callback() as static.
69645  - Fix compilation errors with MA_NO_DECODING and MA_NO_ENCODING.
69646  - Fix compilation errors with MA_NO_DEVICE_IO
69647 
69648 v0.10.9 - 2020-06-24
69649  - Amalgamation of dr_wav, dr_flac and dr_mp3. With this change, including the header section of these libraries before the implementation of miniaudio is no
69650  longer required. Decoding of WAV, FLAC and MP3 should be supported seamlessly without any additional libraries. Decoders can be excluded from the build
69651  with the following options:
69652  - MA_NO_WAV
69653  - MA_NO_FLAC
69654  - MA_NO_MP3
69655  If you get errors about multiple definitions you need to either enable the options above, move the implementation of dr_wav, dr_flac and/or dr_mp3 to before
69656  the implementation of miniaudio, or update dr_wav, dr_flac and/or dr_mp3.
69657  - Changes to the internal atomics library. This has been replaced with c89atomic.h which is embedded within this file.
69658  - Fix a bug when a decoding backend reports configurations outside the limits of miniaudio's decoder abstraction.
69659  - Fix the UWP build.
69660  - Fix the Core Audio build.
69661  - Fix the -std=c89 build on GCC.
69662 
69663 v0.10.8 - 2020-06-22
69664  - Remove dependency on ma_context from mutexes.
69665  - Change ma_data_source_read_pcm_frames() to return a result code and output the frames read as an output parameter.
69666  - Change ma_data_source_seek_pcm_frames() to return a result code and output the frames seeked as an output parameter.
69667  - Change ma_audio_buffer_unmap() to return MA_AT_END when the end has been reached. This should be considered successful.
69668  - Change playback.pDeviceID and capture.pDeviceID to constant pointers in ma_device_config.
69669  - Add support for initializing decoders from a virtual file system object. This is achieved via the ma_vfs API and allows the application to customize file
69670  IO for the loading and reading of raw audio data. Passing in NULL for the VFS will use defaults. New APIs:
69671  - ma_decoder_init_vfs()
69672  - ma_decoder_init_vfs_wav()
69673  - ma_decoder_init_vfs_flac()
69674  - ma_decoder_init_vfs_mp3()
69675  - ma_decoder_init_vfs_vorbis()
69676  - ma_decoder_init_vfs_w()
69677  - ma_decoder_init_vfs_wav_w()
69678  - ma_decoder_init_vfs_flac_w()
69679  - ma_decoder_init_vfs_mp3_w()
69680  - ma_decoder_init_vfs_vorbis_w()
69681  - Add support for memory mapping to ma_data_source.
69682  - ma_data_source_map()
69683  - ma_data_source_unmap()
69684  - Add ma_offset_pcm_frames_ptr() and ma_offset_pcm_frames_const_ptr() which can be used for offsetting a pointer by a specified number of PCM frames.
69685  - Add initial implementation of ma_yield() which is useful for spin locks which will be used in some upcoming work.
69686  - Add documentation for log levels.
69687  - The ma_event API has been made public in preparation for some uncoming work.
69688  - Fix a bug in ma_decoder_seek_to_pcm_frame() where the internal sample rate is not being taken into account for determining the seek location.
69689  - Fix some bugs with the linear resampler when dynamically changing the sample rate.
69690  - Fix compilation errors with MA_NO_DEVICE_IO.
69691  - Fix some warnings with GCC and -std=c89.
69692  - Fix some formatting warnings with GCC and -Wall and -Wpedantic.
69693  - Fix some warnings with VC6.
69694  - Minor optimization to ma_copy_pcm_frames(). This is now a no-op when the input and output buffers are the same.
69695 
69696 v0.10.7 - 2020-05-25
69697  - Fix a compilation error in the C++ build.
69698  - Silence a warning.
69699 
69700 v0.10.6 - 2020-05-24
69701  - Change ma_clip_samples_f32() and ma_clip_pcm_frames_f32() to take a 64-bit sample/frame count.
69702  - Change ma_zero_pcm_frames() to clear to 128 for ma_format_u8.
69703  - Add ma_silence_pcm_frames() which replaces ma_zero_pcm_frames(). ma_zero_pcm_frames() will be removed in version 0.11.
69704  - Add support for u8, s24 and s32 formats to ma_channel_converter.
69705  - Add compile-time and run-time version querying.
69706  - MA_VERSION_MINOR
69707  - MA_VERSION_MAJOR
69708  - MA_VERSION_REVISION
69709  - MA_VERSION_STRING
69710  - ma_version()
69711  - ma_version_string()
69712  - Add ma_audio_buffer for reading raw audio data directly from memory.
69713  - Fix a bug in shuffle mode in ma_channel_converter.
69714  - Fix compilation errors in certain configurations for ALSA and PulseAudio.
69715  - The data callback now initializes the output buffer to 128 when the playback sample format is ma_format_u8.
69716 
69717 v0.10.5 - 2020-05-05
69718  - Change ma_zero_pcm_frames() to take a 64-bit frame count.
69719  - Add ma_copy_pcm_frames().
69720  - Add MA_NO_GENERATION build option to exclude the `ma_waveform` and `ma_noise` APIs from the build.
69721  - Add support for formatted logging to the VC6 build.
69722  - Fix a crash in the linear resampler when LPF order is 0.
69723  - Fix compilation errors and warnings with older versions of Visual Studio.
69724  - Minor documentation updates.
69725 
69726 v0.10.4 - 2020-04-12
69727  - Fix a data conversion bug when converting from the client format to the native device format.
69728 
69729 v0.10.3 - 2020-04-07
69730  - Bring up to date with breaking changes to dr_mp3.
69731  - Remove MA_NO_STDIO. This was causing compilation errors and the maintenance cost versus practical benefit is no longer worthwhile.
69732  - Fix a bug with data conversion where it was unnecessarily converting to s16 or f32 and then straight back to the original format.
69733  - Fix compilation errors and warnings with Visual Studio 2005.
69734  - ALSA: Disable ALSA's automatic data conversion by default and add configuration options to the device config:
69735  - alsa.noAutoFormat
69736  - alsa.noAutoChannels
69737  - alsa.noAutoResample
69738  - WASAPI: Add some overrun recovery for ma_device_type_capture devices.
69739 
69740 v0.10.2 - 2020-03-22
69741  - Decorate some APIs with MA_API which were missed in the previous version.
69742  - Fix a bug in ma_linear_resampler_set_rate() and ma_linear_resampler_set_rate_ratio().
69743 
69744 v0.10.1 - 2020-03-17
69745  - Add MA_API decoration. This can be customized by defining it before including miniaudio.h.
69746  - Fix a bug where opening a file would return a success code when in fact it failed.
69747  - Fix compilation errors with Visual Studio 6 and 2003.
69748  - Fix warnings on macOS.
69749 
69750 v0.10.0 - 2020-03-07
69751  - API CHANGE: Refactor data conversion APIs
69752  - ma_format_converter has been removed. Use ma_convert_pcm_frames_format() instead.
69753  - ma_channel_router has been replaced with ma_channel_converter.
69754  - ma_src has been replaced with ma_resampler
69755  - ma_pcm_converter has been replaced with ma_data_converter
69756  - API CHANGE: Add support for custom memory allocation callbacks. The following APIs have been updated to take an extra parameter for the allocation
69757  callbacks:
69758  - ma_malloc()
69759  - ma_realloc()
69760  - ma_free()
69761  - ma_aligned_malloc()
69762  - ma_aligned_free()
69763  - ma_rb_init() / ma_rb_init_ex()
69764  - ma_pcm_rb_init() / ma_pcm_rb_init_ex()
69765  - API CHANGE: Simplify latency specification in device configurations. The bufferSizeInFrames and bufferSizeInMilliseconds parameters have been replaced with
69766  periodSizeInFrames and periodSizeInMilliseconds respectively. The previous variables defined the size of the entire buffer, whereas the new ones define the
69767  size of a period. The following APIs have been removed since they are no longer relevant:
69768  - ma_get_default_buffer_size_in_milliseconds()
69769  - ma_get_default_buffer_size_in_frames()
69770  - API CHANGE: ma_device_set_stop_callback() has been removed. If you require a stop callback, you must now set it via the device config just like the data
69771  callback.
69772  - API CHANGE: The ma_sine_wave API has been replaced with ma_waveform. The following APIs have been removed:
69773  - ma_sine_wave_init()
69774  - ma_sine_wave_read_f32()
69775  - ma_sine_wave_read_f32_ex()
69776  - API CHANGE: ma_convert_frames() has been updated to take an extra parameter which is the size of the output buffer in PCM frames. Parameters have also been
69777  reordered.
69778  - API CHANGE: ma_convert_frames_ex() has been changed to take a pointer to a ma_data_converter_config object to specify the input and output formats to
69779  convert between.
69780  - API CHANGE: ma_calculate_frame_count_after_src() has been renamed to ma_calculate_frame_count_after_resampling().
69781  - Add support for the following filters:
69782  - Biquad (ma_biquad)
69783  - First order low-pass (ma_lpf1)
69784  - Second order low-pass (ma_lpf2)
69785  - Low-pass with configurable order (ma_lpf)
69786  - First order high-pass (ma_hpf1)
69787  - Second order high-pass (ma_hpf2)
69788  - High-pass with configurable order (ma_hpf)
69789  - Second order band-pass (ma_bpf2)
69790  - Band-pass with configurable order (ma_bpf)
69791  - Second order peaking EQ (ma_peak2)
69792  - Second order notching (ma_notch2)
69793  - Second order low shelf (ma_loshelf2)
69794  - Second order high shelf (ma_hishelf2)
69795  - Add waveform generation API (ma_waveform) with support for the following:
69796  - Sine
69797  - Square
69798  - Triangle
69799  - Sawtooth
69800  - Add noise generation API (ma_noise) with support for the following:
69801  - White
69802  - Pink
69803  - Brownian
69804  - Add encoding API (ma_encoder). This only supports outputting to WAV files via dr_wav.
69805  - Add ma_result_description() which is used to retrieve a human readable description of a given result code.
69806  - Result codes have been changed. Binding maintainers will need to update their result code constants.
69807  - More meaningful result codes are now returned when a file fails to open.
69808  - Internal functions have all been made static where possible.
69809  - Fix potential crash when ma_device object's are not aligned to MA_SIMD_ALIGNMENT.
69810  - Fix a bug in ma_decoder_get_length_in_pcm_frames() where it was returning the length based on the internal sample rate rather than the output sample rate.
69811  - Fix bugs in some backends where the device is not drained properly in ma_device_stop().
69812  - Improvements to documentation.
69813 
69814 v0.9.10 - 2020-01-15
69815  - Fix compilation errors due to #if/#endif mismatches.
69816  - WASAPI: Fix a bug where automatic stream routing is being performed for devices that are initialized with an explicit device ID.
69817  - iOS: Fix a crash on device uninitialization.
69818 
69819 v0.9.9 - 2020-01-09
69820  - Fix compilation errors with MinGW.
69821  - Fix compilation errors when compiling on Apple platforms.
69822  - WASAPI: Add support for disabling hardware offloading.
69823  - WASAPI: Add support for disabling automatic stream routing.
69824  - Core Audio: Fix bugs in the case where the internal device uses deinterleaved buffers.
69825  - Core Audio: Add support for controlling the session category (AVAudioSessionCategory) and options (AVAudioSessionCategoryOptions).
69826  - JACK: Fix bug where incorrect ports are connected.
69827 
69828 v0.9.8 - 2019-10-07
69829  - WASAPI: Fix a potential deadlock when starting a full-duplex device.
69830  - WASAPI: Enable automatic resampling by default. Disable with config.wasapi.noAutoConvertSRC.
69831  - Core Audio: Fix bugs with automatic stream routing.
69832  - Add support for controlling whether or not the content of the output buffer passed in to the data callback is pre-initialized
69833  to zero. By default it will be initialized to zero, but this can be changed by setting noPreZeroedOutputBuffer in the device
69834  config. Setting noPreZeroedOutputBuffer to true will leave the contents undefined.
69835  - Add support for clipping samples after the data callback has returned. This only applies when the playback sample format is
69836  configured as ma_format_f32. If you are doing clipping yourself, you can disable this overhead by setting noClip to true in
69837  the device config.
69838  - Add support for master volume control for devices.
69839  - Use ma_device_set_master_volume() to set the volume to a factor between 0 and 1, where 0 is silence and 1 is full volume.
69840  - Use ma_device_set_master_gain_db() to set the volume in decibels where 0 is full volume and < 0 reduces the volume.
69841  - Fix warnings emitted by GCC when `__inline__` is undefined or defined as nothing.
69842 
69843 v0.9.7 - 2019-08-28
69844  - Add support for loopback mode (WASAPI only).
69845  - To use this, set the device type to ma_device_type_loopback, and then fill out the capture section of the device config.
69846  - If you need to capture from a specific output device, set the capture device ID to that of a playback device.
69847  - Fix a crash when an error is posted in ma_device_init().
69848  - Fix a compilation error when compiling for ARM architectures.
69849  - Fix a bug with the audio(4) backend where the device is incorrectly being opened in non-blocking mode.
69850  - Fix memory leaks in the Core Audio backend.
69851  - Minor refactoring to the WinMM, ALSA, PulseAudio, OSS, audio(4), sndio and null backends.
69852 
69853 v0.9.6 - 2019-08-04
69854  - Add support for loading decoders using a wchar_t string for file paths.
69855  - Don't trigger an assert when ma_device_start() is called on a device that is already started. This will now log a warning
69856  and return MA_INVALID_OPERATION. The same applies for ma_device_stop().
69857  - Try fixing an issue with PulseAudio taking a long time to start playback.
69858  - Fix a bug in ma_convert_frames() and ma_convert_frames_ex().
69859  - Fix memory leaks in the WASAPI backend.
69860  - Fix a compilation error with Visual Studio 2010.
69861 
69862 v0.9.5 - 2019-05-21
69863  - Add logging to ma_dlopen() and ma_dlsym().
69864  - Add ma_decoder_get_length_in_pcm_frames().
69865  - Fix a bug with capture on the OpenSL|ES backend.
69866  - Fix a bug with the ALSA backend where a device would not restart after being stopped.
69867 
69868 v0.9.4 - 2019-05-06
69869  - Add support for C89. With this change, miniaudio should compile clean with GCC/Clang with "-std=c89 -ansi -pedantic" and
69870  Microsoft compilers back to VC6. Other compilers should also work, but have not been tested.
69871 
69872 v0.9.3 - 2019-04-19
69873  - Fix compiler errors on GCC when compiling with -std=c99.
69874 
69875 v0.9.2 - 2019-04-08
69876  - Add support for per-context user data.
69877  - Fix a potential bug with context configs.
69878  - Fix some bugs with PulseAudio.
69879 
69880 v0.9.1 - 2019-03-17
69881  - Fix a bug where the output buffer is not getting zeroed out before calling the data callback. This happens when
69882  the device is running in passthrough mode (not doing any data conversion).
69883  - Fix an issue where the data callback is getting called too frequently on the WASAPI and DirectSound backends.
69884  - Fix error on the UWP build.
69885  - Fix a build error on Apple platforms.
69886 
69887 v0.9 - 2019-03-06
69888  - Rebranded to "miniaudio". All namespaces have been renamed from "mal" to "ma".
69889  - API CHANGE: ma_device_init() and ma_device_config_init() have changed significantly:
69890  - The device type, device ID and user data pointer have moved from ma_device_init() to the config.
69891  - All variations of ma_device_config_init_*() have been removed in favor of just ma_device_config_init().
69892  - ma_device_config_init() now takes only one parameter which is the device type. All other properties need
69893  to be set on the returned object directly.
69894  - The onDataCallback and onStopCallback members of ma_device_config have been renamed to "dataCallback"
69895  and "stopCallback".
69896  - The ID of the physical device is now split into two: one for the playback device and the other for the
69897  capture device. This is required for full-duplex. These are named "pPlaybackDeviceID" and "pCaptureDeviceID".
69898  - API CHANGE: The data callback has changed. It now uses a unified callback for all device types rather than
69899  being separate for each. It now takes two pointers - one containing input data and the other output data. This
69900  design in required for full-duplex. The return value is now void instead of the number of frames written. The
69901  new callback looks like the following:
69902  void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
69903  - API CHANGE: Remove the log callback parameter from ma_context_config_init(). With this change,
69904  ma_context_config_init() now takes no parameters and the log callback is set via the structure directly. The
69905  new policy for config initialization is that only mandatory settings are passed in to *_config_init(). The
69906  "onLog" member of ma_context_config has been renamed to "logCallback".
69907  - API CHANGE: Remove ma_device_get_buffer_size_in_bytes().
69908  - API CHANGE: Rename decoding APIs to "pcm_frames" convention.
69909  - mal_decoder_read() -> ma_decoder_read_pcm_frames()
69910  - mal_decoder_seek_to_frame() -> ma_decoder_seek_to_pcm_frame()
69911  - API CHANGE: Rename sine wave reading APIs to f32 convention.
69912  - mal_sine_wave_read() -> ma_sine_wave_read_f32()
69913  - mal_sine_wave_read_ex() -> ma_sine_wave_read_f32_ex()
69914  - API CHANGE: Remove some deprecated APIs
69915  - mal_device_set_recv_callback()
69916  - mal_device_set_send_callback()
69917  - mal_src_set_input_sample_rate()
69918  - mal_src_set_output_sample_rate()
69919  - API CHANGE: Add log level to the log callback. New signature:
69920  - void on_log(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message)
69921  - API CHANGE: Changes to result codes. Constants have changed and unused codes have been removed. If you're
69922  a binding mainainer you will need to update your result code constants.
69923  - API CHANGE: Change the order of the ma_backend enums to priority order. If you are a binding maintainer, you
69924  will need to update.
69925  - API CHANGE: Rename mal_dsp to ma_pcm_converter. All functions have been renamed from mal_dsp_*() to
69926  ma_pcm_converter_*(). All structures have been renamed from mal_dsp* to ma_pcm_converter*.
69927  - API CHANGE: Reorder parameters of ma_decoder_read_pcm_frames() to be consistent with the new parameter order scheme.
69928  - The resampling algorithm has been changed from sinc to linear. The rationale for this is that the sinc implementation
69929  is too inefficient right now. This will hopefully be improved at a later date.
69930  - Device initialization will no longer fall back to shared mode if exclusive mode is requested but is unusable.
69931  With this change, if you request an device in exclusive mode, but exclusive mode is not supported, it will not
69932  automatically fall back to shared mode. The client will need to reinitialize the device in shared mode if that's
69933  what they want.
69934  - Add ring buffer API. This is ma_rb and ma_pcm_rb, the difference being that ma_rb operates on bytes and
69935  ma_pcm_rb operates on PCM frames.
69936  - Add Web Audio backend. This is used when compiling with Emscripten. The SDL backend, which was previously
69937  used for web support, will be removed in a future version.
69938  - Add AAudio backend (Android Audio). This is the new priority backend for Android. Support for AAudio starts
69939  with Android 8. OpenSL|ES is used as a fallback for older versions of Android.
69940  - Remove OpenAL and SDL backends.
69941  - Fix a possible deadlock when rapidly stopping the device after it has started.
69942  - Update documentation.
69943  - Change licensing to a choice of public domain _or_ MIT-0 (No Attribution).
69944 
69945 v0.8.14 - 2018-12-16
69946  - Core Audio: Fix a bug where the device state is not set correctly after stopping.
69947  - Add support for custom weights to the channel router.
69948  - Update decoders to use updated APIs in dr_flac, dr_mp3 and dr_wav.
69949 
69950 v0.8.13 - 2018-12-04
69951  - Core Audio: Fix a bug with channel mapping.
69952  - Fix a bug with channel routing where the back/left and back/right channels have the wrong weight.
69953 
69954 v0.8.12 - 2018-11-27
69955  - Drop support for SDL 1.2. The Emscripten build now requires "-s USE_SDL=2".
69956  - Fix a linking error with ALSA.
69957  - Fix a bug on iOS where the device name is not set correctly.
69958 
69959 v0.8.11 - 2018-11-21
69960  - iOS bug fixes.
69961  - Minor tweaks to PulseAudio.
69962 
69963 v0.8.10 - 2018-10-21
69964  - Core Audio: Fix a hang when uninitializing a device.
69965  - Fix a bug where an incorrect value is returned from mal_device_stop().
69966 
69967 v0.8.9 - 2018-09-28
69968  - Fix a bug with the SDL backend where device initialization fails.
69969 
69970 v0.8.8 - 2018-09-14
69971  - Fix Linux build with the ALSA backend.
69972  - Minor documentation fix.
69973 
69974 v0.8.7 - 2018-09-12
69975  - Fix a bug with UWP detection.
69976 
69977 v0.8.6 - 2018-08-26
69978  - Automatically switch the internal device when the default device is unplugged. Note that this is still in the
69979  early stages and not all backends handle this the same way. As of this version, this will not detect a default
69980  device switch when changed from the operating system's audio preferences (unless the backend itself handles
69981  this automatically). This is not supported in exclusive mode.
69982  - WASAPI and Core Audio: Add support for stream routing. When the application is using a default device and the
69983  user switches the default device via the operating system's audio preferences, miniaudio will automatically switch
69984  the internal device to the new default. This is not supported in exclusive mode.
69985  - WASAPI: Add support for hardware offloading via IAudioClient2. Only supported on Windows 8 and newer.
69986  - WASAPI: Add support for low-latency shared mode via IAudioClient3. Only supported on Windows 10 and newer.
69987  - Add support for compiling the UWP build as C.
69988  - mal_device_set_recv_callback() and mal_device_set_send_callback() have been deprecated. You must now set this
69989  when the device is initialized with mal_device_init*(). These will be removed in version 0.9.0.
69990 
69991 v0.8.5 - 2018-08-12
69992  - Add support for specifying the size of a device's buffer in milliseconds. You can still set the buffer size in
69993  frames if that suits you. When bufferSizeInFrames is 0, bufferSizeInMilliseconds will be used. If both are non-0
69994  then bufferSizeInFrames will take priority. If both are set to 0 the default buffer size is used.
69995  - Add support for the audio(4) backend to OpenBSD.
69996  - Fix a bug with the ALSA backend that was causing problems on Raspberry Pi. This significantly improves the
69997  Raspberry Pi experience.
69998  - Fix a bug where an incorrect number of samples is returned from sinc resampling.
69999  - Add support for setting the value to be passed to internal calls to CoInitializeEx().
70000  - WASAPI and WinMM: Stop the device when it is unplugged.
70001 
70002 v0.8.4 - 2018-08-06
70003  - Add sndio backend for OpenBSD.
70004  - Add audio(4) backend for NetBSD.
70005  - Drop support for the OSS backend on everything except FreeBSD and DragonFly BSD.
70006  - Formats are now native-endian (were previously little-endian).
70007  - Mark some APIs as deprecated:
70008  - mal_src_set_input_sample_rate() and mal_src_set_output_sample_rate() are replaced with mal_src_set_sample_rate().
70009  - mal_dsp_set_input_sample_rate() and mal_dsp_set_output_sample_rate() are replaced with mal_dsp_set_sample_rate().
70010  - Fix a bug when capturing using the WASAPI backend.
70011  - Fix some aliasing issues with resampling, specifically when increasing the sample rate.
70012  - Fix warnings.
70013 
70014 v0.8.3 - 2018-07-15
70015  - Fix a crackling bug when resampling in capture mode.
70016  - Core Audio: Fix a bug where capture does not work.
70017  - ALSA: Fix a bug where the worker thread can get stuck in an infinite loop.
70018  - PulseAudio: Fix a bug where mal_context_init() succeeds when PulseAudio is unusable.
70019  - JACK: Fix a bug where mal_context_init() succeeds when JACK is unusable.
70020 
70021 v0.8.2 - 2018-07-07
70022  - Fix a bug on macOS with Core Audio where the internal callback is not called.
70023 
70024 v0.8.1 - 2018-07-06
70025  - Fix compilation errors and warnings.
70026 
70027 v0.8 - 2018-07-05
70028  - Changed MAL_IMPLEMENTATION to MINI_AL_IMPLEMENTATION for consistency with other libraries. The old
70029  way is still supported for now, but you should update as it may be removed in the future.
70030  - API CHANGE: Replace device enumeration APIs. mal_enumerate_devices() has been replaced with
70031  mal_context_get_devices(). An additional low-level device enumration API has been introduced called
70032  mal_context_enumerate_devices() which uses a callback to report devices.
70033  - API CHANGE: Rename mal_get_sample_size_in_bytes() to mal_get_bytes_per_sample() and add
70034  mal_get_bytes_per_frame().
70035  - API CHANGE: Replace mal_device_config.preferExclusiveMode with mal_device_config.shareMode.
70036  - This new config can be set to mal_share_mode_shared (default) or mal_share_mode_exclusive.
70037  - API CHANGE: Remove excludeNullDevice from mal_context_config.alsa.
70038  - API CHANGE: Rename MAL_MAX_SAMPLE_SIZE_IN_BYTES to MAL_MAX_PCM_SAMPLE_SIZE_IN_BYTES.
70039  - API CHANGE: Change the default channel mapping to the standard Microsoft mapping.
70040  - API CHANGE: Remove backend-specific result codes.
70041  - API CHANGE: Changes to the format conversion APIs (mal_pcm_f32_to_s16(), etc.)
70042  - Add support for Core Audio (Apple).
70043  - Add support for PulseAudio.
70044  - This is the highest priority backend on Linux (higher priority than ALSA) since it is commonly
70045  installed by default on many of the popular distros and offer's more seamless integration on
70046  platforms where PulseAudio is used. In addition, if PulseAudio is installed and running (which
70047  is extremely common), it's better to just use PulseAudio directly rather than going through the
70048  "pulse" ALSA plugin (which is what the "default" ALSA device is likely set to).
70049  - Add support for JACK.
70050  - Remove dependency on asound.h for the ALSA backend. This means the ALSA development packages are no
70051  longer required to build miniaudio.
70052  - Remove dependency on dsound.h for the DirectSound backend. This fixes build issues with some
70053  distributions of MinGW.
70054  - Remove dependency on audioclient.h for the WASAPI backend. This fixes build issues with some
70055  distributions of MinGW.
70056  - Add support for dithering to format conversion.
70057  - Add support for configuring the priority of the worker thread.
70058  - Add a sine wave generator.
70059  - Improve efficiency of sample rate conversion.
70060  - Introduce the notion of standard channel maps. Use mal_get_standard_channel_map().
70061  - Introduce the notion of default device configurations. A default config uses the same configuration
70062  as the backend's internal device, and as such results in a pass-through data transmission pipeline.
70063  - Add support for passing in NULL for the device config in mal_device_init(), which uses a default
70064  config. This requires manually calling mal_device_set_send/recv_callback().
70065  - Add support for decoding from raw PCM data (mal_decoder_init_raw(), etc.)
70066  - Make mal_device_init_ex() more robust.
70067  - Make some APIs more const-correct.
70068  - Fix errors with SDL detection on Apple platforms.
70069  - Fix errors with OpenAL detection.
70070  - Fix some memory leaks.
70071  - Fix a bug with opening decoders from memory.
70072  - Early work on SSE2, AVX2 and NEON optimizations.
70073  - Miscellaneous bug fixes.
70074  - Documentation updates.
70075 
70076 v0.7 - 2018-02-25
70077  - API CHANGE: Change mal_src_read_frames() and mal_dsp_read_frames() to use 64-bit sample counts.
70078  - Add decoder APIs for loading WAV, FLAC, Vorbis and MP3 files.
70079  - Allow opening of devices without a context.
70080  - In this case the context is created and managed internally by the device.
70081  - Change the default channel mapping to the same as that used by FLAC.
70082  - Fix build errors with macOS.
70083 
70084 v0.6c - 2018-02-12
70085  - Fix build errors with BSD/OSS.
70086 
70087 v0.6b - 2018-02-03
70088  - Fix some warnings when compiling with Visual C++.
70089 
70090 v0.6a - 2018-01-26
70091  - Fix errors with channel mixing when increasing the channel count.
70092  - Improvements to the build system for the OpenAL backend.
70093  - Documentation fixes.
70094 
70095 v0.6 - 2017-12-08
70096  - API CHANGE: Expose and improve mutex APIs. If you were using the mutex APIs before this version you'll
70097  need to update.
70098  - API CHANGE: SRC and DSP callbacks now take a pointer to a mal_src and mal_dsp object respectively.
70099  - API CHANGE: Improvements to event and thread APIs. These changes make these APIs more consistent.
70100  - Add support for SDL and Emscripten.
70101  - Simplify the build system further for when development packages for various backends are not installed.
70102  With this change, when the compiler supports __has_include, backends without the relevant development
70103  packages installed will be ignored. This fixes the build for old versions of MinGW.
70104  - Fixes to the Android build.
70105  - Add mal_convert_frames(). This is a high-level helper API for performing a one-time, bulk conversion of
70106  audio data to a different format.
70107  - Improvements to f32 -> u8/s16/s24/s32 conversion routines.
70108  - Fix a bug where the wrong value is returned from mal_device_start() for the OpenSL backend.
70109  - Fixes and improvements for Raspberry Pi.
70110  - Warning fixes.
70111 
70112 v0.5 - 2017-11-11
70113  - API CHANGE: The mal_context_init() function now takes a pointer to a mal_context_config object for
70114  configuring the context. The works in the same kind of way as the device config. The rationale for this
70115  change is to give applications better control over context-level properties, add support for backend-
70116  specific configurations, and support extensibility without breaking the API.
70117  - API CHANGE: The alsa.preferPlugHW device config variable has been removed since it's not really useful for
70118  anything anymore.
70119  - ALSA: By default, device enumeration will now only enumerate over unique card/device pairs. Applications
70120  can enable verbose device enumeration by setting the alsa.useVerboseDeviceEnumeration context config
70121  variable.
70122  - ALSA: When opening a device in shared mode (the default), the dmix/dsnoop plugin will be prioritized. If
70123  this fails it will fall back to the hw plugin. With this change the preferExclusiveMode config is now
70124  honored. Note that this does not happen when alsa.useVerboseDeviceEnumeration is set to true (see above)
70125  which is by design.
70126  - ALSA: Add support for excluding the "null" device using the alsa.excludeNullDevice context config variable.
70127  - ALSA: Fix a bug with channel mapping which causes an assertion to fail.
70128  - Fix errors with enumeration when pInfo is set to NULL.
70129  - OSS: Fix a bug when starting a device when the client sends 0 samples for the initial buffer fill.
70130 
70131 v0.4 - 2017-11-05
70132  - API CHANGE: The log callback is now per-context rather than per-device and as is thus now passed to
70133  mal_context_init(). The rationale for this change is that it allows applications to capture diagnostic
70134  messages at the context level. Previously this was only available at the device level.
70135  - API CHANGE: The device config passed to mal_device_init() is now const.
70136  - Added support for OSS which enables support on BSD platforms.
70137  - Added support for WinMM (waveOut/waveIn).
70138  - Added support for UWP (Universal Windows Platform) applications. Currently C++ only.
70139  - Added support for exclusive mode for selected backends. Currently supported on WASAPI.
70140  - POSIX builds no longer require explicit linking to libpthread (-lpthread).
70141  - ALSA: Explicit linking to libasound (-lasound) is no longer required.
70142  - ALSA: Latency improvements.
70143  - ALSA: Use MMAP mode where available. This can be disabled with the alsa.noMMap config.
70144  - ALSA: Use "hw" devices instead of "plughw" devices by default. This can be disabled with the
70145  alsa.preferPlugHW config.
70146  - WASAPI is now the highest priority backend on Windows platforms.
70147  - Fixed an error with sample rate conversion which was causing crackling when capturing.
70148  - Improved error handling.
70149  - Improved compiler support.
70150  - Miscellaneous bug fixes.
70151 
70152 v0.3 - 2017-06-19
70153  - API CHANGE: Introduced the notion of a context. The context is the highest level object and is required for
70154  enumerating and creating devices. Now, applications must first create a context, and then use that to
70155  enumerate and create devices. The reason for this change is to ensure device enumeration and creation is
70156  tied to the same backend. In addition, some backends are better suited to this design.
70157  - API CHANGE: Removed the rewinding APIs because they're too inconsistent across the different backends, hard
70158  to test and maintain, and just generally unreliable.
70159  - Added helper APIs for initializing mal_device_config objects.
70160  - Null Backend: Fixed a crash when recording.
70161  - Fixed build for UWP.
70162  - Added support for f32 formats to the OpenSL|ES backend.
70163  - Added initial implementation of the WASAPI backend.
70164  - Added initial implementation of the OpenAL backend.
70165  - Added support for low quality linear sample rate conversion.
70166  - Added early support for basic channel mapping.
70167 
70168 v0.2 - 2016-10-28
70169  - API CHANGE: Add user data pointer as the last parameter to mal_device_init(). The rationale for this
70170  change is to ensure the logging callback has access to the user data during initialization.
70171  - API CHANGE: Have device configuration properties be passed to mal_device_init() via a structure. Rationale:
70172  1) The number of parameters is just getting too much.
70173  2) It makes it a bit easier to add new configuration properties in the future. In particular, there's a
70174  chance there will be support added for backend-specific properties.
70175  - Dropped support for f64, A-law and Mu-law formats since they just aren't common enough to justify the
70176  added maintenance cost.
70177  - DirectSound: Increased the default buffer size for capture devices.
70178  - Added initial implementation of the OpenSL|ES backend.
70179 
70180 v0.1 - 2016-10-21
70181  - Initial versioned release.
70182 */
70183 
70184 
70185 /*
70186 This software is available as a choice of the following licenses. Choose
70187 whichever you prefer.
70188 
70189 ===============================================================================
70190 ALTERNATIVE 1 - Public Domain (www.unlicense.org)
70191 ===============================================================================
70192 This is free and unencumbered software released into the public domain.
70193 
70194 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
70195 software, either in source code form or as a compiled binary, for any purpose,
70196 commercial or non-commercial, and by any means.
70197 
70198 In jurisdictions that recognize copyright laws, the author or authors of this
70199 software dedicate any and all copyright interest in the software to the public
70200 domain. We make this dedication for the benefit of the public at large and to
70201 the detriment of our heirs and successors. We intend this dedication to be an
70202 overt act of relinquishment in perpetuity of all present and future rights to
70203 this software under copyright law.
70204 
70205 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70206 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70207 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70208 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
70209 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
70210 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
70211 
70212 For more information, please refer to <http://unlicense.org/>
70213 
70214 ===============================================================================
70215 ALTERNATIVE 2 - MIT No Attribution
70216 ===============================================================================
70217 Copyright 2020 David Reid
70218 
70219 Permission is hereby granted, free of charge, to any person obtaining a copy of
70220 this software and associated documentation files (the "Software"), to deal in
70221 the Software without restriction, including without limitation the rights to
70222 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
70223 of the Software, and to permit persons to whom the Software is furnished to do
70224 so.
70225 
70226 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70227 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70228 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70229 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70230 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70231 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
70232 SOFTWARE.
70233 */
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_DIRECTORY_NOT_EMPTY
#define MA_DIRECTORY_NOT_EMPTY
Definition: pvrecorder/src/miniaudio/miniaudio.h:1783
ma_int64
int64_t ma_int64
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1504
ma_apply_volume_factor_pcm_frames_s32
MA_API void ma_apply_volume_factor_pcm_frames_s32(ma_int32 *pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27979
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
drmp3_uintptr
drmp3_uint32 drmp3_uintptr
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:130
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_opensl_recording_preset
ma_opensl_recording_preset
Definition: pvrecorder/src/miniaudio/miniaudio.h:3289
drwav_seek_origin
drwav_seek_origin
Definition: porcupine/demo/c/dr_libs/dr_wav.h:268
drmp3_L3_gr_info::global_gain
drmp3_uint8 global_gain
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
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
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_format
ma_format
Definition: pvrecorder/src/miniaudio/miniaudio.h:1872
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
DRWAV_INVALID_OPERATION
#define DRWAV_INVALID_OPERATION
Definition: porcupine/demo/c/dr_libs/dr_wav.h:201
drmp3_uninit
DRMP3_API void drmp3_uninit(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61946
DRFLAC_ZERO_MEMORY
#define DRFLAC_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51350
ma_dither_mode
ma_dither_mode
Definition: pvrecorder/src/miniaudio/miniaudio.h:1865
DRMP3_BAD_ADDRESS
#define DRMP3_BAD_ADDRESS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:192
DRFLAC_INLINE
#define DRFLAC_INLINE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51139
MA_LOG_LEVEL
#define MA_LOG_LEVEL
Definition: pvrecorder/src/miniaudio/miniaudio.h:1696
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
ma_uint64
uint64_t ma_uint64
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1505
DRMP3_NO_NETWORK
#define DRMP3_NO_NETWORK
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:203
MA_CHANNEL_AUX_14
#define MA_CHANNEL_AUX_14
Definition: pvrecorder/src/miniaudio/miniaudio.h:1743
DRWAV_TIMEOUT
#define DRWAV_TIMEOUT
Definition: porcupine/demo/c/dr_libs/dr_wav.h:232
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_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_bpf::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2052
ma_device::speex
struct ma_device::@114::@120 speex
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_CHANNEL_TOP_FRONT_CENTER
#define MA_CHANNEL_TOP_FRONT_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1724
ma_backend_callbacks::onDeviceDataLoop
ma_result(* onDeviceDataLoop)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2134
DRWAV_UNAVAILABLE
#define DRWAV_UNAVAILABLE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:220
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_noise_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5400
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
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_pcm_s16_to_s24
MA_API void ma_pcm_s16_to_s24(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28541
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
DRWAV_NOT_DIRECTORY
#define DRWAV_NOT_DIRECTORY
Definition: porcupine/demo/c/dr_libs/dr_wav.h:212
DRMP3_TRUE
#define DRMP3_TRUE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:134
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
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_pcm_s32_to_s16
MA_API void ma_pcm_s32_to_s16(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29265
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
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_device_config::shareMode
ma_share_mode shareMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3131
ma_device_config::noClip
ma_bool32 noClip
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3109
ma_device::operationEvent
ma_event operationEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3837
DRWAV_FALSE
#define DRWAV_FALSE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:165
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_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
ma_aaudio_usage
ma_aaudio_usage
Definition: pvrecorder/src/miniaudio/miniaudio.h:3300
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
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
g_drwavMulawTable
static unsigned short g_drwavMulawTable[256]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49836
drmp3_bool8
drmp3_uint8 drmp3_bool8
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:132
drwav::bitsPerSample
drwav_uint16 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_wav.h:837
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
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_NO_DEVICE
#define MA_NO_DEVICE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1826
MA_LCG_C
#define MA_LCG_C
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2433
ma_encoder_seek_proc
ma_bool32(* ma_encoder_seek_proc)(ma_encoder *pEncoder, int byteOffset, ma_seek_origin origin)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6398
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
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
DRWAV_BEXT_UMID_BYTES
#define DRWAV_BEXT_UMID_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46888
drwav_min
#define drwav_min(a, b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46304
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
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
MA_CHANNEL_AUX_2
#define MA_CHANNEL_AUX_2
Definition: pvrecorder/src/miniaudio/miniaudio.h:1731
MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE
#define MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE
Definition: pvrecorder/src/miniaudio/miniaudio.h:3379
ma_pcm_s24_to_u8
MA_API void ma_pcm_s24_to_u8(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28815
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
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
DRMP3_NOT_UNIQUE
#define DRMP3_NOT_UNIQUE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:204
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
drmp3_seek_proc
drmp3_bool32(* drmp3_seek_proc)(void *pUserData, int offset, drmp3_seek_origin origin)
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:324
drwav_fmt::bitsPerSample
drwav_uint16 bitsPerSample
Definition: porcupine/demo/c/dr_libs/dr_wav.h:320
MA_INVALID_DEVICE_CONFIG
#define MA_INVALID_DEVICE_CONFIG
Definition: pvrecorder/src/miniaudio/miniaudio.h:1828
ma_decoder::pBackendVTable
const ma_decoding_backend_vtable * pBackendVTable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4770
drwav_smpl_loop::firstSampleByteOffset
drwav_uint32 firstSampleByteOffset
Definition: porcupine/demo/c/dr_libs/dr_wav.h:526
drwav::fmt
drwav_fmt fmt
Definition: porcupine/demo/c/dr_libs/dr_wav.h:828
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_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
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
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
ma_aaudio_usage_assitant
@ ma_aaudio_usage_assitant
Definition: pvrecorder/src/miniaudio/miniaudio.h:3311
ma_format_u8
@ ma_format_u8
Definition: pvrecorder/src/miniaudio/miniaudio.h:1879
ma_device::resampling
struct ma_device::@114 resampling
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
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_seek_origin_start
@ ma_seek_origin_start
Definition: pvrecorder/src/miniaudio/miniaudio.h:6116
drwav_metadata_type_unknown
@ drwav_metadata_type_unknown
Definition: porcupine/demo/c/dr_libs/dr_wav.h:455
ma_channel_mix_mode_rectangular
@ ma_channel_mix_mode_rectangular
Definition: pvrecorder/src/miniaudio/miniaudio.h:1921
ma_seek_origin_current
@ ma_seek_origin_current
Definition: pvrecorder/src/miniaudio/miniaudio.h:6117
ma_pcm_s32_to_u8
MA_API void ma_pcm_s32_to_u8(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29185
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
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
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
DRMP3_OUT_OF_MEMORY
#define DRMP3_OUT_OF_MEMORY
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:172
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_CONNECTION_RESET
#define MA_CONNECTION_RESET
Definition: pvrecorder/src/miniaudio/miniaudio.h:1812
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
DRFLAC_VERSION_MINOR
#define DRFLAC_VERSION_MINOR
Definition: porcupine/demo/c/dr_libs/dr_flac.h:234
MA_API
#define MA_API
Definition: pvrecorder/src/miniaudio/miniaudio.h:1652
MA_CHANNEL_NONE
#define MA_CHANNEL_NONE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1709
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
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
drwav_metadata_type_all
@ drwav_metadata_type_all
Definition: porcupine/demo/c/dr_libs/dr_wav.h:500
DRWAV_FREE
#define DRWAV_FREE(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46291
ma_stop_proc
void(* ma_stop_proc)(ma_device *pDevice)
Definition: pvrecorder/src/miniaudio/miniaudio.h:3201
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
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
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
MA_ATOMIC
#define MA_ATOMIC
Definition: pvrecorder/src/miniaudio/miniaudio.h:1703
drflac_oggbs::firstBytePos
drflac_uint64 firstBytePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55446
MA_CHANNEL_TOP_BACK_RIGHT
#define MA_CHANNEL_TOP_BACK_RIGHT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1728
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_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
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
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
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
MA_CANCELLED
#define MA_CANCELLED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1818
ma_device_id::dsound
ma_uint8 dsound[16]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3058
ma_bool32
ma_uint32 ma_bool32
Definition: pvrecorder/src/miniaudio/miniaudio.h:1582
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_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_SOCKET_NOT_SUPPORTED
#define MA_SOCKET_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1811
ma_aaudio_usage_emergency
@ ma_aaudio_usage_emergency
Definition: pvrecorder/src/miniaudio/miniaudio.h:3304
drflac_container_native
@ drflac_container_native
Definition: porcupine/demo/c/dr_libs/dr_flac.h:375
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_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
c89atomic_load_32
#define c89atomic_load_32(ptr)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3988
MA_ALREADY_IN_USE
#define MA_ALREADY_IN_USE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1790
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
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
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
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_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
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
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
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
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
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_mutex_uninit
MA_API void ma_mutex_uninit(ma_mutex *pMutex)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4784
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
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_device_descriptor::periodSizeInMilliseconds
ma_uint32 periodSizeInMilliseconds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2053
ma_rb::subbufferCount
ma_uint32 subbufferCount
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2569
ma_standard_channel_map_flac
@ ma_standard_channel_map_flac
Definition: pvrecorder/src/miniaudio/miniaudio.h:1933
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
DRMP3_CANCELLED
#define DRMP3_CANCELLED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:219
ma_aaudio_usage_notification
@ ma_aaudio_usage_notification
Definition: pvrecorder/src/miniaudio/miniaudio.h:3314
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_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_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_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_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_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
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_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
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_noise_config::amplitude
double amplitude
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5406
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
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
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
drflac_uint64
unsigned long long drflac_uint64
Definition: porcupine/demo/c/dr_libs/dr_flac.h:259
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
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
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
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
drwav_list_labelled_cue_region::country
drwav_uint16 country
Definition: porcupine/demo/c/dr_libs/dr_wav.h:746
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
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
ma_uint8
uint8_t ma_uint8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1499
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_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_AUX_29
#define MA_CHANNEL_AUX_29
Definition: pvrecorder/src/miniaudio/miniaudio.h:1758
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
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
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_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_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_channel_mix_mode_custom_weights
@ ma_channel_mix_mode_custom_weights
Definition: pvrecorder/src/miniaudio/miniaudio.h:1923
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
ma_tell_proc
ma_result(* ma_tell_proc)(void *pUserData, ma_int64 *pCursor)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6160
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
ma_noise_type_white
@ ma_noise_type_white
Definition: pvrecorder/src/miniaudio/miniaudio.h:6481
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
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
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
MA_STATE_STOPPING
#define MA_STATE_STOPPING
Definition: pvrecorder/src/miniaudio/miniaudio.h:3107
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_noise
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5412
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
drwav_metadata_type_list_all_adtl
@ drwav_metadata_type_list_all_adtl
Definition: porcupine/demo/c/dr_libs/dr_wav.h:496
DRMP3_BAD_PROTOCOL
#define DRMP3_BAD_PROTOCOL
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:207
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_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
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
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
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
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
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
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
DRMP3_NOT_CONNECTED
#define DRMP3_NOT_CONNECTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:215
DRMP3_VERSION_REVISION
#define DRMP3_VERSION_REVISION
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:98
ma_decoder_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5174
ma_encoder_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5313
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_channel_mix_mode
ma_channel_mix_mode
Definition: pvrecorder/src/miniaudio/miniaudio.h:1919
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_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
ma_context::pthread_attr_setschedparam
ma_proc pthread_attr_setschedparam
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3577
DRWAV_NO_ADDRESS
#define DRWAV_NO_ADDRESS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:236
MA_CHANNEL_TOP_BACK_CENTER
#define MA_CHANNEL_TOP_BACK_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1727
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
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
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_bool8
ma_uint8 ma_bool8
Definition: pvrecorder/src/miniaudio/miniaudio.h:1581
drwav_list_label_or_note::stringLength
drwav_uint32 stringLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:667
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_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_waveform_type_sawtooth
@ ma_waveform_type_sawtooth
Definition: pvrecorder/src/miniaudio/miniaudio.h:6451
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
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
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_CHANNEL_AUX_20
#define MA_CHANNEL_AUX_20
Definition: pvrecorder/src/miniaudio/miniaudio.h:1749
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
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
ma_lpf_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1921
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
ma_biquad::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1860
DRMP3_BAD_MESSAGE
#define DRMP3_BAD_MESSAGE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:199
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
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_smpl_loop_type_forward
@ drwav_smpl_loop_type_forward
Definition: porcupine/demo/c/dr_libs/dr_wav.h:512
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_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
ma_hpf::hpf2Count
ma_uint32 hpf2Count
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2001
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
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_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
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
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_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_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_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_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_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
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_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
MA_OPEN_MODE_READ
#define MA_OPEN_MODE_READ
Definition: pvrecorder/src/miniaudio/miniaudio.h:6111
ma_data_converter_config::channelMapIn
ma_channel channelMapIn[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2409
drwav_smpl_loop_type_backward
@ drwav_smpl_loop_type_backward
Definition: porcupine/demo/c/dr_libs/dr_wav.h:514
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_biquad::r1
ma_biquad_coefficient r1[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1866
ma_channel_converter_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2354
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
ma_device::operationCompletionEvent
ma_event operationCompletionEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3838
ma_aaudio_content_type_speech
@ ma_aaudio_content_type_speech
Definition: pvrecorder/src/miniaudio/miniaudio.h:3328
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
ma_share_mode_exclusive
@ ma_share_mode_exclusive
Definition: pvrecorder/src/miniaudio/miniaudio.h:3248
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_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
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
MA_CHANNEL_AUX_10
#define MA_CHANNEL_AUX_10
Definition: pvrecorder/src/miniaudio/miniaudio.h:1739
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
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
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
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_data_converter_config::sampleRateOut
ma_uint32 sampleRateOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2408
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_stream_layout
ma_stream_layout
Definition: pvrecorder/src/miniaudio/miniaudio.h:1859
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
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
MA_LOG_LEVEL_WARNING
#define MA_LOG_LEVEL_WARNING
Definition: pvrecorder/src/miniaudio/miniaudio.h:1688
ma_device_config::wasapi
struct ma_device_config::@99 wasapi
ma_flac::onSeek
ma_seek_proc onSeek
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41503
drwav_chunk_header::sizeInBytes
drwav_uint64 sizeInBytes
Definition: porcupine/demo/c/dr_libs/dr_wav.h:290
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
drmp3::currentReadPos
size_t currentReadPos
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:368
drflac_metadata::application
struct drflac_metadata::@0::@2 application
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
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
ma_resample_algorithm_linear
@ ma_resample_algorithm_linear
Definition: pvrecorder/src/miniaudio/miniaudio.h:2491
DRMP3_INLINE
#define DRMP3_INLINE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:245
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_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
DRMP3_INVALID_DATA
#define DRMP3_INVALID_DATA
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:201
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_opensl_recording_preset_default
@ ma_opensl_recording_preset_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:3291
MA_ACCESS_DENIED
#define MA_ACCESS_DENIED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1773
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
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_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
MA_TOO_MANY_OPEN_FILES
#define MA_TOO_MANY_OPEN_FILES
Definition: pvrecorder/src/miniaudio/miniaudio.h:1776
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
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_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
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
ma_context::deviceInfoCapacity
ma_uint32 deviceInfoCapacity
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3219
MA_CHANNEL_TOP_FRONT_RIGHT
#define MA_CHANNEL_TOP_FRONT_RIGHT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1725
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_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
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_resource_format_wav
@ ma_resource_format_wav
Definition: pvrecorder/src/miniaudio/miniaudio.h:6167
ma_hpf_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1989
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
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
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
MA_CHANNEL_AUX_4
#define MA_CHANNEL_AUX_4
Definition: pvrecorder/src/miniaudio/miniaudio.h:1733
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
MA_CHANNEL_AUX_5
#define MA_CHANNEL_AUX_5
Definition: pvrecorder/src/miniaudio/miniaudio.h:1734
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_type_list_info_album
@ drwav_metadata_type_list_info_album
Definition: porcupine/demo/c/dr_libs/dr_wav.h:482
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_ios_session_category
ma_ios_session_category
Definition: pvrecorder/src/miniaudio/miniaudio.h:3252
DRWAV_API
#define DRWAV_API
Definition: porcupine/demo/c/dr_libs/dr_wav.h:192
ma_log_unlock
static void ma_log_unlock(ma_log *pLog)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2052
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_NO_ADDRESS
#define MA_NO_ADDRESS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1805
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
ma_device::currentPeriodFramesRemainingPlayback
ma_uint32 currentPeriodFramesRemainingPlayback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3843
drwav_metadata::type
drwav_metadata_type type
Definition: porcupine/demo/c/dr_libs/dr_wav.h:789
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
ma_device_config::deviceType
ma_device_type deviceType
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3102
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
ma_device::lastProcessedFrameCapture
ma_uint32 lastProcessedFrameCapture
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3846
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
DRWAV_NO_HOST
#define DRWAV_NO_HOST
Definition: porcupine/demo/c/dr_libs/dr_wav.h:247
drwav_seek_origin_start
@ drwav_seek_origin_start
Definition: porcupine/demo/c/dr_libs/dr_wav.h:270
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
drmp3dec_init
DRMP3_API void drmp3dec_init(drmp3dec *dec)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:60855
ma_data_converter_config_init_default
MA_API ma_data_converter_config ma_data_converter_config_init_default(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:34511
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_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_ios_session_category_option_allow_air_play
@ ma_ios_session_category_option_allow_air_play
Definition: pvrecorder/src/miniaudio/miniaudio.h:3273
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
ma_standard_channel_map
ma_standard_channel_map
Definition: pvrecorder/src/miniaudio/miniaudio.h:1928
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_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
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
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
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
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_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
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
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_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_mp3::onTell
ma_tell_proc onTell
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:42136
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
drmp3_reset
static void drmp3_reset(drmp3 *pMP3)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:62099
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_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_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_encoding_format_flac
@ ma_encoding_format_flac
Definition: pvrecorder/src/miniaudio/miniaudio.h:6174
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
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
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
ma_device_type_playback
@ ma_device_type_playback
Definition: pvrecorder/src/miniaudio/miniaudio.h:3239
MA_CHANNEL_AUX_24
#define MA_CHANNEL_AUX_24
Definition: pvrecorder/src/miniaudio/miniaudio.h:1753
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_ATTRIBUTE_FORMAT
#define MA_ATTRIBUTE_FORMAT(fmt, va)
Definition: pvrecorder/src/miniaudio/miniaudio.h:2048
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
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
ma_backend_jack
@ ma_backend_jack
Definition: pvrecorder/src/miniaudio/miniaudio.h:3131
ma_device::lock
ma_mutex lock
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3593
ma_encoder::onUninit
ma_encoder_uninit_proc onUninit
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5330
ma_hpf::hpf1
ma_hpf1 hpf1[1]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2002
DRWAV_CUE_POINT_BYTES
#define DRWAV_CUE_POINT_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46889
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_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_context::pthread_mutex_lock
ma_proc pthread_mutex_lock
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3567
ma_countof
#define ma_countof(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:776
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
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_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_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
DRWAV_SUCCESS
#define DRWAV_SUCCESS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:198
drflac_vorbis_comment_iterator
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1257
ma_biquad_config::b1
double b1
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1848
ma_offset_pcm_frames_ptr_f32
static MA_INLINE float * ma_offset_pcm_frames_ptr_f32(float *p, ma_uint64 offsetInFrames, ma_uint32 channels)
Definition: pvrecorder/src/miniaudio/miniaudio.h:5925
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_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_backend_winmm
@ ma_backend_winmm
Definition: pvrecorder/src/miniaudio/miniaudio.h:3124
ma_decoder::onUninit
ma_decoder_uninit_proc onUninit
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5211
ma_context_command__wasapi
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2172
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
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_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
DRMP3_INVALID_OPERATION
#define DRMP3_INVALID_OPERATION
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:171
DRWAV_TOO_MANY_OPEN_FILES
#define DRWAV_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/dr_libs/dr_wav.h:207
ma_aaudio_usage_default
@ ma_aaudio_usage_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:3302
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
DRFLAC_METADATA_BLOCK_TYPE_PICTURE
#define DRFLAC_METADATA_BLOCK_TYPE_PICTURE
Definition: porcupine/demo/c/dr_libs/dr_flac.h:347
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
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
ma_pcm_f32_to_s32
MA_API void ma_pcm_f32_to_s32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30143
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_decoder_config_init_default
MA_API ma_decoder_config ma_decoder_config_init_default(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40663
MA_MALLOC
#define MA_MALLOC(sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:722
drwav_allocation_callbacks::onRealloc
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:413
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_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_data_converter_config::ditherMode
ma_dither_mode ditherMode
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2411
ma_decoder::onRead
ma_decoder_read_proc onRead
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5195
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_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
DRFLAC_VERSION_STRING
#define DRFLAC_VERSION_STRING
Definition: porcupine/demo/c/dr_libs/dr_flac.h:236
DRMP3_SUCCESS
#define DRMP3_SUCCESS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:168
ma_file_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4643
drwav_metadata_location_inside_info_list
@ drwav_metadata_location_inside_info_list
Definition: porcupine/demo/c/dr_libs/dr_wav.h:771
ma_context
struct ma_context ma_context
Definition: pvrecorder/src/miniaudio/miniaudio.h:1705
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
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_decoder_config::linear
struct ma_decoder_config::@122::@123 linear
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
ma_ios_session_category_option_mix_with_others
@ ma_ios_session_category_option_mix_with_others
Definition: pvrecorder/src/miniaudio/miniaudio.h:3267
drwav_bext::codingHistorySize
drwav_uint32 codingHistorySize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:699
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
DRMP3_INTERRUPT
#define DRMP3_INTERRUPT
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:189
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
MA_NO_BACKEND
#define MA_NO_BACKEND
Definition: pvrecorder/src/miniaudio/miniaudio.h:1825
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
c89atomic_if64::f
double f
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4126
ma_decoder::memory
struct ma_decoder::@125 memory
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_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
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_CHANNEL_AUX_3
#define MA_CHANNEL_AUX_3
Definition: pvrecorder/src/miniaudio/miniaudio.h:1732
ma_data_source_base::pCurrent
ma_data_source * pCurrent
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4533
MA_TOO_MANY_LINKS
#define MA_TOO_MANY_LINKS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1795
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
MA_64BIT
#define MA_64BIT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:65
MA_NO_DATA_AVAILABLE
#define MA_NO_DATA_AVAILABLE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1799
ma_ios_session_category_ambient
@ ma_ios_session_category_ambient
Definition: pvrecorder/src/miniaudio/miniaudio.h:3256
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
DRWAV_NOT_UNIQUE
#define DRWAV_NOT_UNIQUE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:234
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
drflac_uint8
unsigned char drflac_uint8
Definition: porcupine/demo/c/dr_libs/dr_flac.h:242
DRWAV_BEXT_BYTES
#define DRWAV_BEXT_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46883
ma_device_type_capture
@ ma_device_type_capture
Definition: pvrecorder/src/miniaudio/miniaudio.h:3240
ma_data_converter_config::channelsIn
ma_uint32 channelsIn
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2405
ma_vfs_file
ma_handle ma_vfs_file
Definition: pvrecorder/src/miniaudio/miniaudio.h:6109
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_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
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
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
DRMP3_BAD_SEEK
#define DRMP3_BAD_SEEK
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:193
ma_ios_session_category_option_allow_bluetooth
@ ma_ios_session_category_option_allow_bluetooth
Definition: pvrecorder/src/miniaudio/miniaudio.h:3269
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
MA_MIN_CHANNELS
#define MA_MIN_CHANNELS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1844
ma_dither_mode_rectangle
@ ma_dither_mode_rectangle
Definition: pvrecorder/src/miniaudio/miniaudio.h:1868
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
MA_INVALID_DATA
#define MA_INVALID_DATA
Definition: pvrecorder/src/miniaudio/miniaudio.h:1800
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
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_int32
signed int ma_int32
Definition: pvrecorder/src/miniaudio/miniaudio.h:1556
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
drmp3_L3_gr_info::block_type
drmp3_uint8 block_type
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59498
ma_opensl_recording_preset_camcorder
@ ma_opensl_recording_preset_camcorder
Definition: pvrecorder/src/miniaudio/miniaudio.h:3293
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
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_SOCKET_NOT_SUPPORTED
#define DRMP3_SOCKET_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:212
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
MA_NOT_IMPLEMENTED
#define MA_NOT_IMPLEMENTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1796
drflac_metadata::cuesheet
struct drflac_metadata::@0::@5 cuesheet
MA_FORMAT_NOT_SUPPORTED
#define MA_FORMAT_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1822
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
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
DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE
#define DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE
Definition: porcupine/demo/c/dr_libs/dr_flac.h:344
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
FALSE
#define FALSE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:642
ma_context::pthread_mutex_init
ma_proc pthread_mutex_init
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3565
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_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
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
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
DRWAV_IN_PROGRESS
#define DRWAV_IN_PROGRESS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:248
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
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
ma_apply_volume_factor_pcm_frames_s16
MA_API void ma_apply_volume_factor_pcm_frames_s16(ma_int16 *pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27969
drmp3dec_frame_info::bitrate_kbps
int bitrate_kbps
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:259
MA_TRUE
#define MA_TRUE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1583
ma_aaudio_input_preset_voice_performance
@ ma_aaudio_input_preset_voice_performance
Definition: pvrecorder/src/miniaudio/miniaudio.h:3340
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
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
drflac_frame
Definition: porcupine/demo/c/dr_libs/dr_flac.h:673
MA_NO_HOST
#define MA_NO_HOST
Definition: pvrecorder/src/miniaudio/miniaudio.h:1816
ma_int8
int8_t ma_int8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1498
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::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
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
ma_stream_format_pcm
@ ma_stream_format_pcm
Definition: pvrecorder/src/miniaudio/miniaudio.h:1856
drflac_cuesheet_track::pIndexPoints
const drflac_cuesheet_track_index * pIndexPoints
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1301
DRWAV_PATH_TOO_LONG
#define DRWAV_PATH_TOO_LONG
Definition: porcupine/demo/c/dr_libs/dr_wav.h:210
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
MA_ADDRESS_FAMILY_NOT_SUPPORTED
#define MA_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1810
ma_thread_priority_high
@ ma_thread_priority_high
Definition: pvrecorder/src/miniaudio/miniaudio.h:1970
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
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
ma_thread_priority_default
@ ma_thread_priority_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:1973
drflac_frame_header::channelAssignment
drflac_uint8 channelAssignment
Definition: porcupine/demo/c/dr_libs/dr_flac.h:664
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
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_IO_ERROR
#define DRWAV_IO_ERROR
Definition: porcupine/demo/c/dr_libs/dr_wav.h:218
drwav::onWrite
drwav_write_proc onWrite
Definition: porcupine/demo/c/dr_libs/dr_wav.h:811
ma_int16
int16_t ma_int16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1500
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
DRFLAC_NO_DATA_AVAILABLE
#define DRFLAC_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51389
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_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
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
DRMP3_PROTOCOL_NOT_SUPPORTED
#define DRMP3_PROTOCOL_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:209
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
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_device::timer
ma_timer timer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3841
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
ma_ios_session_category_option
ma_ios_session_category_option
Definition: pvrecorder/src/miniaudio/miniaudio.h:3265
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
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
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
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_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
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
ma_format_unknown
@ ma_format_unknown
Definition: pvrecorder/src/miniaudio/miniaudio.h:1878
DRMP3_TIMEOUT
#define DRMP3_TIMEOUT
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:202
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
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_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
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
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::granulePosition
drflac_uint64 granulePosition
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54780
ma_aaudio_usage_safety
@ ma_aaudio_usage_safety
Definition: pvrecorder/src/miniaudio/miniaudio.h:3305
ma_wav::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40865
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
drwav_container_w64
@ drwav_container_w64
Definition: porcupine/demo/c/dr_libs/dr_wav.h:277
c89atomic_exchange_32
#define c89atomic_exchange_32(dst, src)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3992
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_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_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
drmp3_seek_origin_start
@ drmp3_seek_origin_start
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:286
ma_encoder_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5317
DRMP3_ALREADY_CONNECTED
#define DRMP3_ALREADY_CONNECTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:214
c89atomic_if32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4118
MA_CONNECTION_REFUSED
#define MA_CONNECTION_REFUSED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1815
DRFLAC_TOO_BIG
#define DRFLAC_TOO_BIG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51368
MA_FAILED_TO_INIT_BACKEND
#define MA_FAILED_TO_INIT_BACKEND
Definition: pvrecorder/src/miniaudio/miniaudio.h:1838
ma_context::null_backend
struct ma_context::@108::@112 null_backend
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
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
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
MA_CHANNEL_AUX_8
#define MA_CHANNEL_AUX_8
Definition: pvrecorder/src/miniaudio/miniaudio.h:1737
ma_flac::dr
drflac * dr
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41508
ma_channel_mix_mode_default
@ ma_channel_mix_mode_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:1925
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_opensl_recording_preset_generic
@ ma_opensl_recording_preset_generic
Definition: pvrecorder/src/miniaudio/miniaudio.h:3292
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
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
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
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_thread_priority_realtime
@ ma_thread_priority_realtime
Definition: pvrecorder/src/miniaudio/miniaudio.h:1972
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_decoder_tell_proc
ma_result(* ma_decoder_tell_proc)(ma_decoder *pDecoder, ma_int64 *pCursor)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6215
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
ma_semaphore
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2892
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
ma_device::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3625
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
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
MA_BAD_PROTOCOL
#define MA_BAD_PROTOCOL
Definition: pvrecorder/src/miniaudio/miniaudio.h:1806
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_ios_session_category_none
@ ma_ios_session_category_none
Definition: pvrecorder/src/miniaudio/miniaudio.h:3255
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_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
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
MA_DEVICE_NOT_INITIALIZED
#define MA_DEVICE_NOT_INITIALIZED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1832
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
DRWAV_BUSY
#define DRWAV_BUSY
Definition: porcupine/demo/c/dr_libs/dr_wav.h:217
MA_NOT_CONNECTED
#define MA_NOT_CONNECTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1814
ma_decoder::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5208
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
drmp3dec::free_format_bytes
int free_format_bytes
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:265
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_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_linear_resampler_config::sampleRateOut
ma_uint32 sampleRateOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2210
ma_proc
void(* ma_proc)(void)
Definition: pvrecorder/src/miniaudio/miniaudio.h:1588
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
ma_decoding_backend_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4715
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_INTERRUPT
#define MA_INTERRUPT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1788
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
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
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_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
ma_apply_volume_factor_pcm_frames_u8
MA_API void ma_apply_volume_factor_pcm_frames_u8(ma_uint8 *pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27964
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_thread_priority
ma_thread_priority
Definition: pvrecorder/src/miniaudio/miniaudio.h:1964
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_context_config::useVerboseDeviceEnumeration
ma_bool32 useVerboseDeviceEnumeration
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3168
MA_DEVICE_NOT_STOPPED
#define MA_DEVICE_NOT_STOPPED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1835
drflac__memory_stream::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/dr_flac.h:576
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
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_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
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_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
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
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
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
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
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
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_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_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_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_aaudio_usage_notification_event
@ ma_aaudio_usage_notification_event
Definition: pvrecorder/src/miniaudio/miniaudio.h:3315
ma_device_info::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1930
drwav_smpl::samplePeriodNanoseconds
drwav_uint32 samplePeriodNanoseconds
Definition: porcupine/demo/c/dr_libs/dr_wav.h:545
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
drwav_read_proc
size_t(* drwav_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:354
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_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
DRMP3_TOO_MANY_OPEN_FILES
#define DRMP3_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:177
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_device_descriptor::channelMap
ma_channel channelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2051
ma_ios_session_category_play_and_record
@ ma_ios_session_category_play_and_record
Definition: pvrecorder/src/miniaudio/miniaudio.h:3260
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
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
MA_CHANNEL_AUX_16
#define MA_CHANNEL_AUX_16
Definition: pvrecorder/src/miniaudio/miniaudio.h:1745
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_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_context::backend
ma_backend backend
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3212
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
MA_DEFAULT_FORMAT
#define MA_DEFAULT_FORMAT
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:596
MA_INVALID_FILE
#define MA_INVALID_FILE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1777
ma_opensl_stream_type
ma_opensl_stream_type
Definition: pvrecorder/src/miniaudio/miniaudio.h:3277
ma_flac::onRead
ma_read_proc onRead
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41502
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_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
drmp3_read_proc
size_t(* drmp3_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:310
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_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
DRWAV_BAD_PROTOCOL
#define DRWAV_BAD_PROTOCOL
Definition: porcupine/demo/c/dr_libs/dr_wav.h:237
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_device_uninit
MA_API void ma_device_uninit(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27425
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_context::pthread_cond_init
ma_proc pthread_cond_init
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3569
DRWAV_DIRECTORY_NOT_EMPTY
#define DRWAV_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/dr_libs/dr_wav.h:214
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
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
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
MA_INLINE
#define MA_INLINE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1624
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
ma_pcm_u8_to_s24
MA_API void ma_pcm_u8_to_s24(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28177
ma_data_source
void ma_data_source
Definition: pvrecorder/src/miniaudio/miniaudio.h:5978
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_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
DRMP3_NO_ADDRESS
#define DRMP3_NO_ADDRESS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:206
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_share_mode
ma_share_mode
Definition: pvrecorder/src/miniaudio/miniaudio.h:3245
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
ma_pcm_u8_to_f32
MA_API void ma_pcm_u8_to_f32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28308
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
ma_stream_layout_interleaved
@ ma_stream_layout_interleaved
Definition: pvrecorder/src/miniaudio/miniaudio.h:1861
drwav_acid::numBeats
drwav_uint32 numBeats
Definition: porcupine/demo/c/dr_libs/dr_wav.h:644
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_context_config_init
MA_API ma_context_config ma_context_config_init(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26542
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
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_decoder_read_proc
size_t(* ma_decoder_read_proc)(ma_decoder *pDecoder, void *pBufferOut, size_t bytesToRead)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6213
g_maLCG
static ma_lcg g_maLCG
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2435
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
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
DRWAV_VERSION_REVISION
#define DRWAV_VERSION_REVISION
Definition: porcupine/demo/c/dr_libs/dr_wav.h:128
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
drwav_acid_flag_disk_based
@ drwav_acid_flag_disk_based
Definition: porcupine/demo/c/dr_libs/dr_wav.h:627
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
ma_uint32
unsigned int ma_uint32
Definition: pvrecorder/src/miniaudio/miniaudio.h:1557
drflac::memoryStream
drflac__memory_stream memoryStream
Definition: porcupine/demo/c/dr_libs/dr_flac.h:741
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_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_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
DRWAV_NOT_CONNECTED
#define DRWAV_NOT_CONNECTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:245
ma_backend_callbacks::onDeviceUninit
ma_result(* onDeviceUninit)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2129
drwav__memory_stream::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:421
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_15
#define MA_CHANNEL_AUX_15
Definition: pvrecorder/src/miniaudio/miniaudio.h:1744
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
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_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
drflac_meta_proc
void(* drflac_meta_proc)(void *pUserData, drflac_metadata *pMetadata)
Definition: porcupine/demo/c/dr_libs/dr_flac.h:561
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
drwav_chunk_header::fourcc
drwav_uint8 fourcc[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:285
DRWAV_ALREADY_EXISTS
#define DRWAV_ALREADY_EXISTS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:206
ma_device_config::noMMap
ma_bool32 noMMap
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3151
ma_device_config::dataCallback
ma_device_callback_proc dataCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3110
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
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
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_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
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
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_standard_sample_rate_96000
@ ma_standard_sample_rate_96000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1898
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_backend_webaudio
@ ma_backend_webaudio
Definition: pvrecorder/src/miniaudio/miniaudio.h:3134
MA_VERSION_STRING
#define MA_VERSION_STRING
Definition: pvrecorder/src/miniaudio/miniaudio.h:1502
ma_decoder::pData
const ma_uint8 * pData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5216
MA_CHANNEL_MONO
#define MA_CHANNEL_MONO
Definition: pvrecorder/src/miniaudio/miniaudio.h:1710
DRFLAC_VERSION_MAJOR
#define DRFLAC_VERSION_MAJOR
Definition: porcupine/demo/c/dr_libs/dr_flac.h:233
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_biquad_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1846
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
ma_apply_volume_factor_pcm_frames
MA_API void ma_apply_volume_factor_pcm_frames(void *pFrames, 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_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
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
drwav_cue_point::dataChunkId
drwav_uint8 dataChunkId[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:599
MA_DEADLOCK
#define MA_DEADLOCK
Definition: pvrecorder/src/miniaudio/miniaudio.h:1794
ma_audio_buffer_ref::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4565
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
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_lpf2_config
struct ma_lpf1_config ma_lpf2_config
ma_peak2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2102
DRWAV_VERSION_MINOR
#define DRWAV_VERSION_MINOR
Definition: porcupine/demo/c/dr_libs/dr_wav.h:127
ma_context::pthread_create
ma_proc pthread_create
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3563
MA_CHANNEL_RIGHT
#define MA_CHANNEL_RIGHT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1762
drwav_cue_point::playOrderPosition
drwav_uint32 playOrderPosition
Definition: porcupine/demo/c/dr_libs/dr_wav.h:596
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
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
DRWAV_PROTOCOL_NOT_SUPPORTED
#define DRWAV_PROTOCOL_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:239
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
drwav_allocation_callbacks::onFree
void(* onFree)(void *p, void *pUserData)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:414
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
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_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_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_aaudio_usage_voice_communication_signalling
@ ma_aaudio_usage_voice_communication_signalling
Definition: pvrecorder/src/miniaudio/miniaudio.h:3318
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_decoder_config::speex
struct ma_decoder_config::@122::@124 speex
MA_ALREADY_EXISTS
#define MA_ALREADY_EXISTS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1775
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_SUCCESS
#define MA_SUCCESS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1767
DRMP3_NOT_SOCKET
#define DRMP3_NOT_SOCKET
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:205
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
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_CHANNEL_AUX_0
#define MA_CHANNEL_AUX_0
Definition: pvrecorder/src/miniaudio/miniaudio.h:1729
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_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
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
drwav_metadata_type_list_info_artist
@ drwav_metadata_type_list_info_artist
Definition: porcupine/demo/c/dr_libs/dr_wav.h:478
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
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_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
ma_standard_channel_map_alsa
@ ma_standard_channel_map_alsa
Definition: pvrecorder/src/miniaudio/miniaudio.h:1931
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_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_device_config::noDefaultQualitySRC
ma_bool32 noDefaultQualitySRC
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3145
ma_device::deviceThread
ma_thread deviceThread
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3836
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_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_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_context::pthreadSO
ma_handle pthreadSO
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3562
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
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_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_decoder::readPointerInPCMFrames
ma_uint64 readPointerInPCMFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4776
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
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
drflac_bs::onSeek
drflac_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/dr_flac.h:587
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_aaudio_content_type
ma_aaudio_content_type
Definition: pvrecorder/src/miniaudio/miniaudio.h:3322
ma_ios_session_category_option_interrupt_spoken_audio_and_mix_with_others
@ ma_ios_session_category_option_interrupt_spoken_audio_and_mix_with_others
Definition: pvrecorder/src/miniaudio/miniaudio.h:3271
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)
DRMP3_VERSION_MINOR
#define DRMP3_VERSION_MINOR
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:97
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_ios_session_category_default
@ ma_ios_session_category_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:3254
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
drwav_seek_origin_current
@ drwav_seek_origin_current
Definition: porcupine/demo/c/dr_libs/dr_wav.h:271
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_NO_NETWORK
#define MA_NO_NETWORK
Definition: pvrecorder/src/miniaudio/miniaudio.h:1802
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
ma_aaudio_usage_announcement
@ ma_aaudio_usage_announcement
Definition: pvrecorder/src/miniaudio/miniaudio.h:3303
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
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_DEVICE_NOT_STARTED
#define MA_DEVICE_NOT_STARTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1834
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
DRMP3_NO_DATA_AVAILABLE
#define DRMP3_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:200
drflac_version_string
const DRFLAC_API char * drflac_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51436
ma_device_callback_proc
void(* ma_device_callback_proc)(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
Definition: pvrecorder/src/miniaudio/miniaudio.h:3182
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
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_standard_channel_map_webaudio
@ ma_standard_channel_map_webaudio
Definition: pvrecorder/src/miniaudio/miniaudio.h:1937
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
ma_linear_resampler::lpf
ma_lpf lpf
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2221
DRMP3_NO_SPACE
#define DRMP3_NO_SPACE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:186
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
drmp3_cos
static DRMP3_INLINE double drmp3_cos(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61074
ma_share_mode_shared
@ ma_share_mode_shared
Definition: pvrecorder/src/miniaudio/miniaudio.h:3247
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
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
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_pcm_s16_to_s32
MA_API void ma_pcm_s16_to_s32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28603
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_NOT_DIRECTORY
#define MA_NOT_DIRECTORY
Definition: pvrecorder/src/miniaudio/miniaudio.h:1781
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
drflac_metadata::seektable
struct drflac_metadata::@0::@3 seektable
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
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
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
MA_NAME_TOO_LONG
#define MA_NAME_TOO_LONG
Definition: pvrecorder/src/miniaudio/miniaudio.h:1780
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
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
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_FAILED_TO_STOP_BACKEND_DEVICE
#define MA_FAILED_TO_STOP_BACKEND_DEVICE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1841
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
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
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
drwav_metadata_type_list_info_genre
@ drwav_metadata_type_list_info_genre
Definition: porcupine/demo/c/dr_libs/dr_wav.h:481
ma_channel_mix_mode_planar_blend
@ ma_channel_mix_mode_planar_blend
Definition: pvrecorder/src/miniaudio/miniaudio.h:1924
DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED
#define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:211
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
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
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
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::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
DRMP3_ERROR
#define DRMP3_ERROR
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:169
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
drwav_container_rf64
@ drwav_container_rf64
Definition: porcupine/demo/c/dr_libs/dr_wav.h:278
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
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
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
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
ma_standard_sample_rate_88200
@ ma_standard_sample_rate_88200
Definition: pvrecorder/src/miniaudio/miniaudio.h:1897
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__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_version_string
const DRWAV_API char * drwav_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46374
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
DR_WAVE_FORMAT_PCM
#define DR_WAVE_FORMAT_PCM
Definition: porcupine/demo/c/dr_libs/dr_wav.h:254
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_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_TIMEOUT
#define MA_TIMEOUT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1801
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_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_lpf1::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1895
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_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
DRWAV_SOCKET_NOT_SUPPORTED
#define DRWAV_SOCKET_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:242
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_aaudio_input_preset_voice_communication
@ ma_aaudio_input_preset_voice_communication
Definition: pvrecorder/src/miniaudio/miniaudio.h:3339
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_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
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_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
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
drmp3_L3_gr_info
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59494
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
DRMP3_INVALID_FILE
#define DRMP3_INVALID_FILE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:178
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__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
ma_standard_sample_rate
ma_standard_sample_rate
Definition: pvrecorder/src/miniaudio/miniaudio.h:1887
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_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_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_duplex_rb
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1447
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
ma_ios_session_category_record
@ ma_ios_session_category_record
Definition: pvrecorder/src/miniaudio/miniaudio.h:3259
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_decoder_seek_proc
ma_bool32(* ma_decoder_seek_proc)(ma_decoder *pDecoder, ma_int64 byteOffset, ma_seek_origin origin)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6214
ma_peak2_config::gainDB
double gainDB
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2105
drflac_ogg_page_header::segmentCount
drflac_uint8 segmentCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54784
MA_CHANNEL_SIDE_LEFT
#define MA_CHANNEL_SIDE_LEFT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1720
c89atomic_spinlock
c89atomic_flag c89atomic_spinlock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4178
ma_resample_algorithm_speex
@ ma_resample_algorithm_speex
Definition: pvrecorder/src/miniaudio/miniaudio.h:2492
DRMP3_DOES_NOT_EXIST
#define DRMP3_DOES_NOT_EXIST
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:175
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
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_type_list_note
@ drwav_metadata_type_list_note
Definition: porcupine/demo/c/dr_libs/dr_wav.h:472
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
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_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_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_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
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
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
ma_pcm_f32_to_s24
MA_API void ma_pcm_f32_to_s24(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:30068
ma_standard_sample_rate_48000
@ ma_standard_sample_rate_48000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1890
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
DRWAV_SEQUENTIAL
#define DRWAV_SEQUENTIAL
Definition: porcupine/demo/c/dr_libs/dr_wav.h:263
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_device::currentPeriodFramesRemainingCapture
ma_uint32 currentPeriodFramesRemainingCapture
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3844
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
DRWAV_CONNECTION_RESET
#define DRWAV_CONNECTION_RESET
Definition: porcupine/demo/c/dr_libs/dr_wav.h:243
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
drflac_init_info::totalPCMFrameCount
drflac_uint64 totalPCMFrameCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54799
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_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
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_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
ma_aaudio_input_preset_camcorder
@ ma_aaudio_input_preset_camcorder
Definition: pvrecorder/src/miniaudio/miniaudio.h:3336
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
ma_device::operationResult
ma_result operationResult
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3840
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
MA_NOT_UNIQUE
#define MA_NOT_UNIQUE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1803
ma_stream_layout_deinterleaved
@ ma_stream_layout_deinterleaved
Definition: pvrecorder/src/miniaudio/miniaudio.h:1862
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
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)
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
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_ALREADY_CONNECTED
#define MA_ALREADY_CONNECTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1813
ma_backend_wasapi
@ ma_backend_wasapi
Definition: pvrecorder/src/miniaudio/miniaudio.h:3122
ma_waveform::advance
double advance
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5376
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_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_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
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
MA_FAILED_TO_OPEN_BACKEND_DEVICE
#define MA_FAILED_TO_OPEN_BACKEND_DEVICE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1839
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_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
ma_device::operationSemaphore
ma_semaphore operationSemaphore
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2850
ma_decoder::outputChannelMap
ma_channel outputChannelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5206
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
DRWAV_TOO_MANY_LINKS
#define DRWAV_TOO_MANY_LINKS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:226
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
drflac_oggbs::currentBytePos
drflac_uint64 currentBytePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55445
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
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_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
MA_VERSION_REVISION
#define MA_VERSION_REVISION
Definition: pvrecorder/src/miniaudio/miniaudio.h:1501
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_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_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_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
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
ma_context::pthread_mutex_destroy
ma_proc pthread_mutex_destroy
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3566
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_VERSION_MAJOR
#define MA_VERSION_MAJOR
Definition: pvrecorder/src/miniaudio/miniaudio.h:1499
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
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
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
DRWAV_ZERO_MEMORY
#define DRWAV_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46297
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
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
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
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
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
ma_resampler
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2260
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
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_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
DRMP3_IS_DIRECTORY
#define DRMP3_IS_DIRECTORY
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:183
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_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_CHANNEL_AUX_17
#define MA_CHANNEL_AUX_17
Definition: pvrecorder/src/miniaudio/miniaudio.h:1746
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
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
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
DRMP3_NO_HOST
#define DRMP3_NO_HOST
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:217
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_STATE_STOPPED
#define MA_STATE_STOPPED
Definition: pvrecorder/src/miniaudio/miniaudio.h:3104
ma_device_config::capture
struct ma_device_config::@98 capture
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
ma_aaudio_usage_notification_ringtone
@ ma_aaudio_usage_notification_ringtone
Definition: pvrecorder/src/miniaudio/miniaudio.h:3316
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
DRWAV_TOO_BIG
#define DRWAV_TOO_BIG
Definition: porcupine/demo/c/dr_libs/dr_wav.h:209
ma_thread_priority
ma_thread_priority
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2812
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_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_aaudio_usage_alarm
@ ma_aaudio_usage_alarm
Definition: pvrecorder/src/miniaudio/miniaudio.h:3307
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
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
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_aaudio_usage_game
@ ma_aaudio_usage_game
Definition: pvrecorder/src/miniaudio/miniaudio.h:3312
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
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_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
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
drwav_fmt::channels
drwav_uint16 channels
Definition: porcupine/demo/c/dr_libs/dr_wav.h:308
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
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
ma_backend_sndio
@ ma_backend_sndio
Definition: pvrecorder/src/miniaudio/miniaudio.h:3126
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
ma_read_proc
ma_result(* ma_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead, size_t *pBytesRead)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6158
DRFLAC_FALSE
#define DRFLAC_FALSE
Definition: porcupine/demo/c/dr_libs/dr_flac.h:272
python.setup.name
name
Definition: porcupine/binding/python/setup.py:69
DRWAV_BAD_MESSAGE
#define DRWAV_BAD_MESSAGE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:229
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_bpf2_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2027
ma_standard_channel_map_default
@ ma_standard_channel_map_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:1938
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_CHANNEL_TOP_CENTER
#define MA_CHANNEL_TOP_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1722
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
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
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_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_hpf1_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1959
DRWAV_NO_DATA_AVAILABLE
#define DRWAV_NO_DATA_AVAILABLE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:230
ma_opensl_stream_type
ma_opensl_stream_type
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1799
DRWAV_INTERRUPT
#define DRWAV_INTERRUPT
Definition: porcupine/demo/c/dr_libs/dr_wav.h:219
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
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
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
drwav_metadata_type_list_info_tracknumber
@ drwav_metadata_type_list_info_tracknumber
Definition: porcupine/demo/c/dr_libs/dr_wav.h:483
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_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
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
drflac_cache_t
drflac_uint32 drflac_cache_t
Definition: porcupine/demo/c/dr_libs/dr_flac.h:337
drwav_fmt::extendedSize
drwav_uint16 extendedSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:323
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
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
DRMP3_ALREADY_IN_USE
#define DRMP3_ALREADY_IN_USE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:191
drwav::dataChunkDataSize
drwav_uint64 dataChunkDataSize
Definition: porcupine/demo/c/dr_libs/dr_wav.h:847
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_BAD_ADDRESS
#define MA_BAD_ADDRESS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1791
ma_notch2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2075
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_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
DRMP3_DIRECTORY_NOT_EMPTY
#define DRMP3_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:184
drflac_read_proc
size_t(* drflac_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: porcupine/demo/c/dr_libs/dr_flac.h:510
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
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_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_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_PROTOCOL_FAMILY_NOT_SUPPORTED
#define MA_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1809
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_uint64
unsigned long long ma_uint64
Definition: pvrecorder/src/miniaudio/miniaudio.h:1570
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_linear_resampler_config::lpfOrder
ma_uint32 lpfOrder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2211
ma_backend_null
@ ma_backend_null
Definition: pvrecorder/src/miniaudio/miniaudio.h:3136
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_METADATA_BLOCK_TYPE_INVALID
#define DRFLAC_METADATA_BLOCK_TYPE_INVALID
Definition: porcupine/demo/c/dr_libs/dr_flac.h:348
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_opensl_recording_preset_voice_communication
@ ma_opensl_recording_preset_voice_communication
Definition: pvrecorder/src/miniaudio/miniaudio.h:3295
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_wav::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40860
ma_opensl_stream_type_system
@ ma_opensl_stream_type_system
Definition: pvrecorder/src/miniaudio/miniaudio.h:3281
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_loshelf2_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2132
drwav_acid_flag_stretch
@ drwav_acid_flag_stretch
Definition: porcupine/demo/c/dr_libs/dr_wav.h:626
ma_standard_sample_rate_32000
@ ma_standard_sample_rate_32000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1893
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
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
ma_device_info::id
ma_device_id id
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3076
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_uintptr
ma_uint32 ma_uintptr
Definition: pvrecorder/src/miniaudio/miniaudio.h:1578
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_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
ma_lcg::state
ma_int32 state
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5390
ma_context::threadStackSize
size_t threadStackSize
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2205
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
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
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_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
DRMP3_PATH_TOO_LONG
#define DRMP3_PATH_TOO_LONG
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:180
ma_context::pthread_attr_setschedpolicy
ma_proc pthread_attr_setschedpolicy
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3575
drflac_bool8
drflac_uint8 drflac_bool8
Definition: porcupine/demo/c/dr_libs/dr_flac.h:269
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_ALREADY_IN_USE
#define DRWAV_ALREADY_IN_USE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:221
drwav_metadata::inst
drwav_inst inst
Definition: porcupine/demo/c/dr_libs/dr_wav.h:796
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_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
MA_MAX_FILTER_ORDER
#define MA_MAX_FILTER_ORDER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1851
ma_linear_resampler_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2208
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_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_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
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
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
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
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
DRMP3_TOO_BIG
#define DRMP3_TOO_BIG
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:179
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
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
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
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
DRMP3_DEADLOCK
#define DRMP3_DEADLOCK
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:195
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_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
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
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
ma_resample_algorithm
ma_resample_algorithm
Definition: pvrecorder/src/miniaudio/miniaudio.h:2489
MA_LOG_LEVEL_DEBUG
#define MA_LOG_LEVEL_DEBUG
Definition: pvrecorder/src/miniaudio/miniaudio.h:1686
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
MA_THREADCALL
#define MA_THREADCALL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4265
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
drflac::firstFLACFramePosInBytes
drflac_uint64 firstFLACFramePosInBytes
Definition: porcupine/demo/c/dr_libs/dr_flac.h:737
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
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
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
drflac_bs
Definition: porcupine/demo/c/dr_libs/dr_flac.h:581
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
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_metadata_type_list_info_comment
@ drwav_metadata_type_list_info_comment
Definition: porcupine/demo/c/dr_libs/dr_wav.h:479
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
NULL
#define NULL
Definition: pvrecorder/src/miniaudio/miniaudio.h:1596
ma_context_config::alsa
struct ma_context_config::@104 alsa
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
drwav::cachedFrames
drwav_int32 cachedFrames[4]
Definition: porcupine/demo/c/dr_libs/dr_wav.h:888
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_encoding_format_wav
@ ma_encoding_format_wav
Definition: pvrecorder/src/miniaudio/miniaudio.h:6173
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_opensl_recording_preset_voice_unprocessed
@ ma_opensl_recording_preset_voice_unprocessed
Definition: pvrecorder/src/miniaudio/miniaudio.h:3296
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
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
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_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_encoder::pInternalEncoder
void * pInternalEncoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5333
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_encoding_format_mp3
@ ma_encoding_format_mp3
Definition: pvrecorder/src/miniaudio/miniaudio.h:6175
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
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
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
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_audio_buffer_config::pData
const void * pData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4591
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
drflac_seek_origin_start
@ drflac_seek_origin_start
Definition: porcupine/demo/c/dr_libs/dr_flac.h:382
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_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_CHANNEL_AUX_9
#define MA_CHANNEL_AUX_9
Definition: pvrecorder/src/miniaudio/miniaudio.h:1738
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_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
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_waveform_config::amplitude
double amplitude
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5367
ma_clip_pcm_frames_f32
static MA_INLINE void ma_clip_pcm_frames_f32(float *p, ma_uint64 frameCount, ma_uint32 channels)
Definition: pvrecorder/src/miniaudio/miniaudio.h:5933
DRFLAC_BAD_MESSAGE
#define DRFLAC_BAD_MESSAGE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51388
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
MA_IN_PROGRESS
#define MA_IN_PROGRESS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1817
DRMP3_INVALID_ARGS
#define DRMP3_INVALID_ARGS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:170
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
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
ma_encoding_format
ma_encoding_format
Definition: pvrecorder/src/miniaudio/miniaudio.h:6170
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_aaudio_input_preset
ma_aaudio_input_preset
Definition: pvrecorder/src/miniaudio/miniaudio.h:3332
ma_device_descriptor::periodSizeInFrames
ma_uint32 periodSizeInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2052
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_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
ma_device::lastProcessedFramePlayback
ma_uint64 lastProcessedFramePlayback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3845
fileno
int fileno(FILE *stream)
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
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
drwav_fmt::sampleRate
drwav_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_wav.h:311
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
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_BUSY
#define MA_BUSY
Definition: pvrecorder/src/miniaudio/miniaudio.h:1786
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
ma_context_config::pApplicationName
const char * pApplicationName
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3172
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_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
ma_hishelf_config
struct ma_hishelf2_config ma_hishelf_config
DRFLAC_VERSION_REVISION
#define DRFLAC_VERSION_REVISION
Definition: porcupine/demo/c/dr_libs/dr_flac.h:235
DRFLAC_PROTOCOL_UNAVAILABLE
#define DRFLAC_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51397
ma_thread_priority_low
@ ma_thread_priority_low
Definition: pvrecorder/src/miniaudio/miniaudio.h:1968
DRMP3_BAD_PIPE
#define DRMP3_BAD_PIPE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:194
drflac_oggbs::currentPageHeader
drflac_ogg_page_header currentPageHeader
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55449
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
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
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::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_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
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
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
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
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_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_seek_proc
ma_result(* ma_seek_proc)(void *pUserData, ma_int64 offset, ma_seek_origin origin)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6159
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_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_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
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
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
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_log_callback_proc
void(* ma_log_callback_proc)(void *pUserData, ma_uint32 level, const char *pMessage)
Definition: pvrecorder/src/miniaudio/miniaudio.h:2055
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
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
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
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
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_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_type_square
@ ma_waveform_type_square
Definition: pvrecorder/src/miniaudio/miniaudio.h:6449
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_format_s32
@ ma_format_s32
Definition: pvrecorder/src/miniaudio/miniaudio.h:1882
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_aaudio_content_type_sonification
@ ma_aaudio_content_type_sonification
Definition: pvrecorder/src/miniaudio/miniaudio.h:3327
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
drmp3_int16
signed short drmp3_int16
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:106
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
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
DRWAV_NO_SPACE
#define DRWAV_NO_SPACE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:216
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
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
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
drflac_oggbs::pageDataSize
drflac_uint32 pageDataSize
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55451
MA_DEVICE_TYPE_NOT_SUPPORTED
#define MA_DEVICE_TYPE_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1823
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
DRWAV_INVALID_DATA
#define DRWAV_INVALID_DATA
Definition: porcupine/demo/c/dr_libs/dr_wav.h:231
ma_device_config::lpfOrder
ma_uint32 lpfOrder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3118
drflac_frame::header
drflac_frame_header header
Definition: porcupine/demo/c/dr_libs/dr_flac.h:676
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
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
ma_standard_channel_map_vorbis
@ ma_standard_channel_map_vorbis
Definition: pvrecorder/src/miniaudio/miniaudio.h:1934
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
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
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
DRWAV_NO_MESSAGE
#define DRWAV_NO_MESSAGE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:228
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_encoder_write_pcm_frames_proc
ma_uint64(* ma_encoder_write_pcm_frames_proc)(ma_encoder *pEncoder, const void *pFramesIn, ma_uint64 frameCount)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6401
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
ma_audio_buffer_ref::pData
const void * pData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4569
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
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_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
ma_bpf_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2043
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
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
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
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
drflac::_noSeekTableSeek
drflac_bool32 _noSeekTableSeek
Definition: porcupine/demo/c/dr_libs/dr_flac.h:754
DRWAV_DEADLOCK
#define DRWAV_DEADLOCK
Definition: porcupine/demo/c/dr_libs/dr_wav.h:225
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::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
MA_AT_END
#define MA_AT_END
Definition: pvrecorder/src/miniaudio/miniaudio.h:1784
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
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
DRFLAC_SUBFRAME_RESERVED
#define DRFLAC_SUBFRAME_RESERVED
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51416
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_context::pthread_attr_getschedparam
ma_proc pthread_attr_getschedparam
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3576
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_standard_channel_map_sndio
@ ma_standard_channel_map_sndio
Definition: pvrecorder/src/miniaudio/miniaudio.h:1936
ma_audio_buffer
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4597
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
DRMP3_HDR_TEST_MPEG1
#define DRMP3_HDR_TEST_MPEG1(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59349
DRMP3_NOT_DIRECTORY
#define DRMP3_NOT_DIRECTORY
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:182
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
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
DRMP3_ALREADY_EXISTS
#define DRMP3_ALREADY_EXISTS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:176
drmp3_L3_gr_info::count1_table
drmp3_uint8 count1_table
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59500
MA_API_NOT_FOUND
#define MA_API_NOT_FOUND
Definition: pvrecorder/src/miniaudio/miniaudio.h:1827
MA_LOG_LEVEL_INFO
#define MA_LOG_LEVEL_INFO
Definition: pvrecorder/src/miniaudio/miniaudio.h:1687
C89ATOMIC_INLINE
#define C89ATOMIC_INLINE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2641
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
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_SIZE_MAX
#define MA_SIZE_MAX
Definition: pvrecorder/src/miniaudio/miniaudio.h:1602
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_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_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
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_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_aaudio_usage_assistance_accessibility
@ ma_aaudio_usage_assistance_accessibility
Definition: pvrecorder/src/miniaudio/miniaudio.h:3308
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_lpf_config::order
ma_uint32 order
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1923
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
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_resource_format
ma_resource_format
Definition: pvrecorder/src/miniaudio/miniaudio.h:6165
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
ma_standard_sample_rate_44100
@ ma_standard_sample_rate_44100
Definition: pvrecorder/src/miniaudio/miniaudio.h:1891
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
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
ma_biquad::b2
ma_biquad_coefficient b2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1863
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_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_backend_audio4
@ ma_backend_audio4
Definition: pvrecorder/src/miniaudio/miniaudio.h:3127
DRMP3_VERSION_MAJOR
#define DRMP3_VERSION_MAJOR
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:96
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
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
MA_CHANNEL_FRONT_LEFT
#define MA_CHANNEL_FRONT_LEFT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1711
ma_context_sizeof
MA_API size_t ma_context_sizeof(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26779
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
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_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
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
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
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_context::pthread_cond_wait
ma_proc pthread_cond_wait
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3571
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_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_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
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
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
drwav_metadata_type_cue
@ drwav_metadata_type_cue
Definition: porcupine/demo/c/dr_libs/dr_wav.h:460
ma_opensl_stream_type_default
@ ma_opensl_stream_type_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:3279
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_encoder_init_proc
ma_result(* ma_encoder_init_proc)(ma_encoder *pEncoder)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6399
drmp3::pcmFramesRemainingInMP3Frame
drmp3_uint32 pcmFramesRemainingInMP3Frame
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:353
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_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
DRWAV_VERSION_MAJOR
#define DRWAV_VERSION_MAJOR
Definition: porcupine/demo/c/dr_libs/dr_wav.h:126
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
ma_ios_session_category_option_allow_bluetooth_a2dp
@ ma_ios_session_category_option_allow_bluetooth_a2dp
Definition: pvrecorder/src/miniaudio/miniaudio.h:3272
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
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_int8
signed char ma_int8
Definition: pvrecorder/src/miniaudio/miniaudio.h:1552
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
drwav::readCursorInPCMFrames
drwav_uint64 readCursorInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_wav.h:856
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
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
ma_device_info
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3073
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_CHANNEL_SIDE_RIGHT
#define MA_CHANNEL_SIDE_RIGHT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1721
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_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
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
drwav_acid_flag
drwav_acid_flag
Definition: porcupine/demo/c/dr_libs/dr_wav.h:622
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
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
MA_CHANNEL_AUX_6
#define MA_CHANNEL_AUX_6
Definition: pvrecorder/src/miniaudio/miniaudio.h:1735
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
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_metadata::vorbis_comment
struct drflac_metadata::@0::@4 vorbis_comment
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
DRFLAC_DOES_NOT_EXIST
#define DRFLAC_DOES_NOT_EXIST
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51364
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
drflac_container_ogg
@ drflac_container_ogg
Definition: porcupine/demo/c/dr_libs/dr_flac.h:376
ma_aaudio_content_type_default
@ ma_aaudio_content_type_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:3324
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_CHANNEL_AUX_27
#define MA_CHANNEL_AUX_27
Definition: pvrecorder/src/miniaudio/miniaudio.h:1756
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_device::operation
ma_uint32 operation
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3839
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
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
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_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_aaudio_content_type_music
@ ma_aaudio_content_type_music
Definition: pvrecorder/src/miniaudio/miniaudio.h:3326
drflac_init_info::oggSerial
drflac_uint32 oggSerial
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54807
ma_hpf2
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1974
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_device::thread
ma_thread thread
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3597
ma_loshelf2_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2124
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_encoder::onInit
ma_encoder_init_proc onInit
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5329
ma_encoder::onWrite
ma_encoder_write_proc onWrite
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5327
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
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
ma_waveform_type_triangle
@ ma_waveform_type_triangle
Definition: pvrecorder/src/miniaudio/miniaudio.h:6450
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_standard_sample_rate_352800
@ ma_standard_sample_rate_352800
Definition: pvrecorder/src/miniaudio/miniaudio.h:1906
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_PROTOCOL_FAMILY_NOT_SUPPORTED
#define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:210
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
ma_resampler_config::lpfOrder
ma_uint32 lpfOrder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2249
ma_pcm_f32_to_u8
MA_API void ma_pcm_f32_to_u8(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29543
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_log_postf
MA_API ma_result ma_log_postf(ma_log *pLog, ma_uint32 level, const char *pFormat,...) MA_ATTRIBUTE_FORMAT(3
ma_backend_coreaudio
@ ma_backend_coreaudio
Definition: pvrecorder/src/miniaudio/miniaudio.h:3125
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
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
drmp3_int64
signed long long drmp3_int64
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:121
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_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
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_CHANNEL_AUX_28
#define MA_CHANNEL_AUX_28
Definition: pvrecorder/src/miniaudio/miniaudio.h:1757
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
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_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_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_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_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_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
ma_device_config::opensl
struct ma_device_config::@178 opensl
python.setup.description
description
Definition: porcupine/binding/python/setup.py:73
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
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_seek_proc
drwav_bool32(* drwav_seek_proc)(void *pUserData, int offset, drwav_seek_origin origin)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:381
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_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_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
DRFLAC_IN_PROGRESS
#define DRFLAC_IN_PROGRESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51407
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_noise_type_pink
@ ma_noise_type_pink
Definition: pvrecorder/src/miniaudio/miniaudio.h:6482
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
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
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_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_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
DRMP3_NOT_IMPLEMENTED
#define DRMP3_NOT_IMPLEMENTED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:197
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_BAD_SEEK
#define MA_BAD_SEEK
Definition: pvrecorder/src/miniaudio/miniaudio.h:1792
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__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_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
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
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
DRFLAC_SUBFRAME_VERBATIM
#define DRFLAC_SUBFRAME_VERBATIM
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51413
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_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
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
DRMP3_CONNECTION_RESET
#define DRMP3_CONNECTION_RESET
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:213
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_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
drwav_metadata_location_inside_adtl_list
@ drwav_metadata_location_inside_adtl_list
Definition: porcupine/demo/c/dr_libs/dr_wav.h:772
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
ma_backend_alsa
@ ma_backend_alsa
Definition: pvrecorder/src/miniaudio/miniaudio.h:3130
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
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_opensl_stream_type_media
@ ma_opensl_stream_type_media
Definition: pvrecorder/src/miniaudio/miniaudio.h:3283
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
DRFLAC_TOO_MANY_OPEN_FILES
#define DRFLAC_TOO_MANY_OPEN_FILES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51366
DRWAV_ASSERT
#define DRWAV_ASSERT(expression)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46282
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
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
drwav_metadata_type_none
@ drwav_metadata_type_none
Definition: porcupine/demo/c/dr_libs/dr_wav.h:446
ma_standard_sample_rate_176400
@ ma_standard_sample_rate_176400
Definition: pvrecorder/src/miniaudio/miniaudio.h:1899
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
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
ma_seek_origin_end
@ ma_seek_origin_end
Definition: pvrecorder/src/miniaudio/miniaudio.h:6118
drflac_init_info::pUserDataMD
void * pUserDataMD
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54795
ma_decoder_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5172
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_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: pvrecorder/src/miniaudio/miniaudio.h:3516
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_context::pthread_attr_destroy
ma_proc pthread_attr_destroy
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3574
MA_ASSERT
#define MA_ASSERT(condition)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:770
ma_dither_mode_none
@ ma_dither_mode_none
Definition: pvrecorder/src/miniaudio/miniaudio.h:1867
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_waveform_type
ma_waveform_type
Definition: pvrecorder/src/miniaudio/miniaudio.h:6442
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_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_resampler_uninit
MA_API void ma_resampler_uninit(ma_resampler *pResampler)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:33154
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
ma_pcm_s24_to_f32
MA_API void ma_pcm_s24_to_f32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29039
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_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_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_data_converter_config::allowDynamicSampleRate
ma_bool32 allowDynamicSampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2417
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
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
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
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_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_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
MA_DEVICE_ALREADY_INITIALIZED
#define MA_DEVICE_ALREADY_INITIALIZED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1833
ma_channel_converter_config::channelMapIn
ma_channel channelMapIn[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2363
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_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_pcm_s24_to_s16
MA_API void ma_pcm_s24_to_s16(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28895
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
drwav_uint8
unsigned char drwav_uint8
Definition: porcupine/demo/c/dr_libs/dr_wav.h:135
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
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
MA_CHANNEL_FRONT_RIGHT
#define MA_CHANNEL_FRONT_RIGHT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1712
drwav_uintptr
drwav_uint32 drwav_uintptr
Definition: porcupine/demo/c/dr_libs/dr_wav.h:160
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/dr_libs/dr_wav.h:407
drflac_frame::pcmFramesRemaining
drflac_uint32 pcmFramesRemaining
Definition: porcupine/demo/c/dr_libs/dr_flac.h:682
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
ma_backend_oss
@ ma_backend_oss
Definition: pvrecorder/src/miniaudio/miniaudio.h:3128
DRFLAC_DIRECTORY_NOT_EMPTY
#define DRFLAC_DIRECTORY_NOT_EMPTY
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51373
ma_handle
void * ma_handle
Definition: pvrecorder/src/miniaudio/miniaudio.h:1586
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_standard_sample_rate_192000
@ ma_standard_sample_rate_192000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1900
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
drwav_container_riff
@ drwav_container_riff
Definition: porcupine/demo/c/dr_libs/dr_wav.h:276
drwav_metadata_location_invalid
@ drwav_metadata_location_invalid
Definition: porcupine/demo/c/dr_libs/dr_wav.h:769
ma_device_config::usage
ma_aaudio_usage usage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2011
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
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_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
DRMP3_IO_ERROR
#define DRMP3_IO_ERROR
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:188
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
MA_CHANNEL_AUX_19
#define MA_CHANNEL_AUX_19
Definition: pvrecorder/src/miniaudio/miniaudio.h:1748
ma_uint8
unsigned char ma_uint8
Definition: pvrecorder/src/miniaudio/miniaudio.h:1553
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_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__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_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
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
DRWAV_BAD_SEEK
#define DRWAV_BAD_SEEK
Definition: porcupine/demo/c/dr_libs/dr_wav.h:223
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
ma_bpf_config::order
ma_uint32 order
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2045
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_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_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_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
ma_aaudio_usage_assistance_sonification
@ ma_aaudio_usage_assistance_sonification
Definition: pvrecorder/src/miniaudio/miniaudio.h:3310
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
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
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
ma_aaudio_usage_vehicle_status
@ ma_aaudio_usage_vehicle_status
Definition: pvrecorder/src/miniaudio/miniaudio.h:3306
RESAMPLER_ERR_OVERFLOW
@ RESAMPLER_ERR_OVERFLOW
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/speex_resampler.h:109
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
drflac_align
#define drflac_align(x, a)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51423
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
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
ma_format_count
@ ma_format_count
Definition: pvrecorder/src/miniaudio/miniaudio.h:1884
ma_ios_session_category_playback
@ ma_ios_session_category_playback
Definition: pvrecorder/src/miniaudio/miniaudio.h:3258
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
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
drwav_smpl_loop::cuePointId
drwav_uint32 cuePointId
Definition: porcupine/demo/c/dr_libs/dr_wav.h:520
ma_aaudio_input_preset_generic
@ ma_aaudio_input_preset_generic
Definition: pvrecorder/src/miniaudio/miniaudio.h:3335
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
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
drmp3::dataConsumed
size_t dataConsumed
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:361
ma_event
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2868
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
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_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_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
MA_IO_ERROR
#define MA_IO_ERROR
Definition: pvrecorder/src/miniaudio/miniaudio.h:1787
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_ios_session_category_multi_route
@ ma_ios_session_category_multi_route
Definition: pvrecorder/src/miniaudio/miniaudio.h:3261
drwav_metadata_type_list_all_info_strings
@ drwav_metadata_type_list_all_info_strings
Definition: porcupine/demo/c/dr_libs/dr_wav.h:486
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_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
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
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_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
MA_CHANNEL_FRONT_RIGHT_CENTER
#define MA_CHANNEL_FRONT_RIGHT_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1718
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
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_performance_profile_low_latency
@ ma_performance_profile_low_latency
Definition: pvrecorder/src/miniaudio/miniaudio.h:1943
ma_bpf_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2044
ma_backend_dsound
@ ma_backend_dsound
Definition: pvrecorder/src/miniaudio/miniaudio.h:3123
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
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_CHANNEL_AUX_23
#define MA_CHANNEL_AUX_23
Definition: pvrecorder/src/miniaudio/miniaudio.h:1752
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
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
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_standard_sample_rate_24000
@ ma_standard_sample_rate_24000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1894
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
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_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_INVALID_ARGS
#define MA_INVALID_ARGS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1769
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
MA_PATH_TOO_LONG
#define MA_PATH_TOO_LONG
Definition: pvrecorder/src/miniaudio/miniaudio.h:1779
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_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
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_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_standard_sample_rate_count
@ ma_standard_sample_rate_count
Definition: pvrecorder/src/miniaudio/miniaudio.h:1911
ma_backend_callbacks::onDeviceDataLoopWakeup
ma_result(* onDeviceDataLoopWakeup)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2135
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_performance_profile
ma_performance_profile
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1816
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
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
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
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
drwav_acid_flag_one_shot
@ drwav_acid_flag_one_shot
Definition: porcupine/demo/c/dr_libs/dr_wav.h:624
ma_flac::ds
ma_data_source_base ds
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41501
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_linear_resampler_config::lpfNyquistFactor
double lpfNyquistFactor
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2212
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
DRMP3_OUT_OF_RANGE
#define DRMP3_OUT_OF_RANGE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:173
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
ma_stream_format
ma_stream_format
Definition: pvrecorder/src/miniaudio/miniaudio.h:1854
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_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
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_ACCESS_DENIED
#define DRWAV_ACCESS_DENIED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:204
drwav__metadata_parser_stage
drwav__metadata_parser_stage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46893
DRWAV_AT_END
#define DRWAV_AT_END
Definition: porcupine/demo/c/dr_libs/dr_wav.h:251
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_thread_priority_highest
@ ma_thread_priority_highest
Definition: pvrecorder/src/miniaudio/miniaudio.h:1971
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_CHANNEL_AUX_31
#define MA_CHANNEL_AUX_31
Definition: pvrecorder/src/miniaudio/miniaudio.h:1760
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
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
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
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
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_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
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_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_uninit
DRWAV_API drwav_result drwav_uninit(drwav *pWav)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:49216
ma_data_converter_config::speex
struct ma_data_converter_config::@80::@82 speex
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_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
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_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
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
ma_data_source_get_next_proc
ma_data_source *(* ma_data_source_get_next_proc)(ma_data_source *pDataSource)
Definition: pvrecorder/src/miniaudio/miniaudio.h:5991
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_performance_profile_conservative
@ ma_performance_profile_conservative
Definition: pvrecorder/src/miniaudio/miniaudio.h:1944
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
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
MA_CHANNEL_TOP_BACK_LEFT
#define MA_CHANNEL_TOP_BACK_LEFT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1726
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
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
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_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
ma_ptr
void * ma_ptr
Definition: pvrecorder/src/miniaudio/miniaudio.h:1587
ma_uint16
unsigned short ma_uint16
Definition: pvrecorder/src/miniaudio/miniaudio.h:1555
drwav_list_labelled_cue_region::stringLength
drwav_uint32 stringLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:752
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
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
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_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
add
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
ma_device::name
char name[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3620
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
ma_pcm_s32_to_f32
MA_API void ma_pcm_s32_to_f32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29410
ma_device::quality
int quality
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3615
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_pcm_u8_to_s32
MA_API void ma_pcm_u8_to_s32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28242
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_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
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_smpl_loop::sampleFraction
drwav_uint32 sampleFraction
Definition: porcupine/demo/c/dr_libs/dr_wav.h:532
DR_WAVE_FORMAT_DVI_ADPCM
#define DR_WAVE_FORMAT_DVI_ADPCM
Definition: porcupine/demo/c/dr_libs/dr_wav.h:259
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
DRWAV_BAD_PIPE
#define DRWAV_BAD_PIPE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:224
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_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_int16
signed short ma_int16
Definition: pvrecorder/src/miniaudio/miniaudio.h:1554
ma_bpf
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2050
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
ma_aaudio_usage_assistance_navigation_guidance
@ ma_aaudio_usage_assistance_navigation_guidance
Definition: pvrecorder/src/miniaudio/miniaudio.h:3309
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_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
DRFLAC_TRUE
#define DRFLAC_TRUE
Definition: porcupine/demo/c/dr_libs/dr_flac.h:271
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
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
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_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_thread_priority_normal
@ ma_thread_priority_normal
Definition: pvrecorder/src/miniaudio/miniaudio.h:1969
ma_waveform
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5373
ma_backend
ma_backend
Definition: pvrecorder/src/miniaudio/miniaudio.h:3120
ma_aaudio_input_preset_voice_recognition
@ ma_aaudio_input_preset_voice_recognition
Definition: pvrecorder/src/miniaudio/miniaudio.h:3338
ma_context_config::logCallback
ma_log_proc logCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3162
drmp3_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:326
MA_INVALID_OPERATION
#define MA_INVALID_OPERATION
Definition: pvrecorder/src/miniaudio/miniaudio.h:1770
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_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
ma_log_proc
void(* ma_log_proc)(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message)
Definition: pvrecorder/src/miniaudio/miniaudio.h:3235
drwav_smpl
Definition: porcupine/demo/c/dr_libs/dr_wav.h:538
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
MA_CHANNEL_AUX_18
#define MA_CHANNEL_AUX_18
Definition: pvrecorder/src/miniaudio/miniaudio.h:1747
ma_device::duplexRB
ma_duplex_rb duplexRB
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2626
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_audio_buffer_ref
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4562
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
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_FAILED_TO_START_BACKEND_DEVICE
#define MA_FAILED_TO_START_BACKEND_DEVICE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1840
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_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
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_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_opensl_stream_type_ring
@ ma_opensl_stream_type_ring
Definition: pvrecorder/src/miniaudio/miniaudio.h:3282
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
ma_device::priorRunTime
double priorRunTime
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3842
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
drwav_acid_flag_root_note_set
@ drwav_acid_flag_root_note_set
Definition: porcupine/demo/c/dr_libs/dr_wav.h:625
MA_CHANNEL_BACK_RIGHT
#define MA_CHANNEL_BACK_RIGHT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1716
ma_device_id::winmm
ma_uint32 winmm
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3059
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
drwav_metadata_type_list_info_date
@ drwav_metadata_type_list_info_date
Definition: porcupine/demo/c/dr_libs/dr_wav.h:480
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_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_ALREADY_CONNECTED
#define DRWAV_ALREADY_CONNECTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:244
ma_loshelf2_config::frequency
double frequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2135
ma_opensl_stream_type_voice
@ ma_opensl_stream_type_voice
Definition: pvrecorder/src/miniaudio/miniaudio.h:3280
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_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_ios_session_category_solo_ambient
@ ma_ios_session_category_solo_ambient
Definition: pvrecorder/src/miniaudio/miniaudio.h:3257
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
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
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
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
ma_pcm_rb
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2593
DRWAV_INVALID_FILE
#define DRWAV_INVALID_FILE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:208
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
DRFLAC_API
#define DRFLAC_API
Definition: porcupine/demo/c/dr_libs/dr_flac.h:299
MA_STATE_UNINITIALIZED
#define MA_STATE_UNINITIALIZED
Definition: pvrecorder/src/miniaudio/miniaudio.h:3103
MA_OUT_OF_RANGE
#define MA_OUT_OF_RANGE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1772
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_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_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
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_MAX_LOG_CALLBACKS
#define MA_MAX_LOG_CALLBACKS
Definition: pvrecorder/src/miniaudio/miniaudio.h:2052
DRMP3_PEEK_BITS
#define DRMP3_PEEK_BITS(n)
MA_CHANNEL_AUX_26
#define MA_CHANNEL_AUX_26
Definition: pvrecorder/src/miniaudio/miniaudio.h:1755
MA_MAX_CHANNELS
#define MA_MAX_CHANNELS
Definition: pvrecorder/src/miniaudio/miniaudio.h:1846
ma_data_source_base::loopEndInFrames
ma_uint64 loopEndInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4532
MA_CHANNEL_AUX_21
#define MA_CHANNEL_AUX_21
Definition: pvrecorder/src/miniaudio/miniaudio.h:1750
ma_apply_volume_factor_pcm_frames_s24
MA_API void ma_apply_volume_factor_pcm_frames_s24(void *pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27974
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_TOO_BIG
#define MA_TOO_BIG
Definition: pvrecorder/src/miniaudio/miniaudio.h:1778
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_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
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_subframe::pSamplesS32
drflac_int32 * pSamplesS32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:637
DRWAV_CANCELLED
#define DRWAV_CANCELLED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:249
drflac_bs::cache
drflac_cache_t cache
Definition: porcupine/demo/c/dr_libs/dr_flac.h:614
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_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
ma_peak_config
struct ma_peak2_config ma_peak_config
drmp3_L3_gr_info::sfbtab
const drmp3_uint8 * sfbtab
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59496
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_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
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_NOT_SOCKET
#define MA_NOT_SOCKET
Definition: pvrecorder/src/miniaudio/miniaudio.h:1804
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_DOES_NOT_EXIST
#define MA_DOES_NOT_EXIST
Definition: pvrecorder/src/miniaudio/miniaudio.h:1774
drwav_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/dr_wav.h:409
DRWAV_NOT_SOCKET
#define DRWAV_NOT_SOCKET
Definition: porcupine/demo/c/dr_libs/dr_wav.h:235
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
ma_rb::ownsBuffer
ma_bool32 ownsBuffer
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2573
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_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_LOG_LEVEL_ERROR
#define MA_LOG_LEVEL_ERROR
Definition: pvrecorder/src/miniaudio/miniaudio.h:1689
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
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_standard_sample_rate_max
@ ma_standard_sample_rate_max
Definition: pvrecorder/src/miniaudio/miniaudio.h:1910
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_NO_NETWORK
#define DRWAV_NO_NETWORK
Definition: porcupine/demo/c/dr_libs/dr_wav.h:233
MA_OPEN_MODE_WRITE
#define MA_OPEN_MODE_WRITE
Definition: pvrecorder/src/miniaudio/miniaudio.h:6112
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
MA_CHANNEL_AUX_22
#define MA_CHANNEL_AUX_22
Definition: pvrecorder/src/miniaudio/miniaudio.h:1751
drflac__crc32_table
static drflac_uint32 drflac__crc32_table[]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:55254
DRMP3_UNAVAILABLE
#define DRMP3_UNAVAILABLE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:190
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
drwav_bext::maxMomentaryLoudness
drwav_uint16 maxMomentaryLoudness
Definition: porcupine/demo/c/dr_libs/dr_wav.h:708
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
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_context::_unused
int _unused
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3531
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
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
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
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
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_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_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_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_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
ma_backend_pulseaudio
@ ma_backend_pulseaudio
Definition: pvrecorder/src/miniaudio/miniaudio.h:3129
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
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
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
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
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
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_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_context_config::noAudioSessionDeactivate
ma_bool32 noAudioSessionDeactivate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2161
ma_data_source_callbacks
struct ma_data_source_vtable ma_data_source_callbacks
MA_NO_MESSAGE
#define MA_NO_MESSAGE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1797
MA_CHANNEL_TOP_FRONT_LEFT
#define MA_CHANNEL_TOP_FRONT_LEFT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1723
DRMP3_PROTOCOL_UNAVAILABLE
#define DRMP3_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:208
ma_resampler_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2242
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_data_source_base::loopBegInFrames
ma_uint64 loopBegInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4531
MA_CHANNEL_LEFT
#define MA_CHANNEL_LEFT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1761
c89atomic_uint64
unsigned long long c89atomic_uint64
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2590
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_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_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_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_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_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
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_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
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
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
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_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_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
ma_device_config::quality
int quality
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3122
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_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
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_FALSE
#define DRMP3_FALSE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:135
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_vfs
void ma_vfs
Definition: pvrecorder/src/miniaudio/miniaudio.h:6108
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
drwav_acid_flag_acidizer
@ drwav_acid_flag_acidizer
Definition: porcupine/demo/c/dr_libs/dr_wav.h:628
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_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_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
drflac_seek_origin_current
@ drflac_seek_origin_current
Definition: porcupine/demo/c/dr_libs/dr_flac.h:383
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
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
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
ma_biquad_coefficient::s32
ma_int32 s32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1844
MA_CHANNEL_BACK_LEFT
#define MA_CHANNEL_BACK_LEFT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1715
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
DRMP3_STOP_BLOCK_TYPE
#define DRMP3_STOP_BLOCK_TYPE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59340
DRMP3_ACCESS_DENIED
#define DRMP3_ACCESS_DENIED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:174
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
drflac_container_unknown
@ drflac_container_unknown
Definition: porcupine/demo/c/dr_libs/dr_flac.h:377
ma_flac::onTell
ma_tell_proc onTell
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41504
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
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
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
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_ASSUME
#define MA_ASSUME(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:408
ma_aaudio_usage_voice_communication
@ ma_aaudio_usage_voice_communication
Definition: pvrecorder/src/miniaudio/miniaudio.h:3317
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_peak2_config::q
double q
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2106
MA_CHANNEL_LFE
#define MA_CHANNEL_LFE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1714
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
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
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
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
drwav_metadata_type_list_label
@ drwav_metadata_type_list_label
Definition: porcupine/demo/c/dr_libs/dr_wav.h:471
drflac_init_info::runningFilePos
drflac_uint64 runningFilePos
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54801
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_resource_format
ma_resource_format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5145
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
ma_device_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3129
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
ma_int64
signed long long ma_int64
Definition: pvrecorder/src/miniaudio/miniaudio.h:1569
DRWAV_BEXT_RESERVED_BYTES
#define DRWAV_BEXT_RESERVED_BYTES
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46887
drwav_smpl_loop_type
drwav_smpl_loop_type
Definition: porcupine/demo/c/dr_libs/dr_wav.h:510
drwav_metadata_type_list_info_title
@ drwav_metadata_type_list_info_title
Definition: porcupine/demo/c/dr_libs/dr_wav.h:477
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_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_expd
static MA_INLINE double ma_expd(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:793
ma_decoder::outputChannels
ma_uint32 outputChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5204
ma_context::pthread_cond_destroy
ma_proc pthread_cond_destroy
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3570
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
ma_encoding_format_unknown
@ ma_encoding_format_unknown
Definition: pvrecorder/src/miniaudio/miniaudio.h:6172
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
drwav__metadata_parser::stage
drwav__metadata_parser_stage stage
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:46903
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
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
ma_device_config::noAutoResample
ma_bool32 noAutoResample
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1993
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_opensl_stream_type_notification
@ ma_opensl_stream_type_notification
Definition: pvrecorder/src/miniaudio/miniaudio.h:3285
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_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_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_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
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
drwav_inst::fineTuneCents
drwav_int8 fineTuneCents
Definition: porcupine/demo/c/dr_libs/dr_wav.h:576
DRFLAC_METADATA_BLOCK_TYPE_CUESHEET
#define DRFLAC_METADATA_BLOCK_TYPE_CUESHEET
Definition: porcupine/demo/c/dr_libs/dr_flac.h:346
python.setup.version
version
Definition: porcupine/binding/python/setup.py:70
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_noise_type_brownian
@ ma_noise_type_brownian
Definition: pvrecorder/src/miniaudio/miniaudio.h:6483
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_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_device_id::jack
int jack
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3062
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_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_offset_pcm_frames_const_ptr_f32
static const MA_INLINE float * ma_offset_pcm_frames_const_ptr_f32(const float *p, ma_uint64 offsetInFrames, ma_uint32 channels)
Definition: pvrecorder/src/miniaudio/miniaudio.h:5926
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
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_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_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
drwav_write_proc
size_t(* drwav_write_proc)(void *pUserData, const void *pData, size_t bytesToWrite)
Definition: porcupine/demo/c/dr_libs/dr_wav.h:367
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
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_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
drmp3::decoder
drmp3dec decoder
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:342
DRMP3_IN_PROGRESS
#define DRMP3_IN_PROGRESS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:218
drflac_metadata::type
drflac_uint32 type
Definition: porcupine/demo/c/dr_libs/dr_flac.h:415
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
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
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
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
ma_device_type
ma_device_type
Definition: pvrecorder/src/miniaudio/miniaudio.h:3237
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
ma_thread_priority_lowest
@ ma_thread_priority_lowest
Definition: pvrecorder/src/miniaudio/miniaudio.h:1967
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_pcm_s24_to_s32
MA_API void ma_pcm_s24_to_s32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28965
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
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
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_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
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
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
drflac_uintptr
drflac_uint32 drflac_uintptr
Definition: porcupine/demo/c/dr_libs/dr_flac.h:267
MA_UNAVAILABLE
#define MA_UNAVAILABLE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1789
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_STATE_STARTING
#define MA_STATE_STARTING
Definition: pvrecorder/src/miniaudio/miniaudio.h:3106
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_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
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
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
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
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
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
drwav_metadata_type_all_including_unknown
@ drwav_metadata_type_all_including_unknown
Definition: porcupine/demo/c/dr_libs/dr_wav.h:501
c89atomic_int32
signed int c89atomic_int32
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:2576
drwav_metadata_type_list_labelled_cue_region
@ drwav_metadata_type_list_labelled_cue_region
Definition: porcupine/demo/c/dr_libs/dr_wav.h:473
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
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
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_event::lock
pthread_mutex_t lock
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:522
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_performance_profile
ma_performance_profile
Definition: pvrecorder/src/miniaudio/miniaudio.h:1941
ma_standard_sample_rate_16000
@ ma_standard_sample_rate_16000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1902
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
MA_CHANNEL_AUX_7
#define MA_CHANNEL_AUX_7
Definition: pvrecorder/src/miniaudio/miniaudio.h:1736
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_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_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
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
MA_BAD_PIPE
#define MA_BAD_PIPE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1793
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_backend_callbacks::onDeviceStop
ma_result(* onDeviceStop)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2131
drmp3::allocationCallbacks
drmp3_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:349
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
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_decoder::pVFS
ma_vfs * pVFS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4787
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
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
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
DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED
#define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:240
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
ma_waveform_type_sine
@ ma_waveform_type_sine
Definition: pvrecorder/src/miniaudio/miniaudio.h:6448
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_context_config::pulse
struct ma_context_config::@105 pulse
ma_context
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3210
MA_VERSION_MINOR
#define MA_VERSION_MINOR
Definition: pvrecorder/src/miniaudio/miniaudio.h:1500
drmp3::atEnd
drmp3_bool32 atEnd
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:363
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
ma_lcg
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5388
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_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
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
ma_seek_origin
ma_seek_origin
Definition: pvrecorder/src/miniaudio/miniaudio.h:6114
drflac_bs::unalignedCache
drflac_cache_t unalignedCache
Definition: porcupine/demo/c/dr_libs/dr_flac.h:601
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
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
drmp3_int8
signed char drmp3_int8
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:104
drwav_list_labelled_cue_region::sampleLength
drwav_uint32 sampleLength
Definition: porcupine/demo/c/dr_libs/dr_wav.h:740
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_get_bytes_per_frame
static MA_INLINE ma_uint32 ma_get_bytes_per_frame(ma_format format, ma_uint32 channels)
Definition: pvrecorder/src/miniaudio/miniaudio.h:2988
DRWAV_OUT_OF_MEMORY
#define DRWAV_OUT_OF_MEMORY
Definition: porcupine/demo/c/dr_libs/dr_wav.h:202
DRWAV_DOES_NOT_EXIST
#define DRWAV_DOES_NOT_EXIST
Definition: porcupine/demo/c/dr_libs/dr_wav.h:205
ma_version_string
const MA_API char * ma_version_string(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:707
c89atomic_memory_order_acquire
#define c89atomic_memory_order_acquire
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:3290
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
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
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
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
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_data_converter::hasPreFormatConversion
ma_bool32 hasPreFormatConversion
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2434
ma_audio_buffer_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4586
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
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
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
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
ma_flac::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:41506
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_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
drflac_close
DRFLAC_API void drflac_close(drflac *pFlac)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:56763
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_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_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
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_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__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_NO_SPACE
#define MA_NO_SPACE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1785
DRWAV_PROTOCOL_UNAVAILABLE
#define DRWAV_PROTOCOL_UNAVAILABLE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:238
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_device_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3103
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
ma_aaudio_usage_media
@ ma_aaudio_usage_media
Definition: pvrecorder/src/miniaudio/miniaudio.h:3313
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_init_info::channels
drflac_uint8 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:54797
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
MA_CHANNEL_BACK_CENTER
#define MA_CHANNEL_BACK_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1719
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_channel_mix_mode_simple
@ ma_channel_mix_mode_simple
Definition: pvrecorder/src/miniaudio/miniaudio.h:1922
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_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
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_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_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_device::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3588
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_standard_sample_rate_min
@ ma_standard_sample_rate_min
Definition: pvrecorder/src/miniaudio/miniaudio.h:1909
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_STATE_STARTED
#define MA_STATE_STARTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:3105
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_ios_session_category_option_default_to_speaker
@ ma_ios_session_category_option_default_to_speaker
Definition: pvrecorder/src/miniaudio/miniaudio.h:3270
drwav_metadata_type_smpl
@ drwav_metadata_type_smpl
Definition: porcupine/demo/c/dr_libs/dr_wav.h:458
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
ma_standard_sample_rate_22050
@ ma_standard_sample_rate_22050
Definition: pvrecorder/src/miniaudio/miniaudio.h:1895
drflac_streaminfo::sampleRate
drflac_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/dr_flac.h:402
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
drflac::_oggbs
void * _oggbs
Definition: porcupine/demo/c/dr_libs/dr_flac.h:751
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
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
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
MA_PROTOCOL_UNAVAILABLE
#define MA_PROTOCOL_UNAVAILABLE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1807
ma_encoding_format
ma_encoding_format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4692
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_384000
@ ma_standard_sample_rate_384000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1907
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
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
ma_backend_custom
@ ma_backend_custom
Definition: pvrecorder/src/miniaudio/miniaudio.h:3135
drwav_acid::reserved2
float reserved2
Definition: porcupine/demo/c/dr_libs/dr_wav.h:641
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
ma_context::pthread_attr_init
ma_proc pthread_attr_init
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3573
drwav::allocationCallbacks
drwav_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/dr_wav.h:820
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
DRWAV_BAD_ADDRESS
#define DRWAV_BAD_ADDRESS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:222
DR_WAVE_FORMAT_IEEE_FLOAT
#define DR_WAVE_FORMAT_IEEE_FLOAT
Definition: porcupine/demo/c/dr_libs/dr_wav.h:256
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
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
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
DRMP3_HDR_GET_BITRATE
#define DRMP3_HDR_GET_BITRATE(h)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59356
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
ma_context_config::pLog
ma_log * pLog
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2141
MA_BAD_MESSAGE
#define MA_BAD_MESSAGE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1798
drflac_frame::subframes
drflac_subframe subframes[8]
Definition: porcupine/demo/c/dr_libs/dr_flac.h:685
ma_cosd
static MA_INLINE double ma_cosd(double x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:818
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_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
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
ma_context::pDeviceInfos
ma_device_info * pDeviceInfos
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3222
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
config
static sai_transceiver_t config
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:75
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
drwav_smpl_loop_type_pingpong
@ drwav_smpl_loop_type_pingpong
Definition: porcupine/demo/c/dr_libs/dr_wav.h:513
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
drmp3_L12_scale_info::scf
float scf[3 *64]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59487
drmp3_seek_origin_current
@ drmp3_seek_origin_current
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:287
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
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
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_CHANNEL_FRONT_CENTER
#define MA_CHANNEL_FRONT_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1713
ma_data_converter_config::formatOut
ma_format formatOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2404
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
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_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
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_dither_mode_triangle
@ ma_dither_mode_triangle
Definition: pvrecorder/src/miniaudio/miniaudio.h:1869
ma_context::pthread_join
ma_proc pthread_join
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3564
DRFLAC_METADATA_BLOCK_TYPE_APPLICATION
#define DRFLAC_METADATA_BLOCK_TYPE_APPLICATION
Definition: porcupine/demo/c/dr_libs/dr_flac.h:343
DRWAV_OUT_OF_RANGE
#define DRWAV_OUT_OF_RANGE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:203
MA_DEVICE_OP_KILL__NULL
#define MA_DEVICE_OP_KILL__NULL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:6221
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
ma_context_config::coreaudio
struct ma_context_config::@106 coreaudio
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
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
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_standard_channel_map_sound4
@ ma_standard_channel_map_sound4
Definition: pvrecorder/src/miniaudio/miniaudio.h:1935
c89atomic_if32::i
c89atomic_uint32 i
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:4120
ma_device_type_duplex
@ ma_device_type_duplex
Definition: pvrecorder/src/miniaudio/miniaudio.h:3241
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
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
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_biquad::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1859
ma_apply_volume_factor_pcm_frames_f32
MA_API void ma_apply_volume_factor_pcm_frames_f32(float *pFrames, ma_uint64 frameCount, ma_uint32 channels, float factor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27984
args
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_opensl_stream_type_alarm
@ ma_opensl_stream_type_alarm
Definition: pvrecorder/src/miniaudio/miniaudio.h:3284
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_encoding_format_vorbis
@ ma_encoding_format_vorbis
Definition: pvrecorder/src/miniaudio/miniaudio.h:6176
drwav_metadata_location_top_level
@ drwav_metadata_location_top_level
Definition: porcupine/demo/c/dr_libs/dr_wav.h:770
ma_thread
pthread_t ma_thread
Definition: pvrecorder/src/miniaudio/miniaudio.h:1983
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
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_format_s16
@ ma_format_s16
Definition: pvrecorder/src/miniaudio/miniaudio.h:1880
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
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
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_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
DRMP3_ZERO_OBJECT
#define DRMP3_ZERO_OBJECT(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61027
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
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
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_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
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_ADDRESS_FAMILY_NOT_SUPPORTED
#define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:241
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
DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT
#define DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT
Definition: porcupine/demo/c/dr_libs/dr_flac.h:345
ma_ios_session_category_option_duck_others
@ ma_ios_session_category_option_duck_others
Definition: pvrecorder/src/miniaudio/miniaudio.h:3268
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_notch_config
struct ma_notch2_config ma_notch_config
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
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_pcm_s16_to_u8
MA_API void ma_pcm_s16_to_u8(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28470
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
ma_aaudio_content_type_movie
@ ma_aaudio_content_type_movie
Definition: pvrecorder/src/miniaudio/miniaudio.h:3325
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
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_device_config::contentType
ma_aaudio_content_type contentType
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2012
header
const std::string header
ma_backend_aaudio
@ ma_backend_aaudio
Definition: pvrecorder/src/miniaudio/miniaudio.h:3132
ma_result
int ma_result
Definition: pvrecorder/src/miniaudio/miniaudio.h:1766
DRMP3_S1
#define DRMP3_S1(k)
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_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
ma_channel_converter::shuffleTable
ma_uint8 shuffleTable[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2384
MA_CHANNEL_FRONT_LEFT_CENTER
#define MA_CHANNEL_FRONT_LEFT_CENTER
Definition: pvrecorder/src/miniaudio/miniaudio.h:1717
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_hpf::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:776
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_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
DRWAV_TRUE
#define DRWAV_TRUE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:164
ma_standard_sample_rate_11025
@ ma_standard_sample_rate_11025
Definition: pvrecorder/src/miniaudio/miniaudio.h:1903
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
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_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
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
DRMP3_MIN
#define DRMP3_MIN(a, b)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59364
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
ma_context::pthread_cond_signal
ma_proc pthread_cond_signal
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3572
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
ma_pcm_rb::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2597
ma_backend_opensl
@ ma_backend_opensl
Definition: pvrecorder/src/miniaudio/miniaudio.h:3133
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_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
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
DRWAV_IS_DIRECTORY
#define DRWAV_IS_DIRECTORY
Definition: porcupine/demo/c/dr_libs/dr_wav.h:213
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
DRWAV_PRIVATE
#define DRWAV_PRIVATE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:193
drmp3_L12_scale_info::total_bands
drmp3_uint8 total_bands
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:59488
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_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_thread_priority_idle
@ ma_thread_priority_idle
Definition: pvrecorder/src/miniaudio/miniaudio.h:1966
drflac_seekpoint::flacFrameOffset
drflac_uint64 flacFrameOffset
Definition: porcupine/demo/c/dr_libs/dr_flac.h:391
drwav_acid::tempo
float tempo
Definition: porcupine/demo/c/dr_libs/dr_wav.h:651
ma_hpf2_config
struct ma_hpf1_config ma_hpf2_config
ma_hpf_config::cutoffFrequency
double cutoffFrequency
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1990
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_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
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
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
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
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
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_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
DRMP3_API
#define DRMP3_API
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:162
DRMP3_BUSY
#define DRMP3_BUSY
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:187
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
ma_context::pthread_mutex_unlock
ma_proc pthread_mutex_unlock
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3568
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
ma_format_s24
@ ma_format_s24
Definition: pvrecorder/src/miniaudio/miniaudio.h:1881
DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
#define DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
Definition: porcupine/demo/c/dr_libs/dr_flac.h:341
drwav_metadata_type_bext
@ drwav_metadata_type_bext
Definition: porcupine/demo/c/dr_libs/dr_wav.h:462
DRWAV_CONNECTION_REFUSED
#define DRWAV_CONNECTION_REFUSED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:246
ma_biquad::r2
ma_biquad_coefficient r2[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1867
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_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
MA_MEMORY_ALREADY_MAPPED
#define MA_MEMORY_ALREADY_MAPPED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1819
drmp3_seek_point::mp3FramesToDiscard
drmp3_uint16 mp3FramesToDiscard
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:294
ma_device::lpfOrder
ma_uint32 lpfOrder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3611
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
MA_ERROR
#define MA_ERROR
Definition: pvrecorder/src/miniaudio/miniaudio.h:1768
MA_CHANNEL_AUX_1
#define MA_CHANNEL_AUX_1
Definition: pvrecorder/src/miniaudio/miniaudio.h:1730
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
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_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__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_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
ma_device_type_loopback
@ ma_device_type_loopback
Definition: pvrecorder/src/miniaudio/miniaudio.h:3242
drflac_streaminfo::minFrameSizeInPCMFrames
drflac_uint32 minFrameSizeInPCMFrames
Definition: porcupine/demo/c/dr_libs/dr_flac.h:400
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
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_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
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_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_hishelf2_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2159
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
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
DRFLAC_METADATA_BLOCK_TYPE_PADDING
#define DRFLAC_METADATA_BLOCK_TYPE_PADDING
Definition: porcupine/demo/c/dr_libs/dr_flac.h:342
DR_WAVE_FORMAT_EXTENSIBLE
#define DR_WAVE_FORMAT_EXTENSIBLE
Definition: porcupine/demo/c/dr_libs/dr_wav.h:260
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_pcm_s16_to_f32
MA_API void ma_pcm_s16_to_f32(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28677
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
drwav_metadata_type_acid
@ drwav_metadata_type_acid
Definition: porcupine/demo/c/dr_libs/dr_wav.h:461
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
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_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
DRMP3_TOO_MANY_LINKS
#define DRMP3_TOO_MANY_LINKS
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:196
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_device_descriptor::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2048
ma_device::stopEvent
ma_event stopEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3596
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
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
DRMP3_NO_MESSAGE
#define DRMP3_NO_MESSAGE
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:198
drwav_smpl::sampleLoopCount
drwav_uint32 sampleLoopCount
Definition: porcupine/demo/c/dr_libs/dr_wav.h:558
ma_context_config::allocationCallbacks
ma_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3165
drflac_seek_proc
drflac_bool32(* drflac_seek_proc)(void *pUserData, int offset, drflac_seek_origin origin)
Definition: porcupine/demo/c/dr_libs/dr_flac.h:541
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_encoder_write_proc
size_t(* ma_encoder_write_proc)(ma_encoder *pEncoder, const void *pBufferIn, size_t bytesToWrite)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6397
ma_backend
ma_backend
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2793
DRWAV_NOT_IMPLEMENTED
#define DRWAV_NOT_IMPLEMENTED
Definition: porcupine/demo/c/dr_libs/dr_wav.h:227
drwav_bool8
drwav_uint8 drwav_bool8
Definition: porcupine/demo/c/dr_libs/dr_wav.h:162
ma_event::value
ma_uint32 value
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2885
ma_pcm_s32_to_s24
MA_API void ma_pcm_s32_to_s24(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29330
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
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_CHANNEL_AUX_12
#define MA_CHANNEL_AUX_12
Definition: pvrecorder/src/miniaudio/miniaudio.h:1741
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_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
MA_FALSE
#define MA_FALSE
Definition: pvrecorder/src/miniaudio/miniaudio.h:1584
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
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_IS_DIRECTORY
#define MA_IS_DIRECTORY
Definition: pvrecorder/src/miniaudio/miniaudio.h:1782
ma_device::wakeupEvent
ma_event wakeupEvent
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3594
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_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
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
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
drflac::pSeekpoints
drflac_seekpoint * pSeekpoints
Definition: porcupine/demo/c/dr_libs/dr_flac.h:748
DR_WAVE_FORMAT_MULAW
#define DR_WAVE_FORMAT_MULAW
Definition: porcupine/demo/c/dr_libs/dr_wav.h:258
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
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
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
DRWAV_INVALID_ARGS
#define DRWAV_INVALID_ARGS
Definition: porcupine/demo/c/dr_libs/dr_wav.h:200
ma_noise_type
ma_noise_type
Definition: pvrecorder/src/miniaudio/miniaudio.h:6479
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_CHANNEL_AUX_13
#define MA_CHANNEL_AUX_13
Definition: pvrecorder/src/miniaudio/miniaudio.h:1742
drflac_int32
signed int drflac_int32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:245
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_metadata_type_list_info_software
@ drwav_metadata_type_list_info_software
Definition: porcupine/demo/c/dr_libs/dr_wav.h:475
ma_device_info::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1932
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
MA_TAU_D
#define MA_TAU_D
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:590
ma_pcm_f32_to_s16
MA_API void ma_pcm_f32_to_s16(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:29989
ma_context_config::sessionCategory
ma_ios_session_category sessionCategory
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3178
ma_zero_pcm_frames
static MA_INLINE void ma_zero_pcm_frames(void *p, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
Definition: pvrecorder/src/miniaudio/miniaudio.h:5917
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
DRWAV_ERROR
#define DRWAV_ERROR
Definition: porcupine/demo/c/dr_libs/dr_wav.h:199
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
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__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
drflac_metadata::pRawData
const void * pRawData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:422
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_data_source_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4515
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
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_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
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_decoder::file
ma_vfs_file file
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4788
ma_context::deviceInfoLock
ma_mutex deviceInfoLock
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3218
ma_sleep
static void ma_sleep(ma_uint32 milliseconds)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:522
ma_aaudio_input_preset_unprocessed
@ ma_aaudio_input_preset_unprocessed
Definition: pvrecorder/src/miniaudio/miniaudio.h:3337
ma_format_f32
@ ma_format_f32
Definition: pvrecorder/src/miniaudio/miniaudio.h:1883
ma_aaudio_input_preset_default
@ ma_aaudio_input_preset_default
Definition: pvrecorder/src/miniaudio/miniaudio.h:3334
MA_CHANNEL_AUX_11
#define MA_CHANNEL_AUX_11
Definition: pvrecorder/src/miniaudio/miniaudio.h:1740
drmp3dec::qmf_state
float qmf_state[15 *2 *32]
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:264
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_copy_and_apply_volume_factor_pcm_frames
MA_API void ma_copy_and_apply_volume_factor_pcm_frames(void *pFramesOut, const void *pFramesIn, 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_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
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
drwav_metadata_type_inst
@ drwav_metadata_type_inst
Definition: porcupine/demo/c/dr_libs/dr_wav.h:459
ma_resampler_config::speex
struct ma_resampler_config::@76 speex
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_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
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
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_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_loshelf_config
struct ma_loshelf2_config ma_loshelf_config
MA_CHANNEL_AUX_25
#define MA_CHANNEL_AUX_25
Definition: pvrecorder/src/miniaudio/miniaudio.h:1754
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_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
drmp3::pSeekPoints
drmp3_seek_point * pSeekPoints
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:357
DRMP3_VERSION_STRING
#define DRMP3_VERSION_STRING
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:99
ma_standard_sample_rate_8000
@ ma_standard_sample_rate_8000
Definition: pvrecorder/src/miniaudio/miniaudio.h:1904
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_encoder::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5332
DRMP3_SIZE_MAX
#define DRMP3_SIZE_MAX
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:61007
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
ma_device::isStarted
ma_bool32 isStarted
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3847
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
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
ma_channel
ma_uint8 ma_channel
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1600
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_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_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
ma_standard_channel_map_rfc3551
@ ma_standard_channel_map_rfc3551
Definition: pvrecorder/src/miniaudio/miniaudio.h:1932
MA_DEFAULT_SAMPLE_RATE
#define MA_DEFAULT_SAMPLE_RATE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:606
MA_SIMD_ALIGNMENT
#define MA_SIMD_ALIGNMENT
Definition: pvrecorder/src/miniaudio/miniaudio.h:1658
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_PROTOCOL_NOT_SUPPORTED
#define MA_PROTOCOL_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1808
ma_pcm_u8_to_s16
MA_API void ma_pcm_u8_to_s16(void *pOut, const void *pIn, ma_uint64 count, ma_dither_mode ditherMode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:28110
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
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
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
drwav_smpl::smpteFormat
drwav_uint32 smpteFormat
Definition: porcupine/demo/c/dr_libs/dr_wav.h:554
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_result
drflac_int32 drflac_result
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51356
ma_waveform::time
double time
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5377
DR_WAVE_FORMAT_ALAW
#define DR_WAVE_FORMAT_ALAW
Definition: porcupine/demo/c/dr_libs/dr_wav.h:257
drflac_cuesheet_track_iterator::pRunningData
const char * pRunningData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:1280
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
ma_audio_buffer_ref::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4566
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__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
drwav_list_label_or_note::pString
char * pString
Definition: porcupine/demo/c/dr_libs/dr_wav.h:670
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_mutex
pthread_mutex_t ma_mutex
Definition: pvrecorder/src/miniaudio/miniaudio.h:1990
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
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
DRMP3_CONNECTION_REFUSED
#define DRMP3_CONNECTION_REFUSED
Definition: porcupine/demo/c/dr_libs/dr_mp3.h:216
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
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
MA_SHARE_MODE_NOT_SUPPORTED
#define MA_SHARE_MODE_NOT_SUPPORTED
Definition: pvrecorder/src/miniaudio/miniaudio.h:1824
drwav::memoryStreamWrite
drwav__memory_stream_write memoryStreamWrite
Definition: porcupine/demo/c/dr_libs/dr_wav.h:879
drwav_metadata_type_list_info_copyright
@ drwav_metadata_type_list_info_copyright
Definition: porcupine/demo/c/dr_libs/dr_wav.h:476
ma_device::internalPeriodSizeInFrames
ma_uint32 internalPeriodSizeInFrames
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3632
DRWAV_VERSION_STRING
#define DRWAV_VERSION_STRING
Definition: porcupine/demo/c/dr_libs/dr_wav.h:129
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_biquad_coefficient
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1837
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_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
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
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
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
DR_WAVE_FORMAT_ADPCM
#define DR_WAVE_FORMAT_ADPCM
Definition: porcupine/demo/c/dr_libs/dr_wav.h:255
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
DRFLAC_CONNECTION_RESET
#define DRFLAC_CONNECTION_RESET
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51402
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_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
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
MA_ZERO_MEMORY
#define MA_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:746
MA_OUT_OF_MEMORY
#define MA_OUT_OF_MEMORY
Definition: pvrecorder/src/miniaudio/miniaudio.h:1771
drwav__memory_stream_write::currentWritePos
size_t currentWritePos
Definition: porcupine/demo/c/dr_libs/dr_wav.h:432
MA_CHANNEL_AUX_30
#define MA_CHANNEL_AUX_30
Definition: pvrecorder/src/miniaudio/miniaudio.h:1759
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_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
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_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
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
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_converter::channelsOut
ma_uint32 channelsOut
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2371
ma_spinlock
ma_uint32 ma_spinlock
Definition: pvrecorder/src/miniaudio/miniaudio.h:1977
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_opensl_recording_preset_voice_recognition
@ ma_opensl_recording_preset_voice_recognition
Definition: pvrecorder/src/miniaudio/miniaudio.h:3294
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
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
drflac_allocation_callbacks::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/dr_flac.h:566
ma_context_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3160
ma_standard_channel_map_microsoft
@ ma_standard_channel_map_microsoft
Definition: pvrecorder/src/miniaudio/miniaudio.h:1930
ma_encoder_uninit_proc
void(* ma_encoder_uninit_proc)(ma_encoder *pEncoder)
Definition: pvrecorder/src/miniaudio/miniaudio.h:6400
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
ma_loshelf2_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2130
ma_channel
ma_uint8 ma_channel
Definition: pvrecorder/src/miniaudio/miniaudio.h:1708
drflac::allocationCallbacks
drflac_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/dr_flac.h:697
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


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